aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/game/Accounts/RBAC.h6
-rw-r--r--src/server/game/Achievements/AchievementMgr.cpp3464
-rw-r--r--src/server/game/Achievements/AchievementMgr.h551
-rw-r--r--src/server/game/Achievements/CriteriaHandler.cpp2218
-rw-r--r--src/server/game/Achievements/CriteriaHandler.h393
-rw-r--r--src/server/game/AuctionHouse/AuctionHouseMgr.cpp6
-rw-r--r--src/server/game/BattlePets/BattlePetMgr.cpp2
-rw-r--r--src/server/game/Battlefield/Zones/BattlefieldWG.cpp4
-rw-r--r--src/server/game/Battlegrounds/Arena.cpp8
-rw-r--r--src/server/game/Battlegrounds/ArenaTeam.cpp4
-rw-r--r--src/server/game/Battlegrounds/Battleground.cpp32
-rw-r--r--src/server/game/Battlegrounds/Battleground.h2
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp6
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp10
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp4
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp8
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp10
-rw-r--r--src/server/game/Chat/ChatLink.cpp2
-rw-r--r--src/server/game/Conditions/ConditionMgr.cpp8
-rw-r--r--src/server/game/Conditions/DisableMgr.cpp12
-rw-r--r--src/server/game/Conditions/DisableMgr.h2
-rw-r--r--src/server/game/DataStores/DB2Structure.h108
-rw-r--r--src/server/game/DataStores/DBCEnums.h537
-rw-r--r--src/server/game/DungeonFinding/LFGMgr.cpp2
-rw-r--r--src/server/game/Entities/GameObject/GameObject.cpp2
-rw-r--r--src/server/game/Entities/Player/KillRewarder.cpp6
-rw-r--r--src/server/game/Entities/Player/Player.cpp136
-rw-r--r--src/server/game/Entities/Player/Player.h12
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp24
-rw-r--r--src/server/game/Garrison/Garrison.cpp4
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp10
-rw-r--r--src/server/game/Groups/Group.cpp6
-rw-r--r--src/server/game/Guilds/Guild.cpp12
-rw-r--r--src/server/game/Guilds/Guild.h8
-rw-r--r--src/server/game/Guilds/GuildMgr.cpp2
-rw-r--r--src/server/game/Handlers/AuctionHouseHandler.cpp8
-rw-r--r--src/server/game/Handlers/BankHandler.cpp2
-rw-r--r--src/server/game/Handlers/CharacterHandler.cpp10
-rw-r--r--src/server/game/Handlers/ChatHandler.cpp2
-rw-r--r--src/server/game/Handlers/GroupHandler.cpp4
-rw-r--r--src/server/game/Handlers/ItemHandler.cpp4
-rw-r--r--src/server/game/Handlers/LootHandler.cpp10
-rw-r--r--src/server/game/Handlers/MailHandler.cpp2
-rw-r--r--src/server/game/Handlers/QuestHandler.cpp4
-rw-r--r--src/server/game/Handlers/SpellHandler.cpp2
-rw-r--r--src/server/game/Instances/InstanceScript.cpp12
-rw-r--r--src/server/game/Instances/InstanceScript.h6
-rw-r--r--src/server/game/Maps/MapManager.cpp2
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp2
-rw-r--r--src/server/game/Reputation/ReputationMgr.cpp10
-rw-r--r--src/server/game/Spells/Spell.cpp16
-rw-r--r--src/server/game/Spells/SpellEffects.cpp2
-rw-r--r--src/server/game/Tools/CharacterDatabaseCleaner.cpp4
-rw-r--r--src/server/game/World/World.cpp12
-rw-r--r--src/server/scripts/Commands/cs_achievement.cpp2
-rw-r--r--src/server/scripts/Commands/cs_disable.cpp64
-rw-r--r--src/server/scripts/Commands/cs_reload.cpp12
-rw-r--r--src/server/scripts/Commands/cs_reset.cpp4
-rw-r--r--src/server/scripts/Kalimdor/HallsOfOrigination/boss_anraphet.cpp2
-rw-r--r--src/server/scripts/Kalimdor/OnyxiasLair/boss_onyxia.cpp4
-rw-r--r--src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_herald_volazj.cpp4
-rw-r--r--src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_anubarak.cpp4
-rw-r--r--src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp4
-rw-r--r--src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/instance_trial_of_the_crusader.cpp6
-rw-r--r--src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp4
-rw-r--r--src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/instance_halls_of_reflection.cpp2
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp2
-rw-r--r--src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.cpp2
-rw-r--r--src/server/scripts/Northrend/Naxxramas/boss_four_horsemen.cpp2
-rw-r--r--src/server/scripts/Northrend/Naxxramas/boss_patchwerk.cpp4
-rw-r--r--src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp4
-rw-r--r--src/server/scripts/Northrend/Nexus/Oculus/boss_drakos.cpp2
-rw-r--r--src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_loken.cpp4
-rw-r--r--src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_maiden_of_grief.cpp4
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp4
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_ignis.cpp4
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_kologarn.cpp2
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_xt002.cpp4
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp4
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp4
-rw-r--r--src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp4
-rw-r--r--src/server/worldserver/worldserver.conf.dist3
82 files changed, 4010 insertions, 3890 deletions
diff --git a/src/server/game/Accounts/RBAC.h b/src/server/game/Accounts/RBAC.h
index 07ad2a2fd4b..2b85d922657 100644
--- a/src/server/game/Accounts/RBAC.h
+++ b/src/server/game/Accounts/RBAC.h
@@ -254,7 +254,7 @@ enum RBACPermissions
RBAC_PERM_COMMAND_DESERTER_INSTANCE_REMOVE = 347,
RBAC_PERM_COMMAND_DISABLE = 348,
RBAC_PERM_COMMAND_DISABLE_ADD = 349,
- RBAC_PERM_COMMAND_DISABLE_ADD_ACHIEVEMENT_CRITERIA = 350,
+ RBAC_PERM_COMMAND_DISABLE_ADD_CRITERIA = 350,
RBAC_PERM_COMMAND_DISABLE_ADD_BATTLEGROUND = 351,
RBAC_PERM_COMMAND_DISABLE_ADD_MAP = 352,
RBAC_PERM_COMMAND_DISABLE_ADD_MMAP = 353,
@@ -263,7 +263,7 @@ enum RBACPermissions
RBAC_PERM_COMMAND_DISABLE_ADD_SPELL = 356,
RBAC_PERM_COMMAND_DISABLE_ADD_VMAP = 357,
RBAC_PERM_COMMAND_DISABLE_REMOVE = 358,
- RBAC_PERM_COMMAND_DISABLE_REMOVE_ACHIEVEMENT_CRITERIA = 359,
+ RBAC_PERM_COMMAND_DISABLE_REMOVE_CRITERIA = 359,
RBAC_PERM_COMMAND_DISABLE_REMOVE_BATTLEGROUND = 360,
RBAC_PERM_COMMAND_DISABLE_REMOVE_MAP = 361,
RBAC_PERM_COMMAND_DISABLE_REMOVE_MMAP = 362,
@@ -513,7 +513,7 @@ enum RBACPermissions
RBAC_PERM_COMMAND_QUEST_REWARD = 606,
RBAC_PERM_COMMAND_RELOAD = 607,
RBAC_PERM_COMMAND_RELOAD_ACCESS_REQUIREMENT = 608,
- RBAC_PERM_COMMAND_RELOAD_ACHIEVEMENT_CRITERIA_DATA = 609,
+ RBAC_PERM_COMMAND_RELOAD_CRITERIA_DATA = 609,
RBAC_PERM_COMMAND_RELOAD_ACHIEVEMENT_REWARD = 610,
RBAC_PERM_COMMAND_RELOAD_ALL = 611,
RBAC_PERM_COMMAND_RELOAD_ALL_ACHIEVEMENT = 612,
diff --git a/src/server/game/Achievements/AchievementMgr.cpp b/src/server/game/Achievements/AchievementMgr.cpp
index f15476d4071..642c21e3ff1 100644
--- a/src/server/game/Achievements/AchievementMgr.cpp
+++ b/src/server/game/Achievements/AchievementMgr.cpp
@@ -18,644 +18,221 @@
#include "AchievementMgr.h"
#include "AchievementPackets.h"
-#include "ArenaTeam.h"
-#include "ArenaTeamMgr.h"
-#include "Battleground.h"
#include "CellImpl.h"
#include "ChatTextBuilder.h"
-#include "Common.h"
-#include "DatabaseEnv.h"
-#include "DBCEnums.h"
-#include "DisableMgr.h"
-#include "GameEventMgr.h"
-#include "Garrison.h"
#include "GridNotifiersImpl.h"
#include "Group.h"
-#include "Guild.h"
#include "GuildMgr.h"
-#include "InstanceScript.h"
#include "Language.h"
-#include "Map.h"
-#include "MapManager.h"
#include "ObjectMgr.h"
-#include "Player.h"
-#include "ReputationMgr.h"
-#include "ScriptMgr.h"
-#include "SpellMgr.h"
-#include "World.h"
-#include "WorldPacket.h"
-
-bool AchievementCriteriaData::IsValid(AchievementCriteria const* criteria)
+
+struct VisibleAchievementCheck
{
- if (dataType >= MAX_ACHIEVEMENT_CRITERIA_DATA_TYPE)
+ AchievementEntry const* operator()(std::pair<uint32, CompletedAchievementData> const& val)
{
- TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` for criteria (Entry: %u) contains a wrong data type (%u), ignored.", criteria->ID, dataType);
- return false;
+ AchievementEntry const* achievement = sAchievementStore.LookupEntry(val.first);
+ if (achievement && !(achievement->Flags & ACHIEVEMENT_FLAG_HIDDEN))
+ return achievement;
+ return nullptr;
}
+};
- switch (criteria->Entry->Type)
- {
- case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE:
- case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE:
- case ACHIEVEMENT_CRITERIA_TYPE_WIN_BG:
- case ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING:
- case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST: // only hardcoded list
- case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL:
- case ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA:
- case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE:
- case ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL:
- case ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL:
- case ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE:
- case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2:
- case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET:
- case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2:
- case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM:
- case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT:
- case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT:
- case ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE:
- case ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL:
- case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST: // only Children's Week achievements
- case ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM: // only Children's Week achievements
- case ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS:
- case ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL:
- case ACHIEVEMENT_CRITERIA_TYPE_ON_LOGIN:
- break;
- default:
- if (dataType != ACHIEVEMENT_CRITERIA_DATA_TYPE_SCRIPT)
- {
- TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` contains data for a non-supported criteria type (Entry: %u Type: %u), ignored.", criteria->ID, criteria->Entry->Type);
- return false;
- }
- break;
- }
+AchievementMgr::AchievementMgr() : _achievementPoints(0) { }
- switch (dataType)
- {
- case ACHIEVEMENT_CRITERIA_DATA_TYPE_NONE:
- case ACHIEVEMENT_CRITERIA_DATA_TYPE_INSTANCE_SCRIPT:
- return true;
- case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_CREATURE:
- if (!creature.id || !sObjectMgr->GetCreatureTemplate(creature.id))
- {
- TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_CREATURE (%u) contains a non-existing creature id in value1 (%u), ignored.",
- criteria->ID, criteria->Entry->Type, dataType, creature.id);
- return false;
- }
- return true;
- case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_CLASS_RACE:
- if (!classRace.class_id && !classRace.race_id)
- {
- TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_CLASS_RACE (%u) must not have 0 in either value field, ignored.",
- criteria->ID, criteria->Entry->Type, dataType);
- return false;
- }
- if (classRace.class_id && ((1 << (classRace.class_id-1)) & CLASSMASK_ALL_PLAYABLE) == 0)
- {
- TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_CLASS_RACE (%u) contains a non-existing class in value1 (%u), ignored.",
- criteria->ID, criteria->Entry->Type, dataType, classRace.class_id);
- return false;
- }
- if (classRace.race_id && ((1 << (classRace.race_id-1)) & RACEMASK_ALL_PLAYABLE) == 0)
- {
- TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_CLASS_RACE (%u) contains a non-existing race in value2 (%u), ignored.",
- criteria->ID, criteria->Entry->Type, dataType, classRace.race_id);
- return false;
- }
- return true;
- case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_LESS_HEALTH:
- if (health.percent < 1 || health.percent > 100)
- {
- TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_PLAYER_LESS_HEALTH (%u) contains a wrong percent value in value1 (%u), ignored.",
- criteria->ID, criteria->Entry->Type, dataType, health.percent);
- return false;
- }
- return true;
- case ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA:
- case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_AURA:
- {
- SpellInfo const* spellEntry = sSpellMgr->GetSpellInfo(aura.spell_id);
- if (!spellEntry)
- {
- TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type %s (%u) contains a wrong spell id in value1 (%u), ignored.",
- criteria->ID, criteria->Entry->Type, (dataType == ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA ? "ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA" : "ACHIEVEMENT_CRITERIA_DATA_TYPE_T_AURA"), dataType, aura.spell_id);
- return false;
- }
- SpellEffectInfo const* effect = spellEntry->GetEffect(DIFFICULTY_NONE, aura.effect_idx);
- if (!effect)
- {
- TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type %s (%u) contains a wrong spell effect index in value2 (%u), ignored.",
- criteria->ID, criteria->Entry->Type, (dataType == ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA ? "ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA" : "ACHIEVEMENT_CRITERIA_DATA_TYPE_T_AURA"), dataType, aura.effect_idx);
- return false;
- }
- if (!effect->ApplyAuraName)
- {
- TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type %s (%u) contains a non-aura spell effect (ID: %u Effect: %u), ignored.",
- criteria->ID, criteria->Entry->Type, (dataType == ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA ? "ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA" : "ACHIEVEMENT_CRITERIA_DATA_TYPE_T_AURA"), dataType, aura.spell_id, aura.effect_idx);
- return false;
- }
- return true;
- }
- case ACHIEVEMENT_CRITERIA_DATA_TYPE_VALUE:
- if (value.compType >= COMP_TYPE_MAX)
- {
- TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_VALUE (%u) contains a wrong ComparisionType in value2 (%u), ignored.",
- criteria->ID, criteria->Entry->Type, dataType, value.compType);
- return false;
- }
- return true;
- case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_LEVEL:
- if (level.minlevel > STRONG_MAX_LEVEL)
- {
- TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_T_LEVEL (%u) contains a wrong minlevel in value1 (%u), ignored.",
- criteria->ID, criteria->Entry->Type, dataType, level.minlevel);
- return false;
- }
- return true;
- case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_GENDER:
- if (gender.gender > GENDER_NONE)
- {
- TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_T_GENDER (%u) contains a wrong gender value in value1 (%u), ignored.",
- criteria->ID, criteria->Entry->Type, dataType, gender.gender);
- return false;
- }
- return true;
- case ACHIEVEMENT_CRITERIA_DATA_TYPE_SCRIPT:
- if (!ScriptId)
- {
- TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_SCRIPT (%u) does not have a ScriptName set, ignored.",
- criteria->ID, criteria->Entry->Type, dataType);
- return false;
- }
- return true;
- case ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_PLAYER_COUNT:
- if (map_players.maxcount <= 0)
- {
- TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_PLAYER_COUNT (%u) contains a wrong max players count in value1 (%u), ignored.",
- criteria->ID, criteria->Entry->Type, dataType, map_players.maxcount);
- return false;
- }
- return true;
- case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_TEAM:
- if (team.team != ALLIANCE && team.team != HORDE)
- {
- TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_T_TEAM (%u) contains an unknown team value in value1 (%u), ignored.",
- criteria->ID, criteria->Entry->Type, dataType, team.team);
- return false;
- }
- return true;
- case ACHIEVEMENT_CRITERIA_DATA_TYPE_S_DRUNK:
- if (drunk.state >= MAX_DRUNKEN)
- {
- TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_S_DRUNK (%u) contains an unknown drunken state value in value1 (%u), ignored.",
- criteria->ID, criteria->Entry->Type, dataType, drunk.state);
- return false;
- }
- return true;
- case ACHIEVEMENT_CRITERIA_DATA_TYPE_HOLIDAY:
- if (!sHolidaysStore.LookupEntry(holiday.id))
- {
- TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_HOLIDAY (%u) contains an unknown holiday entry in value1 (%u), ignored.",
- criteria->ID, criteria->Entry->Type, dataType, holiday.id);
- return false;
- }
- return true;
- case ACHIEVEMENT_CRITERIA_DATA_TYPE_GAME_EVENT:
- {
- GameEventMgr::GameEventDataMap const& events = sGameEventMgr->GetEventMap();
- if (game_event.id < 1 || game_event.id >= events.size())
- {
- TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_GAME_EVENT (%u) has unknown game_event in value1 (%u), ignored.",
- criteria->ID, criteria->Entry->Type, dataType, game_event.id);
- return false;
- }
- return true;
- }
- case ACHIEVEMENT_CRITERIA_DATA_TYPE_BG_LOSS_TEAM_SCORE:
- return true; // not check correctness node indexes
- case ACHIEVEMENT_CRITERIA_DATA_TYPE_S_EQUIPED_ITEM:
- if (equipped_item.item_quality >= MAX_ITEM_QUALITY)
- {
- TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_S_EQUIPED_ITEM (%u) contains an unknown quality state value in value1 (%u), ignored.",
- criteria->ID, criteria->Entry->Type, dataType, equipped_item.item_quality);
- return false;
- }
- return true;
- case ACHIEVEMENT_CRITERIA_DATA_TYPE_S_PLAYER_CLASS_RACE:
- if (!classRace.class_id && !classRace.race_id)
- {
- TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_S_PLAYER_CLASS_RACE (%u) should not have 0 in either value field. Ignored.",
- criteria->ID, criteria->Entry->Type, dataType);
- return false;
- }
- if (classRace.class_id && ((1 << (classRace.class_id-1)) & CLASSMASK_ALL_PLAYABLE) == 0)
- {
- TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_S_PLAYER_CLASS_RACE (%u) contains a non-existing class entry in value1 (%u), ignored.",
- criteria->ID, criteria->Entry->Type, dataType, classRace.class_id);
- return false;
- }
- if (classRace.race_id && ((1 << (classRace.race_id-1)) & RACEMASK_ALL_PLAYABLE) == 0)
- {
- TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_S_PLAYER_CLASS_RACE (%u) contains a non-existing race entry in value2 (%u), ignored.",
- criteria->ID, criteria->Entry->Type, dataType, classRace.race_id);
- return false;
- }
- return true;
- case ACHIEVEMENT_CRITERIA_DATA_TYPE_S_KNOWN_TITLE:
- if (!sCharTitlesStore.LookupEntry(known_title.title_id))
- {
- TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_S_KNOWN_TITLE (%u) contains an unknown title_id in value1 (%u), ignore.",
- criteria->ID, criteria->Entry->Type, dataType, known_title.title_id);
- return false;
- }
- return true;
- default:
- TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` (Entry: %u Type: %u) contains data of a non-supported data type (%u), ignored.", criteria->ID, criteria->Entry->Type, dataType);
- return false;
- }
-}
+AchievementMgr::~AchievementMgr() { }
-bool AchievementCriteriaData::Meets(uint32 criteria_id, Player const* source, Unit const* target, uint32 miscValue1 /*= 0*/) const
+/**
+* called at player login. The player might have fulfilled some achievements when the achievement system wasn't working yet
+*/
+void AchievementMgr::CheckAllAchievementCriteria(Player* referencePlayer)
{
- switch (dataType)
- {
- case ACHIEVEMENT_CRITERIA_DATA_TYPE_NONE:
- return true;
- case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_CREATURE:
- if (!target || target->GetTypeId() != TYPEID_UNIT)
- return false;
- return target->GetEntry() == creature.id;
- case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_CLASS_RACE:
- if (!target || target->GetTypeId() != TYPEID_PLAYER)
- return false;
- if (classRace.class_id && classRace.class_id != target->ToPlayer()->getClass())
- return false;
- if (classRace.race_id && classRace.race_id != target->ToPlayer()->getRace())
- return false;
- return true;
- case ACHIEVEMENT_CRITERIA_DATA_TYPE_S_PLAYER_CLASS_RACE:
- if (source->GetTypeId() != TYPEID_PLAYER)
- return false;
- if (classRace.class_id && classRace.class_id != source->ToPlayer()->getClass())
- return false;
- if (classRace.race_id && classRace.race_id != source->ToPlayer()->getRace())
- return false;
- return true;
- case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_LESS_HEALTH:
- if (!target || target->GetTypeId() != TYPEID_PLAYER)
- return false;
- return !target->HealthAbovePct(health.percent);
- case ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA:
- return source->HasAuraEffect(aura.spell_id, aura.effect_idx);
- case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_AURA:
- return target && target->HasAuraEffect(aura.spell_id, aura.effect_idx);
- case ACHIEVEMENT_CRITERIA_DATA_TYPE_VALUE:
- return CompareValues(ComparisionType(value.compType), miscValue1, value.value);
- case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_LEVEL:
- if (!target)
- return false;
- return target->getLevel() >= level.minlevel;
- case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_GENDER:
- if (!target)
- return false;
- return target->getGender() == gender.gender;
- case ACHIEVEMENT_CRITERIA_DATA_TYPE_SCRIPT:
- return sScriptMgr->OnCriteriaCheck(ScriptId, const_cast<Player*>(source), const_cast<Unit*>(target));
- case ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_PLAYER_COUNT:
- return source->GetMap()->GetPlayersCountExceptGMs() <= map_players.maxcount;
- case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_TEAM:
- if (!target || target->GetTypeId() != TYPEID_PLAYER)
- return false;
- return target->ToPlayer()->GetTeam() == team.team;
- case ACHIEVEMENT_CRITERIA_DATA_TYPE_S_DRUNK:
- return Player::GetDrunkenstateByValue(source->GetDrunkValue()) >= DrunkenState(drunk.state);
- case ACHIEVEMENT_CRITERIA_DATA_TYPE_HOLIDAY:
- return IsHolidayActive(HolidayIds(holiday.id));
- case ACHIEVEMENT_CRITERIA_DATA_TYPE_GAME_EVENT:
- return IsEventActive(game_event.id);
- case ACHIEVEMENT_CRITERIA_DATA_TYPE_BG_LOSS_TEAM_SCORE:
- {
- Battleground* bg = source->GetBattleground();
- if (!bg)
- return false;
-
- uint32 score = bg->GetTeamScore(source->GetTeamId() == TEAM_ALLIANCE ? TEAM_HORDE : TEAM_ALLIANCE);
- return score >= bg_loss_team_score.min_score && score <= bg_loss_team_score.max_score;
- }
- case ACHIEVEMENT_CRITERIA_DATA_TYPE_INSTANCE_SCRIPT:
- {
- if (!source->IsInWorld())
- return false;
- Map* map = source->GetMap();
- if (!map->IsDungeon())
- {
- TC_LOG_ERROR("achievement", "Achievement system call ACHIEVEMENT_CRITERIA_DATA_TYPE_INSTANCE_SCRIPT (%u) for achievement criteria %u in a non-dungeon/non-raid map %u",
- dataType, criteria_id, map->GetId());
- return false;
- }
- InstanceScript* instance = map->ToInstanceMap()->GetInstanceScript();
- if (!instance)
- {
- TC_LOG_ERROR("achievement", "Achievement system call ACHIEVEMENT_CRITERIA_DATA_TYPE_INSTANCE_SCRIPT (%u) for achievement criteria %u in map %u, but the map does not have an instance script.",
- dataType, criteria_id, map->GetId());
- return false;
- }
- return instance->CheckAchievementCriteriaMeet(criteria_id, source, target, miscValue1);
- }
- case ACHIEVEMENT_CRITERIA_DATA_TYPE_S_EQUIPED_ITEM:
- {
- ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(miscValue1);
- if (!pProto)
- return false;
- return pProto->GetBaseItemLevel() >= equipped_item.item_level && pProto->GetQuality() >= equipped_item.item_quality;
- }
- case ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_ID:
- return source->GetMapId() == map_id.mapId;
- case ACHIEVEMENT_CRITERIA_DATA_TYPE_S_KNOWN_TITLE:
- {
- if (CharTitlesEntry const* titleInfo = sCharTitlesStore.LookupEntry(known_title.title_id))
- return source && source->HasTitle(titleInfo->MaskID);
-
- return false;
- }
- default:
- break;
- }
- return false;
+ // suppress sending packets
+ for (uint32 i = 0; i < CRITERIA_TYPE_TOTAL; ++i)
+ UpdateCriteria(CriteriaTypes(i), 0, 0, 0, NULL, referencePlayer);
}
-bool AchievementCriteriaDataSet::Meets(Player const* source, Unit const* target, uint32 miscValue /*= 0*/) const
+bool AchievementMgr::HasAchieved(uint32 achievementId) const
{
- for (AchievementCriteriaData const& data : storage)
- if (!data.Meets(criteria_id, source, target, miscValue))
- return false;
-
- return true;
+ return _completedAchievements.find(achievementId) != _completedAchievements.end();
}
-template<class T>
-AchievementMgr<T>::AchievementMgr(T* owner): _owner(owner), _achievementPoints(0) { }
-
-template<class T>
-AchievementMgr<T>::~AchievementMgr() { }
-
-template<class T>
-void AchievementMgr<T>::SendPacket(WorldPacket const* /*data*/) const { }
-
-template<>
-void AchievementMgr<Guild>::SendPacket(WorldPacket const* data) const
+uint32 AchievementMgr::GetAchievementPoints() const
{
- GetOwner()->BroadcastPacket(data);
+ return _achievementPoints;
}
-template<>
-void AchievementMgr<Player>::SendPacket(WorldPacket const* data) const
+bool AchievementMgr::CanUpdateCriteriaTree(Criteria const* criteria, CriteriaTree const* tree, Player* referencePlayer) const
{
- GetOwner()->GetSession()->SendPacket(data);
+ if (HasAchieved(tree->Achievement->ID))
+ {
+ TC_LOG_TRACE("criteria.achievement", "AchievementMgr::CanUpdateCriteriaTree: (Id: %u Type %s Achievement %u) Achievement already earned",
+ criteria->ID, CriteriaMgr::GetCriteriaTypeString(criteria->Entry->Type), tree->Achievement->ID);
+ return false;
+ }
+
+ if (tree->Achievement->MapID != -1 && referencePlayer->GetMapId() != uint32(tree->Achievement->MapID))
+ {
+ TC_LOG_TRACE("criteria.achievement", "AchievementMgr::CanUpdateCriteriaTree: (Id: %u Type %s Achievement %u) Wrong map",
+ criteria->ID, CriteriaMgr::GetCriteriaTypeString(criteria->Entry->Type), tree->Achievement->ID);
+ return false;
+ }
+
+ if ((tree->Achievement->Faction == ACHIEVEMENT_FACTION_HORDE && referencePlayer->GetTeam() != HORDE) ||
+ (tree->Achievement->Faction == ACHIEVEMENT_FACTION_ALLIANCE && referencePlayer->GetTeam() != ALLIANCE))
+ {
+ TC_LOG_TRACE("criteria.achievement", "AchievementMgr::CanUpdateCriteriaTree: (Id: %u Type %s Achievement %u) Wrong faction",
+ criteria->ID, CriteriaMgr::GetCriteriaTypeString(criteria->Entry->Type), tree->Achievement->ID);
+ return false;
+ }
+
+ return true;
}
-template<class T>
-void AchievementMgr<T>::RemoveCriteriaProgress(AchievementCriteria const* entry)
+bool AchievementMgr::CanCompleteCriteriaTree(CriteriaTree const* tree)
{
- if (!entry)
- return;
+ AchievementEntry const* achievement = tree->Achievement;
+ if (!achievement)
+ return false;
- CriteriaProgressMap::iterator criteriaProgress = m_criteriaProgress.find(entry->ID);
- if (criteriaProgress == m_criteriaProgress.end())
- return;
+ // counter can never complete
+ if (achievement->Flags & ACHIEVEMENT_FLAG_COUNTER)
+ return false;
- WorldPackets::Achievement::CriteriaDeleted criteriaDeleted;
- criteriaDeleted.CriteriaID = entry->ID;
- SendPacket(criteriaDeleted.Write());
+ if (achievement->Flags & (ACHIEVEMENT_FLAG_REALM_FIRST_REACH | ACHIEVEMENT_FLAG_REALM_FIRST_KILL))
+ {
+ // someone on this realm has already completed that achievement
+ if (sAchievementMgr->IsRealmCompleted(achievement))
+ return false;
+ }
- m_criteriaProgress.erase(criteriaProgress);
+ return true;
}
-template<>
-void AchievementMgr<Guild>::RemoveCriteriaProgress(AchievementCriteria const* entry)
+void AchievementMgr::CompletedCriteriaTree(CriteriaTree const* tree, Player* referencePlayer)
{
- if (!entry)
+ // counter can never complete
+ if (tree->Achievement->Flags & ACHIEVEMENT_FLAG_COUNTER)
return;
- CriteriaProgressMap::iterator criteriaProgress = m_criteriaProgress.find(entry->ID);
- if (criteriaProgress == m_criteriaProgress.end())
+ // already completed and stored
+ if (HasAchieved(tree->Achievement->ID))
return;
- WorldPackets::Achievement::GuildCriteriaDeleted guildCriteriaDeleted;
- guildCriteriaDeleted.GuildGUID = GetOwner()->GetGUID();
- guildCriteriaDeleted.CriteriaID = entry->ID;
- SendPacket(guildCriteriaDeleted.Write());
+ if (IsCompletedAchievement(tree->Achievement))
+ CompletedAchievement(tree->Achievement, referencePlayer);
+}
+
+void AchievementMgr::AfterCriteriaTreeUpdate(CriteriaTree const* tree, Player* referencePlayer)
+{
+ // check again the completeness for SUMM and REQ COUNT achievements,
+ // as they don't depend on the completed criteria but on the sum of the progress of each individual criteria
+ if (tree->Achievement->Flags & ACHIEVEMENT_FLAG_SUMM)
+ if (IsCompletedAchievement(tree->Achievement))
+ CompletedAchievement(tree->Achievement, referencePlayer);
- m_criteriaProgress.erase(criteriaProgress);
+ if (std::vector<AchievementEntry const*> const* achRefList = sAchievementMgr->GetAchievementByReferencedId(tree->Achievement->ID))
+ for (AchievementEntry const* refAchievement : *achRefList)
+ if (IsCompletedAchievement(refAchievement))
+ CompletedAchievement(refAchievement, referencePlayer);
}
-template<class T>
-void AchievementMgr<T>::ResetAchievementCriteria(AchievementCriteriaTypes type, uint64 miscValue1, uint64 miscValue2, bool evenIfCriteriaComplete)
+bool AchievementMgr::IsCompletedAchievement(AchievementEntry const* entry)
{
- TC_LOG_DEBUG("achievement", "ResetAchievementCriteria(%u, " UI64FMTD ", " UI64FMTD ")", type, miscValue1, miscValue2);
+ // counter can never complete
+ if (entry->Flags & ACHIEVEMENT_FLAG_COUNTER)
+ return false;
- // disable for gamemasters with GM-mode enabled
- if (GetOwner()->IsGameMaster())
- return;
+ CriteriaTree const* tree = sCriteriaMgr->GetCriteriaTree(entry->CriteriaTree);
+ if (!tree)
+ return false;
- AchievementCriteriaList const& achievementCriteriaList = sAchievementMgr->GetAchievementCriteriaByType(type);
- for (AchievementCriteria const* achievementCriteria : achievementCriteriaList)
+ // For SUMM achievements, we have to count the progress of each criteria of the achievement.
+ // Oddly, the target count is NOT contained in the achievement, but in each individual criteria
+ if (entry->Flags & ACHIEVEMENT_FLAG_SUMM)
{
- if (achievementCriteria->Entry->FailEvent != miscValue1 || (achievementCriteria->Entry->FailAsset && achievementCriteria->Entry->FailAsset != miscValue2))
- continue;
-
- AchievementCriteriaTreeList const* trees = sAchievementMgr->GetAchievementCriteriaTreesByCriteria(achievementCriteria->ID);
- bool allComplete = true;
- for (AchievementCriteriaTree const* tree : *trees)
+ uint64 progress = 0;
+ CriteriaMgr::WalkCriteriaTree(tree, [this, &progress](CriteriaTree const* criteriaTree)
{
- // don't update already completed criteria if not forced or achievement already complete
- if (!(IsCompletedCriteriaTree(tree) && !evenIfCriteriaComplete) || !HasAchieved(tree->Achievement->ID))
- {
- allComplete = false;
- break;
- }
- }
+ if (criteriaTree->Criteria)
+ if (CriteriaProgress const* criteriaProgress = this->GetCriteriaProgress(criteriaTree->Criteria))
+ progress += criteriaProgress->Counter;
+ });
+ return progress >= tree->Entry->Amount;
+ }
- if (allComplete)
- continue;
+ return IsCompletedCriteriaTree(tree);
+}
- RemoveCriteriaProgress(achievementCriteria);
- }
+bool AchievementMgr::RequiredAchievementSatisfied(uint32 achievementId) const
+{
+ return HasAchieved(achievementId);
}
-template<>
-void AchievementMgr<Guild>::ResetAchievementCriteria(AchievementCriteriaTypes /*type*/, uint64 /*miscValue1*/, uint64 /*miscValue2*/, bool /*evenIfCriteriaComplete*/)
+PlayerAchievementMgr::PlayerAchievementMgr(Player* owner) : _owner(owner)
{
- // Not needed
}
-void DeletePlayerAchievementsFromDB(ObjectGuid guid)
+void PlayerAchievementMgr::Reset()
{
- SQLTransaction trans = CharacterDatabase.BeginTransaction();
+ AchievementMgr::Reset();
- PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_ACHIEVEMENT);
- stmt->setUInt64(0, guid.GetCounter());
- trans->Append(stmt);
+ for (auto iter = _completedAchievements.begin(); iter != _completedAchievements.end(); ++iter)
+ {
+ WorldPackets::Achievement::AchievementDeleted achievementDeleted;
+ achievementDeleted.AchievementID = iter->first;
+ SendPacket(achievementDeleted.Write());
+ }
- stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_ACHIEVEMENT_PROGRESS);
- stmt->setUInt64(0, guid.GetCounter());
- trans->Append(stmt);
+ _completedAchievements.clear();
+ _achievementPoints = 0;
+ DeleteFromDB(_owner->GetGUID());
- CharacterDatabase.CommitTransaction(trans);
+ // re-fill data
+ CheckAllAchievementCriteria(_owner);
}
-void DeleteGuildAchievementsFromDB(ObjectGuid guid)
+void PlayerAchievementMgr::DeleteFromDB(ObjectGuid const& guid)
{
SQLTransaction trans = CharacterDatabase.BeginTransaction();
- PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ALL_GUILD_ACHIEVEMENTS);
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_ACHIEVEMENT);
stmt->setUInt64(0, guid.GetCounter());
trans->Append(stmt);
- stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ALL_GUILD_ACHIEVEMENT_CRITERIA);
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_ACHIEVEMENT_PROGRESS);
stmt->setUInt64(0, guid.GetCounter());
trans->Append(stmt);
CharacterDatabase.CommitTransaction(trans);
}
-template<class T>
-void AchievementMgr<T>::SaveToDB(SQLTransaction& /*trans*/)
-{
-}
-
-template<>
-void AchievementMgr<Player>::SaveToDB(SQLTransaction& trans)
-{
- if (!m_completedAchievements.empty())
- {
- for (CompletedAchievementMap::iterator iter = m_completedAchievements.begin(); iter != m_completedAchievements.end(); ++iter)
- {
- if (!iter->second.changed)
- continue;
-
- PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_ACHIEVEMENT_BY_ACHIEVEMENT);
- stmt->setUInt16(0, iter->first);
- stmt->setUInt64(1, GetOwner()->GetGUID().GetCounter());
- trans->Append(stmt);
-
- stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHAR_ACHIEVEMENT);
- stmt->setUInt64(0, GetOwner()->GetGUID().GetCounter());
- stmt->setUInt16(1, iter->first);
- stmt->setUInt32(2, uint32(iter->second.date));
- trans->Append(stmt);
-
- iter->second.changed = false;
- }
- }
-
- if (!m_criteriaProgress.empty())
- {
- for (CriteriaProgressMap::iterator iter = m_criteriaProgress.begin(); iter != m_criteriaProgress.end(); ++iter)
- {
- if (!iter->second.changed)
- continue;
-
- PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_ACHIEVEMENT_PROGRESS_BY_CRITERIA);
- stmt->setUInt64(0, GetOwner()->GetGUID().GetCounter());
- stmt->setUInt32(1, iter->first);
- trans->Append(stmt);
-
- if (iter->second.counter)
- {
- stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHAR_ACHIEVEMENT_PROGRESS);
- stmt->setUInt64(0, GetOwner()->GetGUID().GetCounter());
- stmt->setUInt32(1, iter->first);
- stmt->setUInt32(2, iter->second.counter);
- stmt->setUInt32(3, uint32(iter->second.date));
- trans->Append(stmt);
- }
-
- iter->second.changed = false;
- }
- }
-}
-
-template<>
-void AchievementMgr<Guild>::SaveToDB(SQLTransaction& trans)
-{
- PreparedStatement* stmt;
- std::ostringstream guidstr;
- for (CompletedAchievementMap::const_iterator itr = m_completedAchievements.begin(); itr != m_completedAchievements.end(); ++itr)
- {
- if (!itr->second.changed)
- continue;
-
- stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_ACHIEVEMENT);
- stmt->setUInt64(0, GetOwner()->GetId());
- stmt->setUInt16(1, itr->first);
- trans->Append(stmt);
-
- stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_GUILD_ACHIEVEMENT);
- stmt->setUInt64(0, GetOwner()->GetId());
- stmt->setUInt16(1, itr->first);
- stmt->setUInt32(2, itr->second.date);
- for (GuidSet::const_iterator gItr = itr->second.guids.begin(); gItr != itr->second.guids.end(); ++gItr)
- guidstr << gItr->GetCounter() << ',';
-
- stmt->setString(3, guidstr.str());
- trans->Append(stmt);
-
- guidstr.str("");
- }
-
- for (CriteriaProgressMap::const_iterator itr = m_criteriaProgress.begin(); itr != m_criteriaProgress.end(); ++itr)
- {
- if (!itr->second.changed)
- continue;
-
- stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_ACHIEVEMENT_CRITERIA);
- stmt->setUInt64(0, GetOwner()->GetId());
- stmt->setUInt32(1, itr->first);
- trans->Append(stmt);
-
- stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_GUILD_ACHIEVEMENT_CRITERIA);
- stmt->setUInt64(0, GetOwner()->GetId());
- stmt->setUInt32(1, itr->first);
- stmt->setUInt64(2, itr->second.counter);
- stmt->setUInt32(3, itr->second.date);
- stmt->setUInt64(4, itr->second.PlayerGUID.GetCounter());
- trans->Append(stmt);
- }
-}
-template<class T>
-void AchievementMgr<T>::LoadFromDB(PreparedQueryResult /*achievementResult*/, PreparedQueryResult /*criteriaResult*/)
-{
-}
-
-template<>
-void AchievementMgr<Player>::LoadFromDB(PreparedQueryResult achievementResult, PreparedQueryResult criteriaResult)
+void PlayerAchievementMgr::LoadFromDB(PreparedQueryResult achievementResult, PreparedQueryResult criteriaResult)
{
if (achievementResult)
{
do
{
Field* fields = achievementResult->Fetch();
- uint32 achievementid = fields[0].GetUInt16();
+ uint32 achievementid = fields[0].GetUInt32();
// must not happen: cleanup at server startup in sAchievementMgr->LoadCompletedAchievements()
- AchievementEntry const* achievement = sAchievementMgr->GetAchievement(achievementid);
+ AchievementEntry const* achievement = sAchievementStore.LookupEntry(achievementid);
if (!achievement)
continue;
- CompletedAchievementData& ca = m_completedAchievements[achievementid];
- ca.date = time_t(fields[1].GetUInt32());
- ca.changed = false;
+ CompletedAchievementData& ca = _completedAchievements[achievementid];
+ ca.Date = time_t(fields[1].GetUInt32());
+ ca.Changed = false;
_achievementPoints += achievement->Points;
// title achievement rewards are retroactive
if (AchievementReward const* reward = sAchievementMgr->GetAchievementReward(achievement))
- if (uint32 titleId = reward->titleId[Player::TeamForRace(GetOwner()->getRace()) == ALLIANCE ? 0 : 1])
+ if (uint32 titleId = reward->TitleId[Player::TeamForRace(_owner->getRace()) == ALLIANCE ? 0 : 1])
if (CharTitlesEntry const* titleEntry = sCharTitlesStore.LookupEntry(titleId))
- GetOwner()->SetTitle(titleEntry);
+ _owner->SetTitle(titleEntry);
- }
- while (achievementResult->NextRow());
+ } while (achievementResult->NextRow());
}
if (criteriaResult)
@@ -664,15 +241,15 @@ void AchievementMgr<Player>::LoadFromDB(PreparedQueryResult achievementResult, P
do
{
Field* fields = criteriaResult->Fetch();
- uint32 id = fields[0].GetUInt32();
+ uint32 id = fields[0].GetUInt32();
uint64 counter = fields[1].GetUInt64();
- time_t date = time_t(fields[2].GetUInt32());
+ time_t date = time_t(fields[2].GetUInt32());
- AchievementCriteria const* criteria = sAchievementMgr->GetAchievementCriteria(id);
+ Criteria const* criteria = sCriteriaMgr->GetCriteria(id);
if (!criteria)
{
// Removing non-existing criteria data for all characters
- TC_LOG_ERROR("achievement", "Non-existing achievement criteria %u data has been removed from the table `character_achievement_progress`.", id);
+ TC_LOG_ERROR("criteria.achievement", "Non-existing achievement criteria %u data has been removed from the table `character_achievement_progress`.", id);
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_INVALID_ACHIEV_PROGRESS_CRITERIA);
stmt->setUInt32(0, uint16(id));
@@ -684,1052 +261,183 @@ void AchievementMgr<Player>::LoadFromDB(PreparedQueryResult achievementResult, P
if (criteria->Entry->StartTimer && time_t(date + criteria->Entry->StartTimer) < now)
continue;
- CriteriaProgress& progress = m_criteriaProgress[id];
- progress.counter = counter;
- progress.date = date;
- progress.changed = false;
- }
- while (criteriaResult->NextRow());
+ CriteriaProgress& progress = _criteriaProgress[id];
+ progress.Counter = counter;
+ progress.Date = date;
+ progress.Changed = false;
+ } while (criteriaResult->NextRow());
}
}
-template<>
-void AchievementMgr<Guild>::LoadFromDB(PreparedQueryResult achievementResult, PreparedQueryResult criteriaResult)
+void PlayerAchievementMgr::SaveToDB(SQLTransaction& trans)
{
- if (achievementResult)
+ if (!_completedAchievements.empty())
{
- do
+ for (auto iter = _completedAchievements.begin(); iter != _completedAchievements.end(); ++iter)
{
- Field* fields = achievementResult->Fetch();
- uint32 achievementid = fields[0].GetUInt16();
-
- // must not happen: cleanup at server startup in sAchievementMgr->LoadCompletedAchievements()
- AchievementEntry const* achievement = sAchievementMgr->GetAchievement(achievementid);
- if (!achievement)
+ if (!iter->second.Changed)
continue;
- CompletedAchievementData& ca = m_completedAchievements[achievementid];
- ca.date = time_t(fields[1].GetUInt32());
- Tokenizer guids(fields[2].GetString(), ' ');
- for (uint32 i = 0; i < guids.size(); ++i)
- ca.guids.insert(ObjectGuid::Create<HighGuid::Player>(uint64(strtoull(guids[i], nullptr, 10))));
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_ACHIEVEMENT_BY_ACHIEVEMENT);
+ stmt->setUInt32(0, iter->first);
+ stmt->setUInt64(1, _owner->GetGUID().GetCounter());
+ trans->Append(stmt);
- ca.changed = false;
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHAR_ACHIEVEMENT);
+ stmt->setUInt64(0, _owner->GetGUID().GetCounter());
+ stmt->setUInt32(1, iter->first);
+ stmt->setUInt32(2, uint32(iter->second.Date));
+ trans->Append(stmt);
- _achievementPoints += achievement->Points;
+ iter->second.Changed = false;
}
- while (achievementResult->NextRow());
}
- if (criteriaResult)
+ if (!_criteriaProgress.empty())
{
- time_t now = time(NULL);
- do
+ for (auto iter = _criteriaProgress.begin(); iter != _criteriaProgress.end(); ++iter)
{
- Field* fields = criteriaResult->Fetch();
- uint32 id = fields[0].GetUInt32();
- uint64 counter = fields[1].GetUInt64();
- time_t date = time_t(fields[2].GetUInt32());
- ObjectGuid::LowType guid = fields[3].GetUInt64();
-
- AchievementCriteria const* criteria = sAchievementMgr->GetAchievementCriteria(id);
- if (!criteria)
- {
- // we will remove not existed criteria for all guilds
- TC_LOG_ERROR("achievement", "Non-existing achievement criteria %u data removed from table `guild_achievement_progress`.", id);
-
- PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_INVALID_ACHIEV_PROGRESS_CRITERIA_GUILD);
- stmt->setUInt32(0, uint16(id));
- CharacterDatabase.Execute(stmt);
- continue;
- }
-
- if (criteria->Entry->StartTimer && time_t(date + criteria->Entry->StartTimer) < now)
+ if (!iter->second.Changed)
continue;
- CriteriaProgress& progress = m_criteriaProgress[id];
- progress.counter = counter;
- progress.date = date;
- progress.PlayerGUID = ObjectGuid::Create<HighGuid::Player>(guid);
- progress.changed = false;
- } while (criteriaResult->NextRow());
- }
-}
-
-template<class T>
-void AchievementMgr<T>::Reset()
-{
-}
-
-template<>
-void AchievementMgr<Player>::Reset()
-{
- for (CompletedAchievementMap::const_iterator iter = m_completedAchievements.begin(); iter != m_completedAchievements.end(); ++iter)
- {
- WorldPackets::Achievement::AchievementDeleted achievementDeleted;
- achievementDeleted.AchievementID = iter->first;
- SendPacket(achievementDeleted.Write());
- }
-
- for (CriteriaProgressMap::const_iterator iter = m_criteriaProgress.begin(); iter != m_criteriaProgress.end(); ++iter)
- {
- WorldPackets::Achievement::CriteriaDeleted criteriaDeleted;
- criteriaDeleted.CriteriaID = iter->first;
- SendPacket(criteriaDeleted.Write());
- }
-
- m_completedAchievements.clear();
- _achievementPoints = 0;
- m_criteriaProgress.clear();
- DeleteFromDB(GetOwner()->GetGUID());
-
- // re-fill data
- CheckAllAchievementCriteria(GetOwner());
-}
-
-template<>
-void AchievementMgr<Guild>::Reset()
-{
- ObjectGuid guid = GetOwner()->GetGUID();
- for (CompletedAchievementMap::const_iterator iter = m_completedAchievements.begin(); iter != m_completedAchievements.end(); ++iter)
- {
- WorldPackets::Achievement::GuildAchievementDeleted guildAchievementDeleted;
- guildAchievementDeleted.AchievementID = iter->first;
- guildAchievementDeleted.GuildGUID = guid;
- guildAchievementDeleted.TimeDeleted = time(NULL);
- SendPacket(guildAchievementDeleted.Write());
- }
-
- while (!m_criteriaProgress.empty())
- if (AchievementCriteria const* criteria = sAchievementMgr->GetAchievementCriteria(m_criteriaProgress.begin()->first))
- RemoveCriteriaProgress(criteria);
-
- _achievementPoints = 0;
- m_completedAchievements.clear();
- DeleteFromDB(GetOwner()->GetGUID());
-}
-
-template<class T>
-void AchievementMgr<T>::SendAchievementEarned(AchievementEntry const* achievement) const
-{
- // Don't send for achievements with ACHIEVEMENT_FLAG_HIDDEN
- if (achievement->Flags & ACHIEVEMENT_FLAG_HIDDEN)
- return;
-
- TC_LOG_DEBUG("achievement", "AchievementMgr::SendAchievementEarned(%u)", achievement->ID);
-
- if (Guild* guild = sGuildMgr->GetGuildById(GetOwner()->GetGuildId()))
- {
- Trinity::BroadcastTextBuilder _builder(GetOwner(), CHAT_MSG_GUILD_ACHIEVEMENT, BROADCAST_TEXT_ACHIEVEMENT_EARNED, GetOwner(), achievement->ID);
- Trinity::LocalizedPacketDo<Trinity::BroadcastTextBuilder> _localizer(_builder);
- guild->BroadcastWorker(_localizer, GetOwner());
- }
-
- if (achievement->Flags & (ACHIEVEMENT_FLAG_REALM_FIRST_KILL | ACHIEVEMENT_FLAG_REALM_FIRST_REACH))
- {
- // broadcast realm first reached
- WorldPackets::Achievement::ServerFirstAchievement serverFirstAchievement;
- serverFirstAchievement.Name = GetOwner()->GetName();
- serverFirstAchievement.PlayerGUID = GetOwner()->GetGUID();
- serverFirstAchievement.AchievementID = achievement->ID;
- sWorld->SendGlobalMessage(serverFirstAchievement.Write());
- }
- // if player is in world he can tell his friends about new achievement
- else if (GetOwner()->IsInWorld())
- {
- Trinity::BroadcastTextBuilder _builder(GetOwner(), CHAT_MSG_ACHIEVEMENT, BROADCAST_TEXT_ACHIEVEMENT_EARNED, GetOwner(), achievement->ID);
- Trinity::LocalizedPacketDo<Trinity::BroadcastTextBuilder> _localizer(_builder);
- Trinity::PlayerDistWorker<Trinity::LocalizedPacketDo<Trinity::BroadcastTextBuilder> > _worker(GetOwner(), sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_SAY), _localizer);
- GetOwner()->VisitNearbyWorldObject(sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_SAY), _worker);
- }
-
- WorldPackets::Achievement::AchievementEarned achievementEarned;
- achievementEarned.Sender = GetOwner()->GetGUID();
- achievementEarned.Earner = GetOwner()->GetGUID();
- achievementEarned.EarnerNativeRealm = achievementEarned.EarnerVirtualRealm = GetVirtualRealmAddress();
- achievementEarned.AchievementID = achievement->ID;
- achievementEarned.Time = time(NULL);
- GetOwner()->SendMessageToSetInRange(achievementEarned.Write(), sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_SAY), true);
-}
-
-template<>
-void AchievementMgr<Guild>::SendAchievementEarned(AchievementEntry const* achievement) const
-{
- if (achievement->Flags & (ACHIEVEMENT_FLAG_REALM_FIRST_KILL | ACHIEVEMENT_FLAG_REALM_FIRST_REACH))
- {
- // broadcast realm first reached
- WorldPackets::Achievement::ServerFirstAchievement serverFirstAchievement;
- serverFirstAchievement.Name = GetOwner()->GetName();
- serverFirstAchievement.PlayerGUID = GetOwner()->GetGUID();
- serverFirstAchievement.AchievementID = achievement->ID;
- serverFirstAchievement.GuildAchievement = true;
- sWorld->SendGlobalMessage(serverFirstAchievement.Write());
- }
-
- WorldPackets::Achievement::GuildAchievementEarned guildAchievementEarned;
- guildAchievementEarned.AchievementID = achievement->ID;
- guildAchievementEarned.GuildGUID = GetOwner()->GetGUID();
- guildAchievementEarned.TimeEarned = time(NULL);
- SendPacket(guildAchievementEarned.Write());
-}
-
-template<class T>
-void AchievementMgr<T>::SendCriteriaUpdate(AchievementCriteria const* /*criteria*/, CriteriaProgress const* /*progress*/, uint32 /*timeElapsed*/, bool /*timedCompleted*/) const
-{
-}
-
-template<>
-void AchievementMgr<Player>::SendCriteriaUpdate(AchievementCriteria const* criteria, CriteriaProgress const* progress, uint32 timeElapsed, bool timedCompleted) const
-{
- WorldPackets::Achievement::CriteriaUpdate criteriaUpdate;
-
- criteriaUpdate.CriteriaID = criteria->ID;
- criteriaUpdate.Quantity = progress->counter;
- criteriaUpdate.PlayerGUID = GetOwner()->GetGUID();
- if (criteria->Entry->StartTimer)
- criteriaUpdate.Flags = timedCompleted ? 1 : 0; // 1 is for keeping the counter at 0 in client
-
- criteriaUpdate.Flags = 0;
- criteriaUpdate.CurrentTime = progress->date;
- criteriaUpdate.ElapsedTime = timeElapsed;
- criteriaUpdate.CreationTime = 0;
-
- SendPacket(criteriaUpdate.Write());
-}
-
-template<>
-void AchievementMgr<Guild>::SendCriteriaUpdate(AchievementCriteria const* entry, CriteriaProgress const* progress, uint32 /*timeElapsed*/, bool /*timedCompleted*/) const
-{
- WorldPackets::Achievement::GuildCriteriaUpdate guildCriteriaUpdate;
- guildCriteriaUpdate.Progress.resize(1);
-
- WorldPackets::Achievement::GuildCriteriaProgress& guildCriteriaProgress = guildCriteriaUpdate.Progress[0];
- guildCriteriaProgress.CriteriaID = entry->ID;
- guildCriteriaProgress.DateCreated = 0;
- guildCriteriaProgress.DateStarted = 0;
- guildCriteriaProgress.DateUpdated = progress->date;
- guildCriteriaProgress.Quantity = progress->counter;
- guildCriteriaProgress.PlayerGUID = progress->PlayerGUID;
- guildCriteriaProgress.Flags = 0;
-
- GetOwner()->BroadcastPacketIfTrackingAchievement(guildCriteriaUpdate.Write(), entry->ID);
-}
-
-template<class T>
-void AchievementMgr<T>::SendAllTrackedCriterias(Player* /*receiver*/, std::set<uint32> const& /*trackedCriterias*/) const
-{
-}
-
-template<>
-void AchievementMgr<Guild>::SendAllTrackedCriterias(Player* receiver, std::set<uint32> const& trackedCriterias) const
-{
- WorldPackets::Achievement::GuildCriteriaUpdate guildCriteriaUpdate;
- guildCriteriaUpdate.Progress.reserve(trackedCriterias.size());
-
- for (uint32 criteriaId : trackedCriterias)
- {
- auto progress = m_criteriaProgress.find(criteriaId);
- if (progress == m_criteriaProgress.end())
- continue;
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_ACHIEVEMENT_PROGRESS_BY_CRITERIA);
+ stmt->setUInt64(0, _owner->GetGUID().GetCounter());
+ stmt->setUInt32(1, iter->first);
+ trans->Append(stmt);
- WorldPackets::Achievement::GuildCriteriaProgress guildCriteriaProgress;
- guildCriteriaProgress.CriteriaID = criteriaId;
- guildCriteriaProgress.DateCreated = 0;
- guildCriteriaProgress.DateStarted = 0;
- guildCriteriaProgress.DateUpdated = progress->second.date;
- guildCriteriaProgress.Quantity = progress->second.counter;
- guildCriteriaProgress.PlayerGUID = progress->second.PlayerGUID;
- guildCriteriaProgress.Flags = 0;
+ if (iter->second.Counter)
+ {
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHAR_ACHIEVEMENT_PROGRESS);
+ stmt->setUInt64(0, _owner->GetGUID().GetCounter());
+ stmt->setUInt32(1, iter->first);
+ stmt->setUInt64(2, iter->second.Counter);
+ stmt->setUInt32(3, uint32(iter->second.Date));
+ trans->Append(stmt);
+ }
- guildCriteriaUpdate.Progress.push_back(guildCriteriaProgress);
+ iter->second.Changed = false;
+ }
}
-
- receiver->GetSession()->SendPacket(guildCriteriaUpdate.Write());
}
-/**
- * called at player login. The player might have fulfilled some achievements when the achievement system wasn't working yet
- */
-template<class T>
-void AchievementMgr<T>::CheckAllAchievementCriteria(Player* referencePlayer)
+void PlayerAchievementMgr::ResetCriteria(CriteriaTypes type, uint64 miscValue1, uint64 miscValue2, bool evenIfCriteriaComplete)
{
- // suppress sending packets
- for (uint32 i = 0; i < ACHIEVEMENT_CRITERIA_TYPE_TOTAL; ++i)
- UpdateAchievementCriteria(AchievementCriteriaTypes(i), 0, 0, 0, NULL, referencePlayer);
-}
-
-// Helper function to avoid having to specialize template for a 800 line long function
-template <typename T> static bool IsGuild() { return false; }
-template<> bool IsGuild<Guild>() { return true; }
-
-/**
- * this function will be called whenever the user might have done a criteria relevant action
- */
-template<class T>
-void AchievementMgr<T>::UpdateAchievementCriteria(AchievementCriteriaTypes type, uint64 miscValue1 /*= 0*/, uint64 miscValue2 /*= 0*/, uint64 miscValue3 /*= 0*/, Unit const* unit /*= NULL*/, Player* referencePlayer /*= NULL*/)
-{
- if (type >= ACHIEVEMENT_CRITERIA_TYPE_TOTAL)
- {
- TC_LOG_DEBUG("achievement", "UpdateAchievementCriteria: Wrong criteria type %u", type);
- return;
- }
-
- if (!referencePlayer)
- {
- TC_LOG_DEBUG("achievement", "UpdateAchievementCriteria: Player is NULL! Cant update criteria");
- return;
- }
+ TC_LOG_DEBUG("criteria.achievement", "PlayerAchievementMgr::ResetCriteria(%u, " UI64FMTD ", " UI64FMTD ")", type, miscValue1, miscValue2);
// disable for gamemasters with GM-mode enabled
- if (referencePlayer->IsGameMaster())
- {
- TC_LOG_DEBUG("achievement", "UpdateAchievementCriteria: [Player %s GM mode on] %s, %s (%u), " UI64FMTD ", " UI64FMTD ", " UI64FMTD
- , referencePlayer->GetName().c_str(), GetOwner()->GetGUID().ToString().c_str(), AchievementGlobalMgr::GetCriteriaTypeString(type), type, miscValue1, miscValue2, miscValue3);
+ if (_owner->IsGameMaster())
return;
- }
-
- TC_LOG_DEBUG("achievement", "UpdateAchievementCriteria: %s, %s (%u), " UI64FMTD ", " UI64FMTD ", " UI64FMTD
- , GetOwner()->GetGUID().ToString().c_str(), AchievementGlobalMgr::GetCriteriaTypeString(type), type, miscValue1, miscValue2, miscValue3);
-
- // Lua_GetGuildLevelEnabled() is checked in achievement UI to display guild tab
- //if (IsGuild<T>() && !sWorld->getBoolConfig(CONFIG_GUILD_LEVELING_ENABLED))
- // return;
- AchievementCriteriaList const& achievementCriteriaList = sAchievementMgr->GetAchievementCriteriaByType(type, IsGuild<T>());
- for (AchievementCriteria const* achievementCriteria : achievementCriteriaList)
+ CriteriaList const& achievementCriteriaList = GetCriteriaByType(type);
+ for (Criteria const* achievementCriteria : achievementCriteriaList)
{
- AchievementCriteriaTreeList const* trees = sAchievementMgr->GetAchievementCriteriaTreesByCriteria(achievementCriteria->ID);
-
- if (!CanUpdateCriteria(achievementCriteria, trees, miscValue1, miscValue2, miscValue3, unit, referencePlayer))
+ if (achievementCriteria->Entry->FailEvent != miscValue1 || (achievementCriteria->Entry->FailAsset && achievementCriteria->Entry->FailAsset != miscValue2))
continue;
- // requirements not found in the dbc
- if (AchievementCriteriaDataSet const* data = sAchievementMgr->GetCriteriaDataSet(achievementCriteria))
- if (!data->Meets(referencePlayer, unit, miscValue1))
- continue;
-
- switch (type)
+ std::vector<CriteriaTree const*> const* trees = sCriteriaMgr->GetCriteriaTreesByCriteria(achievementCriteria->ID);
+ bool allComplete = true;
+ for (CriteriaTree const* tree : *trees)
{
- // std. case: increment at 1
- case ACHIEVEMENT_CRITERIA_TYPE_NUMBER_OF_TALENT_RESETS:
- case ACHIEVEMENT_CRITERIA_TYPE_LOSE_DUEL:
- case ACHIEVEMENT_CRITERIA_TYPE_CREATE_AUCTION:
- case ACHIEVEMENT_CRITERIA_TYPE_WON_AUCTIONS: /* FIXME: for online player only currently */
- case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED:
- case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED:
- case ACHIEVEMENT_CRITERIA_TYPE_QUEST_ABANDONED:
- case ACHIEVEMENT_CRITERIA_TYPE_FLIGHT_PATHS_TAKEN:
- case ACHIEVEMENT_CRITERIA_TYPE_ACCEPTED_SUMMONINGS:
- case ACHIEVEMENT_CRITERIA_TYPE_LOOT_EPIC_ITEM:
- case ACHIEVEMENT_CRITERIA_TYPE_RECEIVE_EPIC_ITEM:
- case ACHIEVEMENT_CRITERIA_TYPE_DEATH:
- case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST:
- case ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP:
- case ACHIEVEMENT_CRITERIA_TYPE_DEATH_IN_DUNGEON:
- case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE:
- case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER:
- case ACHIEVEMENT_CRITERIA_TYPE_DEATHS_FROM:
- case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET:
- case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2:
- case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL:
- case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2:
- case ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA:
- case ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM:
- case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT:
- case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT:
- case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE:
- case ACHIEVEMENT_CRITERIA_TYPE_USE_GAMEOBJECT:
- case ACHIEVEMENT_CRITERIA_TYPE_FISH_IN_GAMEOBJECT:
- case ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL:
- case ACHIEVEMENT_CRITERIA_TYPE_HK_CLASS:
- case ACHIEVEMENT_CRITERIA_TYPE_HK_RACE:
- case ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE:
- case ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL:
- case ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL:
- case ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS:
- case ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL_AT_AREA:
- case ACHIEVEMENT_CRITERIA_TYPE_WIN_ARENA: // This also behaves like ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA
- case ACHIEVEMENT_CRITERIA_TYPE_ON_LOGIN:
- case ACHIEVEMENT_CRITERIA_TYPE_PLACE_GARRISON_BUILDING:
- case ACHIEVEMENT_CRITERIA_TYPE_OWN_BATTLE_PET_COUNT:
- SetCriteriaProgress(achievementCriteria, 1, referencePlayer, PROGRESS_ACCUMULATE);
- break;
- // std case: increment at miscValue1
- case ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_VENDORS:
- case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TALENTS:
- case ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD:
- case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TRAVELLING:
- case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_AT_BARBER:
- case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_MAIL:
- case ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY:
- case ACHIEVEMENT_CRITERIA_TYPE_GOLD_EARNED_BY_AUCTIONS:/* FIXME: for online player only currently */
- case ACHIEVEMENT_CRITERIA_TYPE_TOTAL_DAMAGE_RECEIVED:
- case ACHIEVEMENT_CRITERIA_TYPE_TOTAL_HEALING_RECEIVED:
- case ACHIEVEMENT_CRITERIA_TYPE_USE_LFD_TO_GROUP_WITH_PLAYERS:
- case ACHIEVEMENT_CRITERIA_TYPE_WIN_BG:
- case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND:
- case ACHIEVEMENT_CRITERIA_TYPE_DAMAGE_DONE:
- case ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE:
- SetCriteriaProgress(achievementCriteria, miscValue1, referencePlayer, PROGRESS_ACCUMULATE);
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE:
- case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE:
- case ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE:
- case ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM:
- case ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM:
- case ACHIEVEMENT_CRITERIA_TYPE_CURRENCY:
- SetCriteriaProgress(achievementCriteria, miscValue2, referencePlayer, PROGRESS_ACCUMULATE);
- break;
- // std case: high value at miscValue1
- case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_BID:
- case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_SOLD: /* FIXME: for online player only currently */
- case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_DEALT:
- case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_RECEIVED:
- case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEAL_CAST:
- case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEALING_RECEIVED:
- SetCriteriaProgress(achievementCriteria, miscValue1, referencePlayer, PROGRESS_HIGHEST);
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL:
- SetCriteriaProgress(achievementCriteria, referencePlayer->getLevel(), referencePlayer);
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL:
- if (uint32 skillvalue = referencePlayer->GetBaseSkillValue(achievementCriteria->Entry->Asset.SkillID))
- SetCriteriaProgress(achievementCriteria, skillvalue, referencePlayer);
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL:
- if (uint32 maxSkillvalue = referencePlayer->GetPureMaxSkillValue(achievementCriteria->Entry->Asset.SkillID))
- SetCriteriaProgress(achievementCriteria, maxSkillvalue, referencePlayer);
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT:
- SetCriteriaProgress(achievementCriteria, referencePlayer->GetRewardedQuestCount(), referencePlayer);
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST_DAILY:
- {
- time_t nextDailyResetTime = sWorld->GetNextDailyQuestsResetTime();
- CriteriaProgress *progress = GetCriteriaProgress(achievementCriteria);
-
- if (!miscValue1) // Login case.
- {
- // reset if player missed one day.
- if (progress && progress->date < (nextDailyResetTime - 2 * DAY))
- SetCriteriaProgress(achievementCriteria, 0, referencePlayer, PROGRESS_SET);
- continue;
- }
-
- ProgressType progressType;
- if (!progress)
- // 1st time. Start count.
- progressType = PROGRESS_SET;
- else if (progress->date < (nextDailyResetTime - 2 * DAY))
- // last progress is older than 2 days. Player missed 1 day => Restart count.
- progressType = PROGRESS_SET;
- else if (progress->date < (nextDailyResetTime - DAY))
- // last progress is between 1 and 2 days. => 1st time of the day.
- progressType = PROGRESS_ACCUMULATE;
- else
- // last progress is within the day before the reset => Already counted today.
- continue;
-
- SetCriteriaProgress(achievementCriteria, 1, referencePlayer, progressType);
- break;
- }
- case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE:
- {
- uint32 counter = 0;
-
- const RewardedQuestSet &rewQuests = referencePlayer->getRewardedQuests();
- for (RewardedQuestSet::const_iterator itr = rewQuests.begin(); itr != rewQuests.end(); ++itr)
- {
- Quest const* quest = sObjectMgr->GetQuestTemplate(*itr);
- if (quest && quest->GetZoneOrSort() >= 0 && uint32(quest->GetZoneOrSort()) == achievementCriteria->Entry->Asset.ZoneID)
- ++counter;
- }
- SetCriteriaProgress(achievementCriteria, counter, referencePlayer);
- break;
- }
- case ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING:
- // miscValue1 is the ingame fallheight*100 as stored in dbc
- SetCriteriaProgress(achievementCriteria, miscValue1, referencePlayer);
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST:
- case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL:
- case ACHIEVEMENT_CRITERIA_TYPE_EXPLORE_AREA:
- case ACHIEVEMENT_CRITERIA_TYPE_VISIT_BARBER_SHOP:
- case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM:
- case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM:
- case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT:
- case ACHIEVEMENT_CRITERIA_TYPE_RECRUIT_GARRISON_FOLLOWER:
- case ACHIEVEMENT_CRITERIA_TYPE_OWN_BATTLE_PET:
- SetCriteriaProgress(achievementCriteria, 1, referencePlayer);
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT:
- SetCriteriaProgress(achievementCriteria, referencePlayer->GetBankBagSlotCount(), referencePlayer);
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION:
- {
- int32 reputation = referencePlayer->GetReputationMgr().GetReputation(achievementCriteria->Entry->Asset.FactionID);
- if (reputation > 0)
- SetCriteriaProgress(achievementCriteria, reputation, referencePlayer);
- break;
- }
- case ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION:
- SetCriteriaProgress(achievementCriteria, referencePlayer->GetReputationMgr().GetExaltedFactionCount(), referencePlayer);
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS:
- case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LINE:
- {
- uint32 spellCount = 0;
- for (PlayerSpellMap::const_iterator spellIter = referencePlayer->GetSpellMap().begin();
- spellIter != referencePlayer->GetSpellMap().end();
- ++spellIter)
- {
- SkillLineAbilityMapBounds bounds = sSpellMgr->GetSkillLineAbilityMapBounds(spellIter->first);
- for (SkillLineAbilityMap::const_iterator skillIter = bounds.first; skillIter != bounds.second; ++skillIter)
- {
- if (skillIter->second->SkillLine == achievementCriteria->Entry->Asset.SkillID)
- spellCount++;
- }
- }
- SetCriteriaProgress(achievementCriteria, spellCount, referencePlayer);
- break;
- }
- case ACHIEVEMENT_CRITERIA_TYPE_GAIN_REVERED_REPUTATION:
- SetCriteriaProgress(achievementCriteria, referencePlayer->GetReputationMgr().GetReveredFactionCount(), referencePlayer);
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_GAIN_HONORED_REPUTATION:
- SetCriteriaProgress(achievementCriteria, referencePlayer->GetReputationMgr().GetHonoredFactionCount(), referencePlayer);
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_KNOWN_FACTIONS:
- SetCriteriaProgress(achievementCriteria, referencePlayer->GetReputationMgr().GetVisibleFactionCount(), referencePlayer);
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_EARN_HONORABLE_KILL:
- SetCriteriaProgress(achievementCriteria, referencePlayer->GetUInt32Value(PLAYER_FIELD_LIFETIME_HONORABLE_KILLS), referencePlayer);
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_GOLD_VALUE_OWNED:
- SetCriteriaProgress(achievementCriteria, referencePlayer->GetMoney(), referencePlayer, PROGRESS_HIGHEST);
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_EARN_ACHIEVEMENT_POINTS:
- if (!miscValue1)
- SetCriteriaProgress(achievementCriteria, _achievementPoints, referencePlayer, PROGRESS_SET);
- else
- SetCriteriaProgress(achievementCriteria, miscValue1, referencePlayer, PROGRESS_ACCUMULATE);
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_PERSONAL_RATING:
+ // don't update already completed criteria if not forced or achievement already complete
+ if (!(IsCompletedCriteriaTree(tree) && !evenIfCriteriaComplete) || !HasAchieved(tree->Achievement->ID))
{
- uint32 reqTeamType = achievementCriteria->Entry->Asset.TeamType;
-
- if (miscValue1)
- {
- if (miscValue2 != reqTeamType)
- continue;
-
- SetCriteriaProgress(achievementCriteria, miscValue1, referencePlayer, PROGRESS_HIGHEST);
- }
- else // login case
- {
- for (uint32 arena_slot = 0; arena_slot < MAX_ARENA_SLOT; ++arena_slot)
- {
- uint32 teamId = referencePlayer->GetArenaTeamId(arena_slot);
- if (!teamId)
- continue;
-
- ArenaTeam* team = sArenaTeamMgr->GetArenaTeamById(teamId);
- if (!team || team->GetType() != reqTeamType)
- continue;
-
- if (ArenaTeamMember const* member = team->GetMember(referencePlayer->GetGUID()))
- {
- SetCriteriaProgress(achievementCriteria, member->PersonalRating, referencePlayer, PROGRESS_HIGHEST);
- break;
- }
- }
- }
+ allComplete = false;
break;
}
- case ACHIEVEMENT_CRITERIA_TYPE_REACH_GUILD_LEVEL:
- SetCriteriaProgress(achievementCriteria, miscValue1, referencePlayer);
- break;
- // FIXME: not triggered in code as result, need to implement
- case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_RAID:
- case ACHIEVEMENT_CRITERIA_TYPE_PLAY_ARENA:
- case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_TEAM_RATING:
- case ACHIEVEMENT_CRITERIA_TYPE_OWN_RANK:
- case ACHIEVEMENT_CRITERIA_TYPE_SPENT_GOLD_GUILD_REPAIRS:
- case ACHIEVEMENT_CRITERIA_TYPE_CRAFT_ITEMS_GUILD:
- case ACHIEVEMENT_CRITERIA_TYPE_CATCH_FROM_POOL:
- case ACHIEVEMENT_CRITERIA_TYPE_BUY_GUILD_BANK_SLOTS:
- case ACHIEVEMENT_CRITERIA_TYPE_EARN_GUILD_ACHIEVEMENT_POINTS:
- case ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_BATTLEGROUND:
- case ACHIEVEMENT_CRITERIA_TYPE_REACH_BG_RATING:
- case ACHIEVEMENT_CRITERIA_TYPE_BUY_GUILD_TABARD:
- case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_GUILD:
- case ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILLS_GUILD:
- case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE_GUILD:
- case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ARCHAEOLOGY_PROJECTS:
- case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_GUILD_CHALLENGE_TYPE:
- case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_GUILD_CHALLENGE:
- case ACHIEVEMENT_CRITERIA_TYPE_LFR_DUNGEONS_COMPLETED:
- case ACHIEVEMENT_CRITERIA_TYPE_LFR_LEAVES:
- case ACHIEVEMENT_CRITERIA_TYPE_LFR_VOTE_KICKS_INITIATED_BY_PLAYER:
- case ACHIEVEMENT_CRITERIA_TYPE_LFR_VOTE_KICKS_NOT_INIT_BY_PLAYER:
- case ACHIEVEMENT_CRITERIA_TYPE_BE_KICKED_FROM_LFR:
- case ACHIEVEMENT_CRITERIA_TYPE_COUNT_OF_LFR_QUEUE_BOOSTS_BY_TANK:
- case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_SCENARIO_COUNT:
- case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_SCENARIO:
- case ACHIEVEMENT_CRITERIA_TYPE_CAPTURE_BATTLE_PET:
- case ACHIEVEMENT_CRITERIA_TYPE_WIN_PET_BATTLE:
- case ACHIEVEMENT_CRITERIA_TYPE_LEVEL_BATTLE_PET:
- case ACHIEVEMENT_CRITERIA_TYPE_CAPTURE_BATTLE_PET_CREDIT:
- case ACHIEVEMENT_CRITERIA_TYPE_LEVEL_BATTLE_PET_CREDIT:
- case ACHIEVEMENT_CRITERIA_TYPE_ENTER_AREA:
- case ACHIEVEMENT_CRITERIA_TYPE_LEAVE_AREA:
- case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DUNGEON_ENCOUNTER:
- case ACHIEVEMENT_CRITERIA_TYPE_UPGRADE_GARRISON_BUILDING:
- case ACHIEVEMENT_CRITERIA_TYPE_CONSTRUCT_GARRISON_BUILDING:
- case ACHIEVEMENT_CRITERIA_TYPE_UPGRADE_GARRISON:
- case ACHIEVEMENT_CRITERIA_TYPE_START_GARRISON_MISSION:
- case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_GARRISON_MISSION_COUNT:
- case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_GARRISON_MISSION:
- case ACHIEVEMENT_CRITERIA_TYPE_RECRUIT_GARRISON_FOLLOWER_COUNT:
- case ACHIEVEMENT_CRITERIA_TYPE_LEARN_GARRISON_BLUEPRINT_COUNT:
- case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_GARRISON_SHIPMENT:
- case ACHIEVEMENT_CRITERIA_TYPE_RAISE_GARRISON_FOLLOWER_ITEM_LEVEL:
- case ACHIEVEMENT_CRITERIA_TYPE_RAISE_GARRISON_FOLLOWER_LEVEL:
- case ACHIEVEMENT_CRITERIA_TYPE_OWN_TOY:
- case ACHIEVEMENT_CRITERIA_TYPE_OWN_TOY_COUNT:
- case ACHIEVEMENT_CRITERIA_TYPE_OWN_HEIRLOOMS:
- break; // Not implemented yet :(
- }
-
- for (AchievementCriteriaTree const* tree : *trees)
- {
- if (IsCompletedCriteriaTree(tree))
- CompletedCriteriaFor(tree->Achievement, referencePlayer);
-
- // check again the completeness for SUMM and REQ COUNT achievements,
- // as they don't depend on the completed criteria but on the sum of the progress of each individual criteria
- if (tree->Achievement->Flags & ACHIEVEMENT_FLAG_SUMM)
- if (IsCompletedAchievement(tree->Achievement))
- CompletedAchievement(tree->Achievement, referencePlayer);
-
- if (AchievementEntryList const* achRefList = sAchievementMgr->GetAchievementByReferencedId(tree->Achievement->ID))
- for (AchievementEntry const* refAchievement : *achRefList)
- if (IsCompletedAchievement(refAchievement))
- CompletedAchievement(refAchievement, referencePlayer);
}
- }
-}
-
-// Only player personal achievements require instance id to check realm firsts
-// Guild restrictions are handled with additionalConditionType/additionalConditionValue
-template<class T>
-static uint32 GetInstanceId(T* /*object*/) { return 0xFFFFFFFF; }
-
-template<>
-uint32 GetInstanceId(Player* player) { return player->GetInstanceId(); }
-
-template<class T>
-bool AchievementMgr<T>::IsCompletedCriteriaTree(AchievementCriteriaTree const* tree)
-{
- AchievementEntry const* achievement = tree->Achievement;
- if (!achievement)
- return false;
-
- // counter can never complete
- if (achievement->Flags & ACHIEVEMENT_FLAG_COUNTER)
- return false;
-
- if (achievement->Flags & (ACHIEVEMENT_FLAG_REALM_FIRST_REACH | ACHIEVEMENT_FLAG_REALM_FIRST_KILL))
- {
- // someone on this realm has already completed that achievement
- if (sAchievementMgr->IsRealmCompleted(achievement, GetInstanceId(GetOwner())))
- return false;
- }
-
- uint64 requiredCount = tree->Entry->Amount;
- uint64 completedCount = 0;
- uint32 op = tree->Entry->Operator;
- bool hasAll = true;
-
- // Check criteria we depend on first
- for (AchievementCriteriaTree const* node : tree->Children)
- {
- if (IsCompletedCriteriaTree(node))
- ++completedCount;
- else
- hasAll = false;
-
- if (op & ACHIEVEMENT_CRITERIA_TREE_OPERATOR_ANY && completedCount >= requiredCount)
- {
- if (!tree->Criteria)
- return true;
-
- break;
- }
- }
-
- if (op & ACHIEVEMENT_CRITERIA_TREE_OPERATOR_ANY && completedCount < requiredCount)
- return false;
- if (op & ACHIEVEMENT_CRITERIA_TREE_OPERATOR_ALL && !hasAll)
- return false;
-
- if (!tree->Criteria)
- return true;
-
- return IsCompletedCriteria(tree->Criteria, requiredCount);
-}
-
-template<class T>
-bool AchievementMgr<T>::IsCompletedCriteria(AchievementCriteria const* achievementCriteria, uint64 requiredAmount)
-{
- CriteriaProgress const* progress = GetCriteriaProgress(achievementCriteria);
- if (!progress)
- return false;
-
- switch (AchievementCriteriaTypes(achievementCriteria->Entry->Type))
- {
- case ACHIEVEMENT_CRITERIA_TYPE_WIN_BG:
- case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE:
- case ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL:
- case ACHIEVEMENT_CRITERIA_TYPE_REACH_GUILD_LEVEL:
- case ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL:
- case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT:
- case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST_DAILY:
- case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE:
- case ACHIEVEMENT_CRITERIA_TYPE_DAMAGE_DONE:
- case ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE:
- case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST:
- case ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING:
- case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET:
- case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2:
- case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL:
- case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2:
- case ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE:
- case ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL_AT_AREA:
- case ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL:
- case ACHIEVEMENT_CRITERIA_TYPE_EARN_HONORABLE_KILL:
- case ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM:
- case ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA:
- case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_PERSONAL_RATING:
- case ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM:
- case ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM:
- case ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT:
- case ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION:
- case ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION:
- case ACHIEVEMENT_CRITERIA_TYPE_VISIT_BARBER_SHOP:
- case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM:
- case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT:
- case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT:
- case ACHIEVEMENT_CRITERIA_TYPE_HK_CLASS:
- case ACHIEVEMENT_CRITERIA_TYPE_HK_RACE:
- case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE:
- case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM:
- case ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD:
- case ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY:
- case ACHIEVEMENT_CRITERIA_TYPE_USE_GAMEOBJECT:
- case ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL:
- case ACHIEVEMENT_CRITERIA_TYPE_FISH_IN_GAMEOBJECT:
- case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS:
- case ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL:
- case ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE:
- case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LINE:
- case ACHIEVEMENT_CRITERIA_TYPE_USE_LFD_TO_GROUP_WITH_PLAYERS:
- case ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS:
- case ACHIEVEMENT_CRITERIA_TYPE_CURRENCY:
- case ACHIEVEMENT_CRITERIA_TYPE_PLACE_GARRISON_BUILDING:
- case ACHIEVEMENT_CRITERIA_TYPE_OWN_BATTLE_PET_COUNT:
- return progress->counter >= requiredAmount;
- case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT:
- case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST:
- case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL:
- case ACHIEVEMENT_CRITERIA_TYPE_EXPLORE_AREA:
- case ACHIEVEMENT_CRITERIA_TYPE_RECRUIT_GARRISON_FOLLOWER:
- case ACHIEVEMENT_CRITERIA_TYPE_OWN_BATTLE_PET:
- return progress->counter >= 1;
- case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL:
- return progress->counter >= (requiredAmount * 75);
- case ACHIEVEMENT_CRITERIA_TYPE_EARN_ACHIEVEMENT_POINTS:
- return progress->counter >= 9000;
- case ACHIEVEMENT_CRITERIA_TYPE_WIN_ARENA:
- return requiredAmount && progress->counter >= requiredAmount;
- case ACHIEVEMENT_CRITERIA_TYPE_ON_LOGIN:
- return true;
- // handle all statistic-only criteria here
- case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND:
- case ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP:
- case ACHIEVEMENT_CRITERIA_TYPE_DEATH:
- case ACHIEVEMENT_CRITERIA_TYPE_DEATH_IN_DUNGEON:
- case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE:
- case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER:
- case ACHIEVEMENT_CRITERIA_TYPE_DEATHS_FROM:
- case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_TEAM_RATING:
- case ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_VENDORS:
- case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TALENTS:
- case ACHIEVEMENT_CRITERIA_TYPE_NUMBER_OF_TALENT_RESETS:
- case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_AT_BARBER:
- case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_MAIL:
- case ACHIEVEMENT_CRITERIA_TYPE_LOSE_DUEL:
- case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE:
- case ACHIEVEMENT_CRITERIA_TYPE_GOLD_EARNED_BY_AUCTIONS:
- case ACHIEVEMENT_CRITERIA_TYPE_CREATE_AUCTION:
- case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_BID:
- case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_SOLD:
- case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_GOLD_VALUE_OWNED:
- case ACHIEVEMENT_CRITERIA_TYPE_WON_AUCTIONS:
- case ACHIEVEMENT_CRITERIA_TYPE_GAIN_REVERED_REPUTATION:
- case ACHIEVEMENT_CRITERIA_TYPE_GAIN_HONORED_REPUTATION:
- case ACHIEVEMENT_CRITERIA_TYPE_KNOWN_FACTIONS:
- case ACHIEVEMENT_CRITERIA_TYPE_LOOT_EPIC_ITEM:
- case ACHIEVEMENT_CRITERIA_TYPE_RECEIVE_EPIC_ITEM:
- case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED:
- case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED:
- case ACHIEVEMENT_CRITERIA_TYPE_QUEST_ABANDONED:
- case ACHIEVEMENT_CRITERIA_TYPE_FLIGHT_PATHS_TAKEN:
- case ACHIEVEMENT_CRITERIA_TYPE_ACCEPTED_SUMMONINGS:
- default:
- break;
- }
-
- return false;
-}
-
-template<class T>
-void AchievementMgr<T>::CompletedCriteriaFor(AchievementEntry const* achievement, Player* referencePlayer)
-{
- // counter can never complete
- if (achievement->Flags & ACHIEVEMENT_FLAG_COUNTER)
- return;
-
- // already completed and stored
- if (HasAchieved(achievement->ID))
- return;
-
- if (IsCompletedAchievement(achievement))
- CompletedAchievement(achievement, referencePlayer);
-}
-
-template<class T>
-bool AchievementMgr<T>::IsCompletedAchievement(AchievementEntry const* entry)
-{
- // counter can never complete
- if (entry->Flags & ACHIEVEMENT_FLAG_COUNTER)
- return false;
-
- AchievementCriteriaTree const* tree = sAchievementMgr->GetAchievementCriteriaTree(entry->CriteriaTree);
- if (!tree)
- return false;
+ if (allComplete)
+ continue;
- // For SUMM achievements, we have to count the progress of each criteria of the achievement.
- // Oddly, the target count is NOT contained in the achievement, but in each individual criteria
- if (entry->Flags & ACHIEVEMENT_FLAG_SUMM)
- {
- uint64 progress = 0;
- sAchievementMgr->WalkCriteriaTree(tree, [this, &progress](AchievementCriteriaTree const* criteriaTree)
- {
- if (criteriaTree->Criteria)
- if (CriteriaProgress const* criteriaProgress = this->GetCriteriaProgress(criteriaTree->Criteria))
- progress += criteriaProgress->counter;
- });
- return progress >= tree->Entry->Amount;
+ RemoveCriteriaProgress(achievementCriteria);
}
-
- return IsCompletedCriteriaTree(tree);
}
-template<class T>
-CriteriaProgress* AchievementMgr<T>::GetCriteriaProgress(AchievementCriteria const* entry)
+void PlayerAchievementMgr::SendAllData(Player const* /*receiver*/) const
{
- CriteriaProgressMap::iterator iter = m_criteriaProgress.find(entry->ID);
-
- if (iter == m_criteriaProgress.end())
- return NULL;
-
- return &(iter->second);
-}
-
-template<class T>
-void AchievementMgr<T>::SetCriteriaProgress(AchievementCriteria const* criteria, uint64 changeValue, Player* referencePlayer, ProgressType ptype)
-{
- // Don't allow to cheat - doing timed achievements without timer active
- AchievementCriteriaTreeList const* trees = nullptr;
- if (criteria->Entry->StartTimer)
- {
- trees = sAchievementMgr->GetAchievementCriteriaTreesByCriteria(criteria->ID);
- if (!trees)
- return;
-
- bool hasTreeForTimed = false;
- for (AchievementCriteriaTree const* tree : *trees)
- {
- auto timedIter = m_timedAchievements.find(tree->ID);
- if (timedIter != m_timedAchievements.end())
- {
- hasTreeForTimed = true;
- break;
- }
-
- }
-
- if (!hasTreeForTimed)
- return;
- }
-
- TC_LOG_DEBUG("achievement", "SetCriteriaProgress(%u, " UI64FMTD ") for (%s)",
- criteria->ID, changeValue, GetOwner()->GetGUID().ToString().c_str());
+ VisibleAchievementCheck filterInvisible;
+ WorldPackets::Achievement::AllAchievementData achievementData;
+ achievementData.Data.Earned.reserve(_completedAchievements.size());
+ achievementData.Data.Progress.reserve(_criteriaProgress.size());
- CriteriaProgress* progress = GetCriteriaProgress(criteria);
- if (!progress)
+ for (auto itr = _completedAchievements.begin(); itr != _completedAchievements.end(); ++itr)
{
- // not create record for 0 counter but allow it for timed achievements
- // we will need to send 0 progress to client to start the timer
- if (changeValue == 0 && !criteria->Entry->StartTimer)
- return;
+ AchievementEntry const* achievement = filterInvisible(*itr);
+ if (!achievement)
+ continue;
- progress = &m_criteriaProgress[criteria->ID];
- progress->counter = changeValue;
- }
- else
- {
- uint64 newValue = 0;
- switch (ptype)
+ WorldPackets::Achievement::EarnedAchievement earned;
+ earned.Id = itr->first;
+ earned.Date = itr->second.Date;
+ if (!(achievement->Flags & ACHIEVEMENT_FLAG_ACCOUNT))
{
- case PROGRESS_SET:
- newValue = changeValue;
- break;
- case PROGRESS_ACCUMULATE:
- {
- // avoid overflow
- uint64 max_value = std::numeric_limits<uint64>::max();
- newValue = max_value - progress->counter > changeValue ? progress->counter + changeValue : max_value;
- break;
- }
- case PROGRESS_HIGHEST:
- newValue = progress->counter < changeValue ? changeValue : progress->counter;
- break;
+ earned.Owner = _owner->GetGUID();
+ earned.VirtualRealmAddress = earned.NativeRealmAddress = GetVirtualRealmAddress();
}
-
- // not update (not mark as changed) if counter will have same value
- if (progress->counter == newValue && !criteria->Entry->StartTimer)
- return;
-
- progress->counter = newValue;
+ achievementData.Data.Earned.push_back(earned);
}
- progress->changed = true;
- progress->date = time(NULL); // set the date to the latest update.
- progress->PlayerGUID = referencePlayer->GetGUID();
-
- uint32 timeElapsed = 0;
-
- if (criteria->Entry->StartTimer)
+ for (auto itr = _criteriaProgress.begin(); itr != _criteriaProgress.end(); ++itr)
{
- ASSERT(trees);
-
- for (AchievementCriteriaTree const* tree : *trees)
- {
- auto timedIter = m_timedAchievements.find(tree->ID);
- if (timedIter != m_timedAchievements.end())
- {
- // Client expects this in packet
- timeElapsed = criteria->Entry->StartTimer - (timedIter->second / IN_MILLISECONDS);
-
- // Remove the timer, we wont need it anymore
- if (IsCompletedCriteriaTree(tree))
- m_timedAchievements.erase(timedIter);
- }
- }
+ WorldPackets::Achievement::CriteriaProgress progress;
+ progress.Id = itr->first;
+ progress.Quantity = itr->second.Counter;
+ progress.Player = itr->second.PlayerGUID;
+ progress.Flags = 0;
+ progress.Date = itr->second.Date;
+ progress.TimeFromStart = 0;
+ progress.TimeFromCreate = 0;
+ achievementData.Data.Progress.push_back(progress);
}
- SendCriteriaUpdate(criteria, progress, timeElapsed, true);
-}
-
-template<class T>
-void AchievementMgr<T>::UpdateTimedAchievements(uint32 timeDiff)
-{
- if (!m_timedAchievements.empty())
- {
- for (TimedAchievementMap::iterator itr = m_timedAchievements.begin(); itr != m_timedAchievements.end();)
- {
- // Time is up, remove timer and reset progress
- if (itr->second <= timeDiff)
- {
- AchievementCriteriaTree const* criteriaTree = sAchievementMgr->GetAchievementCriteriaTree(itr->first);
- if (criteriaTree->Criteria)
- RemoveCriteriaProgress(criteriaTree->Criteria);
-
- m_timedAchievements.erase(itr++);
- }
- else
- {
- itr->second -= timeDiff;
- ++itr;
- }
- }
- }
+ SendPacket(achievementData.Write());
}
-template<class T>
-void AchievementMgr<T>::StartTimedAchievement(AchievementCriteriaTimedTypes /*type*/, uint32 /*entry*/, uint32 /*timeLost = 0*/)
+void PlayerAchievementMgr::SendAchievementInfo(Player* receiver, uint32 /*achievementId = 0 */) const
{
-}
+ VisibleAchievementCheck filterInvisible;
+ WorldPackets::Achievement::RespondInspectAchievements inspectedAchievements;
+ inspectedAchievements.Player = _owner->GetGUID();
+ inspectedAchievements.Data.Earned.reserve(_completedAchievements.size());
+ inspectedAchievements.Data.Progress.reserve(_criteriaProgress.size());
-template<>
-void AchievementMgr<Player>::StartTimedAchievement(AchievementCriteriaTimedTypes type, uint32 entry, uint32 timeLost /* = 0 */)
-{
- AchievementCriteriaList const& achievementCriteriaList = sAchievementMgr->GetTimedAchievementCriteriaByType(type);
- for (AchievementCriteria const* criteria : achievementCriteriaList)
+ for (auto itr = _completedAchievements.begin(); itr != _completedAchievements.end(); ++itr)
{
- if (criteria->Entry->StartAsset != entry)
+ AchievementEntry const* achievement = filterInvisible(*itr);
+ if (!achievement)
continue;
- AchievementCriteriaTreeList const* trees = sAchievementMgr->GetAchievementCriteriaTreesByCriteria(criteria->ID);
- bool canStart = false;
- for (AchievementCriteriaTree const* tree : *trees)
+ WorldPackets::Achievement::EarnedAchievement earned;
+ earned.Id = itr->first;
+ earned.Date = itr->second.Date;
+ if (!(achievement->Flags & ACHIEVEMENT_FLAG_ACCOUNT))
{
- if (m_timedAchievements.find(tree->ID) == m_timedAchievements.end() && !IsCompletedCriteriaTree(tree))
- {
- // Start the timer
- if (criteria->Entry->StartTimer * IN_MILLISECONDS > timeLost)
- {
- m_timedAchievements[tree->ID] = criteria->Entry->StartTimer * IN_MILLISECONDS - timeLost;
- canStart = true;
- }
- }
+ earned.Owner = _owner->GetGUID();
+ earned.VirtualRealmAddress = earned.NativeRealmAddress = GetVirtualRealmAddress();
}
-
- if (!canStart)
- continue;
-
- // and at client too
- SetCriteriaProgress(criteria, 0, GetOwner(), PROGRESS_SET);
+ inspectedAchievements.Data.Earned.push_back(earned);
}
-}
-template<class T>
-void AchievementMgr<T>::RemoveTimedAchievement(AchievementCriteriaTimedTypes type, uint32 entry)
-{
- AchievementCriteriaList const& achievementCriteriaList = sAchievementMgr->GetTimedAchievementCriteriaByType(type);
- for (AchievementCriteria const* criteria : achievementCriteriaList)
+ for (auto itr = _criteriaProgress.begin(); itr != _criteriaProgress.end(); ++itr)
{
- if (criteria->Entry->StartAsset != entry)
- continue;
-
- AchievementCriteriaTreeList const* trees = sAchievementMgr->GetAchievementCriteriaTreesByCriteria(criteria->ID);
- // Remove the timer from all trees
- for (AchievementCriteriaTree const* tree : *trees)
- m_timedAchievements.erase(tree->ID);
-
- // remove progress
- RemoveCriteriaProgress(criteria);
+ WorldPackets::Achievement::CriteriaProgress progress;
+ progress.Id = itr->first;
+ progress.Quantity = itr->second.Counter;
+ progress.Player = itr->second.PlayerGUID;
+ progress.Flags = 0;
+ progress.Date = itr->second.Date;
+ progress.TimeFromStart = 0;
+ progress.TimeFromCreate = 0;
+ inspectedAchievements.Data.Progress.push_back(progress);
}
+
+ receiver->GetSession()->SendPacket(inspectedAchievements.Write());
}
-template<>
-void AchievementMgr<Player>::CompletedAchievement(AchievementEntry const* achievement, Player* referencePlayer)
+void PlayerAchievementMgr::CompletedAchievement(AchievementEntry const* achievement, Player* referencePlayer)
{
// disable for gamemasters with GM-mode enabled
- if (GetOwner()->IsGameMaster())
+ if (_owner->IsGameMaster())
return;
if (achievement->Flags & ACHIEVEMENT_FLAG_COUNTER || HasAchieved(achievement->ID))
@@ -1739,22 +447,23 @@ void AchievementMgr<Player>::CompletedAchievement(AchievementEntry const* achiev
if (Guild* guild = referencePlayer->GetGuild())
guild->AddGuildNews(GUILD_NEWS_PLAYER_ACHIEVEMENT, referencePlayer->GetGUID(), achievement->Flags & ACHIEVEMENT_FLAG_SHOW_IN_GUILD_HEADER, achievement->ID);
- if (!GetOwner()->GetSession()->PlayerLoading())
+ if (!_owner->GetSession()->PlayerLoading())
SendAchievementEarned(achievement);
- TC_LOG_DEBUG("achievement", "AchievementMgr::CompletedAchievement(%u). %s %s",
- achievement->ID, GetOwner()->GetGUID().ToString().c_str(), GetOwner()->GetName().c_str());
+ TC_LOG_DEBUG("criteria.achievement", "PlayerAchievementMgr::CompletedAchievement(%u). %s", achievement->ID, GetOwnerInfo().c_str());
- CompletedAchievementData& ca = m_completedAchievements[achievement->ID];
- ca.date = time(NULL);
- ca.changed = true;
+ CompletedAchievementData& ca = _completedAchievements[achievement->ID];
+ ca.Date = time(NULL);
+ ca.Changed = true;
- sAchievementMgr->SetRealmCompleted(achievement, GetOwner()->GetInstanceId());
+ if (achievement->Flags & (ACHIEVEMENT_FLAG_REALM_FIRST_REACH | ACHIEVEMENT_FLAG_REALM_FIRST_KILL))
+ sAchievementMgr->SetRealmCompleted(achievement);
- _achievementPoints += achievement->Points;
+ if (!(achievement->Flags & ACHIEVEMENT_FLAG_TRACKING_FLAG))
+ _achievementPoints += achievement->Points;
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT, 0, 0, 0, NULL, referencePlayer);
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EARN_ACHIEVEMENT_POINTS, achievement->Points, 0, 0, NULL, referencePlayer);
+ UpdateCriteria(CRITERIA_TYPE_COMPLETE_ACHIEVEMENT, 0, 0, 0, NULL, referencePlayer);
+ UpdateCriteria(CRITERIA_TYPE_EARN_ACHIEVEMENT_POINTS, achievement->Points, 0, 0, NULL, referencePlayer);
// reward items and titles if any
AchievementReward const* reward = sAchievementMgr->GetAchievementReward(achievement);
@@ -1768,28 +477,28 @@ void AchievementMgr<Player>::CompletedAchievement(AchievementEntry const* achiev
//! Since no common attributes were found, (not even in titleRewardFlags field)
//! we explicitly check by ID. Maybe in the future we could move the achievement_reward
//! condition fields to the condition system.
- if (uint32 titleId = reward->titleId[achievement->ID == 1793 ? GetOwner()->GetByteValue(PLAYER_BYTES_3, PLAYER_BYTES_3_OFFSET_GENDER) : (GetOwner()->GetTeam() == ALLIANCE ? 0 : 1)])
+ if (uint32 titleId = reward->TitleId[achievement->ID == 1793 ? _owner->GetByteValue(PLAYER_BYTES_3, PLAYER_BYTES_3_OFFSET_GENDER) : (_owner->GetTeam() == ALLIANCE ? 0 : 1)])
if (CharTitlesEntry const* titleEntry = sCharTitlesStore.LookupEntry(titleId))
- GetOwner()->SetTitle(titleEntry);
+ _owner->SetTitle(titleEntry);
// mail
- if (reward->sender)
+ if (reward->SenderCreatureId)
{
- MailDraft draft(reward->mailTemplate);
+ MailDraft draft(uint16(reward->MailTemplateId));
- if (!reward->mailTemplate)
+ if (!reward->MailTemplateId)
{
// subject and text
- std::string subject = reward->subject;
- std::string text = reward->text;
+ std::string subject = reward->Subject;
+ std::string text = reward->Body;
- LocaleConstant localeConstant = GetOwner()->GetSession()->GetSessionDbLocaleIndex();
+ LocaleConstant localeConstant = _owner->GetSession()->GetSessionDbLocaleIndex();
if (localeConstant >= LOCALE_enUS)
{
if (AchievementRewardLocale const* loc = sAchievementMgr->GetAchievementRewardLocale(achievement))
{
- ObjectMgr::GetLocaleString(loc->subject, localeConstant, subject);
- ObjectMgr::GetLocaleString(loc->text, localeConstant, text);
+ ObjectMgr::GetLocaleString(loc->Subject, localeConstant, subject);
+ ObjectMgr::GetLocaleString(loc->Body, localeConstant, text);
}
}
@@ -1798,7 +507,7 @@ void AchievementMgr<Player>::CompletedAchievement(AchievementEntry const* achiev
SQLTransaction trans = CharacterDatabase.BeginTransaction();
- Item* item = reward->itemId ? Item::CreateItem(reward->itemId, 1, GetOwner()) : NULL;
+ Item* item = reward->ItemId ? Item::CreateItem(reward->ItemId, 1, _owner) : NULL;
if (item)
{
// save new item before send
@@ -1808,132 +517,247 @@ void AchievementMgr<Player>::CompletedAchievement(AchievementEntry const* achiev
draft.AddItem(item);
}
- draft.SendMailTo(trans, GetOwner(), MailSender(MAIL_CREATURE, uint64(reward->sender)));
+ draft.SendMailTo(trans, _owner, MailSender(MAIL_CREATURE, uint64(reward->SenderCreatureId)));
CharacterDatabase.CommitTransaction(trans);
}
}
-template<>
-void AchievementMgr<Guild>::CompletedAchievement(AchievementEntry const* achievement, Player* referencePlayer)
+void PlayerAchievementMgr::SendCriteriaUpdate(Criteria const* criteria, CriteriaProgress const* progress, uint32 timeElapsed, bool timedCompleted) const
{
- TC_LOG_DEBUG("achievement", "AchievementMgr<Guild>::CompletedAchievement(%u)", achievement->ID);
+ WorldPackets::Achievement::CriteriaUpdate criteriaUpdate;
- if (achievement->Flags & ACHIEVEMENT_FLAG_COUNTER || HasAchieved(achievement->ID))
- return;
+ criteriaUpdate.CriteriaID = criteria->ID;
+ criteriaUpdate.Quantity = progress->Counter;
+ criteriaUpdate.PlayerGUID = _owner->GetGUID();
+ criteriaUpdate.Flags = 0;
+ if (criteria->Entry->StartTimer)
+ criteriaUpdate.Flags = timedCompleted ? 1 : 0; // 1 is for keeping the counter at 0 in client
- if (achievement->Flags & ACHIEVEMENT_FLAG_SHOW_IN_GUILD_NEWS)
- if (Guild* guild = referencePlayer->GetGuild())
- guild->AddGuildNews(GUILD_NEWS_GUILD_ACHIEVEMENT, ObjectGuid::Empty, achievement->Flags & ACHIEVEMENT_FLAG_SHOW_IN_GUILD_HEADER, achievement->ID);
+ criteriaUpdate.CurrentTime = progress->Date;
+ criteriaUpdate.ElapsedTime = timeElapsed;
+ criteriaUpdate.CreationTime = 0;
- SendAchievementEarned(achievement);
- CompletedAchievementData& ca = m_completedAchievements[achievement->ID];
- ca.date = time(NULL);
- ca.changed = true;
+ SendPacket(criteriaUpdate.Write());
+}
- if (achievement->Flags & ACHIEVEMENT_FLAG_SHOW_GUILD_MEMBERS)
+void PlayerAchievementMgr::SendCriteriaProgressRemoved(uint32 criteriaId)
+{
+ WorldPackets::Achievement::CriteriaDeleted criteriaDeleted;
+ criteriaDeleted.CriteriaID = criteriaId;
+ SendPacket(criteriaDeleted.Write());
+}
+
+void PlayerAchievementMgr::SendAchievementEarned(AchievementEntry const* achievement) const
+{
+ // Don't send for achievements with ACHIEVEMENT_FLAG_HIDDEN
+ if (achievement->Flags & ACHIEVEMENT_FLAG_HIDDEN)
+ return;
+
+ TC_LOG_DEBUG("criteria.achievement", "PlayerAchievementMgr::SendAchievementEarned(%u)", achievement->ID);
+
+ if (!(achievement->Flags & ACHIEVEMENT_FLAG_TRACKING_FLAG))
{
- if (referencePlayer->GetGuildId() == GetOwner()->GetId())
- ca.guids.insert(referencePlayer->GetGUID());
+ if (Guild* guild = sGuildMgr->GetGuildById(_owner->GetGuildId()))
+ {
+ Trinity::BroadcastTextBuilder _builder(_owner, CHAT_MSG_GUILD_ACHIEVEMENT, BROADCAST_TEXT_ACHIEVEMENT_EARNED, _owner, achievement->ID);
+ Trinity::LocalizedPacketDo<Trinity::BroadcastTextBuilder> _localizer(_builder);
+ guild->BroadcastWorker(_localizer, _owner);
+ }
- if (Group const* group = referencePlayer->GetGroup())
- for (GroupReference const* ref = group->GetFirstMember(); ref != NULL; ref = ref->next())
- if (Player const* groupMember = ref->GetSource())
- if (groupMember->GetGuildId() == GetOwner()->GetId())
- ca.guids.insert(groupMember->GetGUID());
+ if (achievement->Flags & (ACHIEVEMENT_FLAG_REALM_FIRST_KILL | ACHIEVEMENT_FLAG_REALM_FIRST_REACH))
+ {
+ // broadcast realm first reached
+ WorldPackets::Achievement::ServerFirstAchievement serverFirstAchievement;
+ serverFirstAchievement.Name = _owner->GetName();
+ serverFirstAchievement.PlayerGUID = _owner->GetGUID();
+ serverFirstAchievement.AchievementID = achievement->ID;
+ sWorld->SendGlobalMessage(serverFirstAchievement.Write());
+ }
+ // if player is in world he can tell his friends about new achievement
+ else if (_owner->IsInWorld())
+ {
+ Trinity::BroadcastTextBuilder _builder(_owner, CHAT_MSG_ACHIEVEMENT, BROADCAST_TEXT_ACHIEVEMENT_EARNED, _owner, achievement->ID);
+ Trinity::LocalizedPacketDo<Trinity::BroadcastTextBuilder> _localizer(_builder);
+ Trinity::PlayerDistWorker<Trinity::LocalizedPacketDo<Trinity::BroadcastTextBuilder> > _worker(_owner, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_SAY), _localizer);
+ _owner->VisitNearbyWorldObject(sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_SAY), _worker);
+ }
}
- sAchievementMgr->SetRealmCompleted(achievement, referencePlayer->GetInstanceId());
+ WorldPackets::Achievement::AchievementEarned achievementEarned;
+ achievementEarned.Sender = _owner->GetGUID();
+ achievementEarned.Earner = _owner->GetGUID();
+ achievementEarned.EarnerNativeRealm = achievementEarned.EarnerVirtualRealm = GetVirtualRealmAddress();
+ achievementEarned.AchievementID = achievement->ID;
+ achievementEarned.Time = time(NULL);
+ if (!(achievement->Flags & ACHIEVEMENT_FLAG_TRACKING_FLAG))
+ _owner->SendMessageToSetInRange(achievementEarned.Write(), sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_SAY), true);
+ else
+ _owner->SendDirectMessage(achievementEarned.Write());
+}
+
+void PlayerAchievementMgr::SendPacket(WorldPacket const* data) const
+{
+ _owner->SendDirectMessage(data);
+}
- _achievementPoints += achievement->Points;
+CriteriaList const& PlayerAchievementMgr::GetCriteriaByType(CriteriaTypes type) const
+{
+ return sCriteriaMgr->GetPlayerCriteriaByType(type);
+}
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT, 0, 0, 0, NULL, referencePlayer);
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EARN_ACHIEVEMENT_POINTS, achievement->Points, 0, 0, NULL, referencePlayer);
+GuildAchievementMgr::GuildAchievementMgr(Guild* owner) : _owner(owner)
+{
}
-struct VisibleAchievementCheck
+void GuildAchievementMgr::Reset()
{
- AchievementEntry const* operator()(CompletedAchievementMap::value_type const& val)
+ AchievementMgr::Reset();
+
+ ObjectGuid guid = _owner->GetGUID();
+ for (auto iter = _completedAchievements.begin(); iter != _completedAchievements.end(); ++iter)
{
- AchievementEntry const* achievement = sAchievementMgr->GetAchievement(val.first);
- if (achievement && !(achievement->Flags & ACHIEVEMENT_FLAG_HIDDEN))
- return achievement;
- return nullptr;
+ WorldPackets::Achievement::GuildAchievementDeleted guildAchievementDeleted;
+ guildAchievementDeleted.AchievementID = iter->first;
+ guildAchievementDeleted.GuildGUID = guid;
+ guildAchievementDeleted.TimeDeleted = time(NULL);
+ SendPacket(guildAchievementDeleted.Write());
}
-};
-template<class T>
-void AchievementMgr<T>::SendAllAchievementData(Player* /*receiver*/) const
+ _achievementPoints = 0;
+ _completedAchievements.clear();
+ DeleteFromDB(guid);
+}
+
+void GuildAchievementMgr::DeleteFromDB(ObjectGuid const& guid)
{
- VisibleAchievementCheck filterInvisible;
- WorldPackets::Achievement::AllAchievementData achievementData;
- achievementData.Data.Earned.reserve(m_completedAchievements.size());
- achievementData.Data.Progress.reserve(m_criteriaProgress.size());
+ SQLTransaction trans = CharacterDatabase.BeginTransaction();
- for (auto itr = m_completedAchievements.begin(); itr != m_completedAchievements.end(); ++itr)
- {
- AchievementEntry const* achievement = filterInvisible(*itr);
- if (!achievement)
- continue;
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ALL_GUILD_ACHIEVEMENTS);
+ stmt->setUInt64(0, guid.GetCounter());
+ trans->Append(stmt);
- WorldPackets::Achievement::EarnedAchievement earned;
- earned.Id = itr->first;
- earned.Date = itr->second.date;
- if (!(achievement->Flags & ACHIEVEMENT_FLAG_ACCOUNT))
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ALL_GUILD_ACHIEVEMENT_CRITERIA);
+ stmt->setUInt64(0, guid.GetCounter());
+ trans->Append(stmt);
+
+ CharacterDatabase.CommitTransaction(trans);
+}
+
+void GuildAchievementMgr::LoadFromDB(PreparedQueryResult achievementResult, PreparedQueryResult criteriaResult)
+{
+ if (achievementResult)
+ {
+ do
{
- earned.Owner = GetOwner()->GetGUID();
- earned.VirtualRealmAddress = earned.NativeRealmAddress = GetVirtualRealmAddress();
- }
- achievementData.Data.Earned.push_back(earned);
+ Field* fields = achievementResult->Fetch();
+ uint32 achievementid = fields[0].GetUInt32();
+
+ // must not happen: cleanup at server startup in sAchievementMgr->LoadCompletedAchievements()
+ AchievementEntry const* achievement = sAchievementStore.LookupEntry(achievementid);
+ if (!achievement)
+ continue;
+
+ CompletedAchievementData& ca = _completedAchievements[achievementid];
+ ca.Date = time_t(fields[1].GetUInt32());
+ Tokenizer guids(fields[2].GetString(), ' ');
+ for (uint32 i = 0; i < guids.size(); ++i)
+ ca.CompletingPlayers.insert(ObjectGuid::Create<HighGuid::Player>(uint64(strtoull(guids[i], nullptr, 10))));
+
+ ca.Changed = false;
+
+ _achievementPoints += achievement->Points;
+ } while (achievementResult->NextRow());
}
- for (auto itr = m_criteriaProgress.begin(); itr != m_criteriaProgress.end(); ++itr)
+ if (criteriaResult)
{
- WorldPackets::Achievement::CriteriaProgress progress;
- progress.Id = itr->first;
- progress.Quantity = itr->second.counter;
- progress.Player = itr->second.PlayerGUID;
- progress.Flags = 0;
- progress.Date = itr->second.date;
- progress.TimeFromStart = 0;
- progress.TimeFromCreate = 0;
- achievementData.Data.Progress.push_back(progress);
- }
+ time_t now = time(NULL);
+ do
+ {
+ Field* fields = criteriaResult->Fetch();
+ uint32 id = fields[0].GetUInt32();
+ uint64 counter = fields[1].GetUInt64();
+ time_t date = time_t(fields[2].GetUInt32());
+ ObjectGuid::LowType guid = fields[3].GetUInt64();
- SendPacket(achievementData.Write());
+ Criteria const* criteria = sCriteriaMgr->GetCriteria(id);
+ if (!criteria)
+ {
+ // we will remove not existed criteria for all guilds
+ TC_LOG_ERROR("criteria.achievement", "Non-existing achievement criteria %u data removed from table `guild_achievement_progress`.", id);
+
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_INVALID_ACHIEV_PROGRESS_CRITERIA_GUILD);
+ stmt->setUInt32(0, uint16(id));
+ CharacterDatabase.Execute(stmt);
+ continue;
+ }
+
+ if (criteria->Entry->StartTimer && time_t(date + criteria->Entry->StartTimer) < now)
+ continue;
+
+ CriteriaProgress& progress = _criteriaProgress[id];
+ progress.Counter = counter;
+ progress.Date = date;
+ progress.PlayerGUID = ObjectGuid::Create<HighGuid::Player>(guid);
+ progress.Changed = false;
+ } while (criteriaResult->NextRow());
+ }
}
-template<>
-void AchievementMgr<Guild>::SendAllAchievementData(Player* receiver) const
+void GuildAchievementMgr::SaveToDB(SQLTransaction& trans)
{
- VisibleAchievementCheck filterInvisible;
- WorldPackets::Achievement::AllGuildAchievements allGuildAchievements;
- allGuildAchievements.Earned.reserve(m_completedAchievements.size());
-
- for (auto itr = m_completedAchievements.begin(); itr != m_completedAchievements.end(); ++itr)
+ PreparedStatement* stmt;
+ std::ostringstream guidstr;
+ for (auto itr = _completedAchievements.begin(); itr != _completedAchievements.end(); ++itr)
{
- AchievementEntry const* achievement = filterInvisible(*itr);
- if (!achievement)
+ if (!itr->second.Changed)
continue;
- WorldPackets::Achievement::EarnedAchievement earned;
- earned.Id = itr->first;
- earned.Date = itr->second.date;
- allGuildAchievements.Earned.push_back(earned);
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_ACHIEVEMENT);
+ stmt->setUInt64(0, _owner->GetId());
+ stmt->setUInt32(1, itr->first);
+ trans->Append(stmt);
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_GUILD_ACHIEVEMENT);
+ stmt->setUInt64(0, _owner->GetId());
+ stmt->setUInt32(1, itr->first);
+ stmt->setUInt32(2, uint32(itr->second.Date));
+ for (GuidSet::const_iterator gItr = itr->second.CompletingPlayers.begin(); gItr != itr->second.CompletingPlayers.end(); ++gItr)
+ guidstr << gItr->GetCounter() << ',';
+
+ stmt->setString(3, guidstr.str());
+ trans->Append(stmt);
+
+ guidstr.str("");
}
- receiver->GetSession()->SendPacket(allGuildAchievements.Write());
+ for (auto itr = _criteriaProgress.begin(); itr != _criteriaProgress.end(); ++itr)
+ {
+ if (!itr->second.Changed)
+ continue;
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GUILD_ACHIEVEMENT_CRITERIA);
+ stmt->setUInt64(0, _owner->GetId());
+ stmt->setUInt32(1, itr->first);
+ trans->Append(stmt);
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_GUILD_ACHIEVEMENT_CRITERIA);
+ stmt->setUInt64(0, _owner->GetId());
+ stmt->setUInt32(1, itr->first);
+ stmt->setUInt64(2, itr->second.Counter);
+ stmt->setUInt32(3, uint32(itr->second.Date));
+ stmt->setUInt64(4, itr->second.PlayerGUID.GetCounter());
+ trans->Append(stmt);
+ }
}
-template<>
-void AchievementMgr<Player>::SendAchievementInfo(Player* receiver, uint32 /*achievementId = 0 */) const
+void GuildAchievementMgr::SendAllData(Player const* receiver) const
{
VisibleAchievementCheck filterInvisible;
- WorldPackets::Achievement::RespondInspectAchievements inspectedAchievements;
- inspectedAchievements.Player = GetOwner()->GetGUID();
- inspectedAchievements.Data.Earned.reserve(m_completedAchievements.size());
- inspectedAchievements.Data.Progress.reserve(m_criteriaProgress.size());
+ WorldPackets::Achievement::AllGuildAchievements allGuildAchievements;
+ allGuildAchievements.Earned.reserve(_completedAchievements.size());
- for (auto itr = m_completedAchievements.begin(); itr != m_completedAchievements.end(); ++itr)
+ for (auto itr = _completedAchievements.begin(); itr != _completedAchievements.end(); ++itr)
{
AchievementEntry const* achievement = filterInvisible(*itr);
if (!achievement)
@@ -1941,52 +765,33 @@ void AchievementMgr<Player>::SendAchievementInfo(Player* receiver, uint32 /*achi
WorldPackets::Achievement::EarnedAchievement earned;
earned.Id = itr->first;
- earned.Date = itr->second.date;
- if (!(achievement->Flags & ACHIEVEMENT_FLAG_ACCOUNT))
- {
- earned.Owner = GetOwner()->GetGUID();
- earned.VirtualRealmAddress = earned.NativeRealmAddress = GetVirtualRealmAddress();
- }
- inspectedAchievements.Data.Earned.push_back(earned);
- }
-
- for (auto itr = m_criteriaProgress.begin(); itr != m_criteriaProgress.end(); ++itr)
- {
- WorldPackets::Achievement::CriteriaProgress progress;
- progress.Id = itr->first;
- progress.Quantity = itr->second.counter;
- progress.Player = itr->second.PlayerGUID;
- progress.Flags = 0;
- progress.Date = itr->second.date;
- progress.TimeFromStart = 0;
- progress.TimeFromCreate = 0;
- inspectedAchievements.Data.Progress.push_back(progress);
+ earned.Date = itr->second.Date;
+ allGuildAchievements.Earned.push_back(earned);
}
- receiver->GetSession()->SendPacket(inspectedAchievements.Write());
+ receiver->GetSession()->SendPacket(allGuildAchievements.Write());
}
-template<>
-void AchievementMgr<Guild>::SendAchievementInfo(Player* receiver, uint32 achievementId /*= 0*/) const
+void GuildAchievementMgr::SendAchievementInfo(Player* receiver, uint32 achievementId /*= 0*/) const
{
WorldPackets::Achievement::GuildCriteriaUpdate guildCriteriaUpdate;
- if (AchievementEntry const* achievement = sAchievementMgr->GetAchievement(achievementId))
+ if (AchievementEntry const* achievement = sAchievementStore.LookupEntry(achievementId))
{
- if (AchievementCriteriaTree const* tree = sAchievementMgr->GetAchievementCriteriaTree(achievement->CriteriaTree))
+ if (CriteriaTree const* tree = sCriteriaMgr->GetCriteriaTree(achievement->CriteriaTree))
{
- sAchievementMgr->WalkCriteriaTree(tree, [this, &guildCriteriaUpdate](AchievementCriteriaTree const* node)
+ CriteriaMgr::WalkCriteriaTree(tree, [this, &guildCriteriaUpdate](CriteriaTree const* node)
{
if (node->Criteria)
{
- auto progress = this->m_criteriaProgress.find(node->Criteria->ID);
- if (progress != this->m_criteriaProgress.end())
+ auto progress = this->_criteriaProgress.find(node->Criteria->ID);
+ if (progress != this->_criteriaProgress.end())
{
WorldPackets::Achievement::GuildCriteriaProgress guildCriteriaProgress;
guildCriteriaProgress.CriteriaID = node->Criteria->ID;
guildCriteriaProgress.DateCreated = 0;
guildCriteriaProgress.DateStarted = 0;
- guildCriteriaProgress.DateUpdated = progress->second.date;
- guildCriteriaProgress.Quantity = progress->second.counter;
+ guildCriteriaProgress.DateUpdated = progress->second.Date;
+ guildCriteriaProgress.Quantity = progress->second.Counter;
guildCriteriaProgress.PlayerGUID = progress->second.PlayerGUID;
guildCriteriaProgress.Flags = 0;
@@ -2000,1073 +805,186 @@ void AchievementMgr<Guild>::SendAchievementInfo(Player* receiver, uint32 achieve
receiver->GetSession()->SendPacket(guildCriteriaUpdate.Write());
}
-template<class T>
-bool AchievementMgr<T>::HasAchieved(uint32 achievementId) const
-{
- return m_completedAchievements.find(achievementId) != m_completedAchievements.end();
-}
-
-template<class T>
-bool AchievementMgr<T>::CanUpdateCriteria(AchievementCriteria const* criteria, AchievementCriteriaTreeList const* trees, uint64 miscValue1, uint64 miscValue2, uint64 miscValue3, Unit const* unit, Player* referencePlayer)
+void GuildAchievementMgr::SendAllTrackedCriterias(Player* receiver, std::set<uint32> const& trackedCriterias) const
{
- if (DisableMgr::IsDisabledFor(DISABLE_TYPE_ACHIEVEMENT_CRITERIA, criteria->ID, NULL))
- {
- TC_LOG_TRACE("achievement", "CanUpdateCriteria: (Id: %u Type %s) Disabled",
- criteria->ID, AchievementGlobalMgr::GetCriteriaTypeString(criteria->Entry->Type));
- return false;
- }
+ WorldPackets::Achievement::GuildCriteriaUpdate guildCriteriaUpdate;
+ guildCriteriaUpdate.Progress.reserve(trackedCriterias.size());
- bool treeRequirementPassed = false;
- for (AchievementCriteriaTree const* tree : *trees)
+ for (uint32 criteriaId : trackedCriterias)
{
- if (HasAchieved(tree->Achievement->ID))
- {
- TC_LOG_TRACE("achievement", "CanUpdateCriteria: (Id: %u Type %s Achievement %u) Achievement already earned",
- criteria->ID, AchievementGlobalMgr::GetCriteriaTypeString(criteria->Entry->Type), tree->Achievement->ID);
+ auto progress = _criteriaProgress.find(criteriaId);
+ if (progress == _criteriaProgress.end())
continue;
- }
-
- if (tree->Achievement->MapID != -1 && referencePlayer->GetMapId() != uint32(tree->Achievement->MapID))
- {
- TC_LOG_TRACE("achievement", "CanUpdateCriteria: (Id: %u Type %s Achievement %u) Wrong map",
- criteria->ID, AchievementGlobalMgr::GetCriteriaTypeString(criteria->Entry->Type), tree->Achievement->ID);
- continue;
- }
-
- if ((tree->Achievement->Faction == ACHIEVEMENT_FACTION_HORDE && referencePlayer->GetTeam() != HORDE) ||
- (tree->Achievement->Faction == ACHIEVEMENT_FACTION_ALLIANCE && referencePlayer->GetTeam() != ALLIANCE))
- {
- TC_LOG_TRACE("achievement", "CanUpdateCriteria: (Id: %u Type %s Achievement %u) Wrong faction",
- criteria->ID, AchievementGlobalMgr::GetCriteriaTypeString(criteria->Entry->Type), tree->Achievement->ID);
- continue;
- }
-
- treeRequirementPassed = true;
- break;
- }
-
- if (!treeRequirementPassed)
- return false;
- if (!RequirementsSatisfied(criteria, miscValue1, miscValue2, miscValue3, unit, referencePlayer))
- {
- TC_LOG_TRACE("achievement", "CanUpdateCriteria: (Id: %u Type %s) Requirements not satisfied",
- criteria->ID, AchievementGlobalMgr::GetCriteriaTypeString(criteria->Entry->Type));
- return false;
- }
-
- if (criteria->Modifier && !AdditionalRequirementsSatisfied(criteria->Modifier, miscValue1, miscValue2, unit, referencePlayer))
- {
- TC_LOG_TRACE("achievement", "CanUpdateCriteria: (Id: %u Type %s) Requirements have not been satisfied",
- criteria->ID, AchievementGlobalMgr::GetCriteriaTypeString(criteria->Entry->Type));
- return false;
- }
+ WorldPackets::Achievement::GuildCriteriaProgress guildCriteriaProgress;
+ guildCriteriaProgress.CriteriaID = criteriaId;
+ guildCriteriaProgress.DateCreated = 0;
+ guildCriteriaProgress.DateStarted = 0;
+ guildCriteriaProgress.DateUpdated = progress->second.Date;
+ guildCriteriaProgress.Quantity = progress->second.Counter;
+ guildCriteriaProgress.PlayerGUID = progress->second.PlayerGUID;
+ guildCriteriaProgress.Flags = 0;
- if (!ConditionsSatisfied(criteria, referencePlayer))
- {
- TC_LOG_TRACE("achievement", "CanUpdateCriteria: (Id: %u Type %s) Conditions have not been satisfied",
- criteria->ID, AchievementGlobalMgr::GetCriteriaTypeString(criteria->Entry->Type));
- return false;
+ guildCriteriaUpdate.Progress.push_back(guildCriteriaProgress);
}
- return true;
+ receiver->GetSession()->SendPacket(guildCriteriaUpdate.Write());
}
-template<class T>
-bool AchievementMgr<T>::ConditionsSatisfied(AchievementCriteria const* criteria, Player* referencePlayer) const
+void GuildAchievementMgr::CompletedAchievement(AchievementEntry const* achievement, Player* referencePlayer)
{
- if (!criteria->Entry->FailEvent)
- return true;
+ TC_LOG_DEBUG("criteria.achievement", "GuildAchievementMgr::CompletedAchievement(%u)", achievement->ID);
- switch (criteria->Entry->FailEvent)
- {
- case ACHIEVEMENT_CRITERIA_CONDITION_BG_MAP:
- if (!referencePlayer->InBattleground())
- return false;
- break;
- case ACHIEVEMENT_CRITERIA_CONDITION_NOT_IN_GROUP:
- if (referencePlayer->GetGroup())
- return false;
- break;
- default:
- break;
- }
-
- return true;
-}
+ if (achievement->Flags & ACHIEVEMENT_FLAG_COUNTER || HasAchieved(achievement->ID))
+ return;
-template<class T>
-bool AchievementMgr<T>::RequirementsSatisfied(AchievementCriteria const* achievementCriteria, uint64 miscValue1, uint64 miscValue2, uint64 miscValue3, Unit const* unit, Player* referencePlayer) const
-{
- switch (AchievementCriteriaTypes(achievementCriteria->Entry->Type))
- {
- case ACHIEVEMENT_CRITERIA_TYPE_ACCEPTED_SUMMONINGS:
- case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST:
- case ACHIEVEMENT_CRITERIA_TYPE_CREATE_AUCTION:
- case ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING:
- case ACHIEVEMENT_CRITERIA_TYPE_FLIGHT_PATHS_TAKEN:
- case ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS:
- case ACHIEVEMENT_CRITERIA_TYPE_GOLD_EARNED_BY_AUCTIONS:
- case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_AT_BARBER:
- case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_MAIL:
- case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TALENTS:
- case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TRAVELLING:
- case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_BID:
- case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_SOLD:
- case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEALING_RECEIVED:
- case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEAL_CAST:
- case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_DEALT:
- case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_RECEIVED:
- case ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL:
- case ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY:
- case ACHIEVEMENT_CRITERIA_TYPE_LOSE_DUEL:
- case ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD:
- case ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_VENDORS:
- case ACHIEVEMENT_CRITERIA_TYPE_NUMBER_OF_TALENT_RESETS:
- case ACHIEVEMENT_CRITERIA_TYPE_QUEST_ABANDONED:
- case ACHIEVEMENT_CRITERIA_TYPE_REACH_GUILD_LEVEL:
- case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED:
- case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED:
- case ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL:
- case ACHIEVEMENT_CRITERIA_TYPE_TOTAL_DAMAGE_RECEIVED:
- case ACHIEVEMENT_CRITERIA_TYPE_TOTAL_HEALING_RECEIVED:
- case ACHIEVEMENT_CRITERIA_TYPE_USE_LFD_TO_GROUP_WITH_PLAYERS:
- case ACHIEVEMENT_CRITERIA_TYPE_VISIT_BARBER_SHOP:
- case ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL:
- case ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA:
- case ACHIEVEMENT_CRITERIA_TYPE_WON_AUCTIONS:
- if (!miscValue1)
- return false;
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT:
- case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST_DAILY:
- case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT:
- case ACHIEVEMENT_CRITERIA_TYPE_EARN_ACHIEVEMENT_POINTS:
- case ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION:
- case ACHIEVEMENT_CRITERIA_TYPE_GAIN_HONORED_REPUTATION:
- case ACHIEVEMENT_CRITERIA_TYPE_GAIN_REVERED_REPUTATION:
- case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_GOLD_VALUE_OWNED:
- case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_PERSONAL_RATING:
- case ACHIEVEMENT_CRITERIA_TYPE_KNOWN_FACTIONS:
- case ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL:
- case ACHIEVEMENT_CRITERIA_TYPE_ON_LOGIN:
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT:
- if (m_completedAchievements.find(achievementCriteria->Entry->Asset.AchievementID) == m_completedAchievements.end())
- return false;
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_WIN_BG:
- if (!miscValue1 || achievementCriteria->Entry->Asset.MapID != referencePlayer->GetMapId())
- return false;
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE:
- if (!miscValue1 || achievementCriteria->Entry->Asset.CreatureID != miscValue1)
- return false;
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL:
- case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL:
- // update at loading or specific skill update
- if (miscValue1 && miscValue1 != achievementCriteria->Entry->Asset.SkillID)
- return false;
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE:
- if (miscValue1 && miscValue1 != achievementCriteria->Entry->Asset.ZoneID)
- return false;
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND:
- case ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP:
- if (!miscValue1 || referencePlayer->GetMapId() != achievementCriteria->Entry->Asset.MapID)
- return false;
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_DEATH:
- {
- if (!miscValue1)
- return false;
- break;
- }
- case ACHIEVEMENT_CRITERIA_TYPE_DEATH_IN_DUNGEON:
- {
- if (!miscValue1)
- return false;
+ if (achievement->Flags & ACHIEVEMENT_FLAG_SHOW_IN_GUILD_NEWS)
+ if (Guild* guild = referencePlayer->GetGuild())
+ guild->AddGuildNews(GUILD_NEWS_GUILD_ACHIEVEMENT, ObjectGuid::Empty, achievement->Flags & ACHIEVEMENT_FLAG_SHOW_IN_GUILD_HEADER, achievement->ID);
- Map const* map = referencePlayer->IsInWorld() ? referencePlayer->GetMap() : sMapMgr->FindMap(referencePlayer->GetMapId(), referencePlayer->GetInstanceId());
- if (!map || !map->IsDungeon())
- return false;
+ SendAchievementEarned(achievement);
+ CompletedAchievementData& ca = _completedAchievements[achievement->ID];
+ ca.Date = time(NULL);
+ ca.Changed = true;
- //FIXME: work only for instances where max == min for players
- if (map->ToInstanceMap()->GetMaxPlayers() != achievementCriteria->Entry->Asset.GroupSize)
- return false;
- break;
- }
- case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE:
- if (!miscValue1 || miscValue1 != achievementCriteria->Entry->Asset.CreatureID)
- return false;
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER:
- if (!miscValue1 || !unit || unit->GetTypeId() != TYPEID_PLAYER)
- return false;
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_DEATHS_FROM:
- if (!miscValue1 || miscValue2 != achievementCriteria->Entry->Asset.DamageType)
- return false;
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST:
- {
- // if miscValues != 0, it contains the questID.
- if (miscValue1)
- {
- if (miscValue1 != achievementCriteria->Entry->Asset.QuestID)
- return false;
- }
- else
- {
- // login case.
- if (!referencePlayer->GetQuestRewardStatus(achievementCriteria->Entry->Asset.QuestID))
- return false;
- }
+ if (achievement->Flags & ACHIEVEMENT_FLAG_SHOW_GUILD_MEMBERS)
+ {
+ if (referencePlayer->GetGuildId() == _owner->GetId())
+ ca.CompletingPlayers.insert(referencePlayer->GetGUID());
- if (AchievementCriteriaDataSet const* data = sAchievementMgr->GetCriteriaDataSet(achievementCriteria))
- if (!data->Meets(referencePlayer, unit))
- return false;
- break;
- }
- case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET:
- case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2:
- case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL:
- case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2:
- if (!miscValue1 || miscValue1 != achievementCriteria->Entry->Asset.SpellID)
- return false;
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL:
- if (miscValue1 && miscValue1 != achievementCriteria->Entry->Asset.SpellID)
- return false;
-
- if (!referencePlayer->HasSpell(achievementCriteria->Entry->Asset.SpellID))
- return false;
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE:
- // miscValue1 = itemId - miscValue2 = count of item loot
- // miscValue3 = loot_type (note: 0 = LOOT_CORPSE and then it ignored)
- if (!miscValue1 || !miscValue2 || !miscValue3 || miscValue3 != achievementCriteria->Entry->Asset.LootType)
- return false;
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM:
- if (miscValue1 && achievementCriteria->Entry->Asset.ItemID != miscValue1)
- return false;
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM:
- case ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM:
- case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM:
- if (!miscValue1 || achievementCriteria->Entry->Asset.ItemID != miscValue1)
- return false;
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_EXPLORE_AREA:
- {
- WorldMapOverlayEntry const* worldOverlayEntry = sWorldMapOverlayStore.LookupEntry(achievementCriteria->Entry->Asset.WorldMapOverlayID);
- if (!worldOverlayEntry)
- break;
+ if (Group const* group = referencePlayer->GetGroup())
+ for (GroupReference const* ref = group->GetFirstMember(); ref != NULL; ref = ref->next())
+ if (Player const* groupMember = ref->GetSource())
+ if (groupMember->GetGuildId() == _owner->GetId())
+ ca.CompletingPlayers.insert(groupMember->GetGUID());
+ }
- bool matchFound = false;
- for (int j = 0; j < MAX_WORLD_MAP_OVERLAY_AREA_IDX; ++j)
- {
- AreaTableEntry const* area = sAreaTableStore.LookupEntry(worldOverlayEntry->AreaID[j]);
- if (!area)
- break;
+ if (achievement->Flags & (ACHIEVEMENT_FLAG_REALM_FIRST_REACH | ACHIEVEMENT_FLAG_REALM_FIRST_KILL))
+ sAchievementMgr->SetRealmCompleted(achievement);
- if (area->AreaBit < 0)
- continue;
+ if (!(achievement->Flags & ACHIEVEMENT_FLAG_TRACKING_FLAG))
+ _achievementPoints += achievement->Points;
- uint32 playerIndexOffset = uint32(area->AreaBit) / 32;
- if (playerIndexOffset >= PLAYER_EXPLORED_ZONES_SIZE)
- continue;
+ UpdateCriteria(CRITERIA_TYPE_COMPLETE_ACHIEVEMENT, 0, 0, 0, NULL, referencePlayer);
+ UpdateCriteria(CRITERIA_TYPE_EARN_ACHIEVEMENT_POINTS, achievement->Points, 0, 0, NULL, referencePlayer);
+}
- uint32 mask = 1 << (uint32(area->AreaBit) % 32);
- if (referencePlayer->GetUInt32Value(PLAYER_EXPLORED_ZONES_1 + playerIndexOffset) & mask)
- {
- matchFound = true;
- break;
- }
- }
+void GuildAchievementMgr::SendCriteriaUpdate(Criteria const* entry, CriteriaProgress const* progress, uint32 /*timeElapsed*/, bool /*timedCompleted*/) const
+{
+ WorldPackets::Achievement::GuildCriteriaUpdate guildCriteriaUpdate;
+ guildCriteriaUpdate.Progress.resize(1);
- if (!matchFound)
- return false;
- break;
- }
- case ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION:
- if (miscValue1 && miscValue1 != achievementCriteria->Entry->Asset.FactionID)
- return false;
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM:
- // miscValue1 = itemid miscValue2 = itemSlot
- if (!miscValue1 || miscValue2 != achievementCriteria->Entry->Asset.ItemSlot)
- return false;
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT:
- case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT:
- {
- // miscValue1 = itemid miscValue2 = diced value
- if (!miscValue1 || miscValue2 != achievementCriteria->Entry->Asset.RollValue)
- return false;
-
- ItemTemplate const* proto = sObjectMgr->GetItemTemplate(uint32(miscValue1));
- if (!proto)
- return false;
- break;
- }
- case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE:
- if (!miscValue1 || miscValue1 != achievementCriteria->Entry->Asset.EmoteID)
- return false;
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_DAMAGE_DONE:
- case ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE:
- if (!miscValue1)
- return false;
-
- if (achievementCriteria->Entry->FailEvent == ACHIEVEMENT_CRITERIA_CONDITION_BG_MAP)
- {
- if (!referencePlayer->InBattleground())
- return false;
+ WorldPackets::Achievement::GuildCriteriaProgress& guildCriteriaProgress = guildCriteriaUpdate.Progress[0];
+ guildCriteriaProgress.CriteriaID = entry->ID;
+ guildCriteriaProgress.DateCreated = 0;
+ guildCriteriaProgress.DateStarted = 0;
+ guildCriteriaProgress.DateUpdated = progress->Date;
+ guildCriteriaProgress.Quantity = progress->Counter;
+ guildCriteriaProgress.PlayerGUID = progress->PlayerGUID;
+ guildCriteriaProgress.Flags = 0;
- // map specific case (BG in fact) expected player targeted damage/heal
- if (!unit || unit->GetTypeId() != TYPEID_PLAYER)
- return false;
- }
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_USE_GAMEOBJECT:
- case ACHIEVEMENT_CRITERIA_TYPE_FISH_IN_GAMEOBJECT:
- if (!miscValue1 || miscValue1 != achievementCriteria->Entry->Asset.GameObjectID)
- return false;
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS:
- case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LINE:
- if (miscValue1 && miscValue1 != achievementCriteria->Entry->Asset.SkillID)
- return false;
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_LOOT_EPIC_ITEM:
- case ACHIEVEMENT_CRITERIA_TYPE_RECEIVE_EPIC_ITEM:
- {
- if (!miscValue1)
- return false;
- ItemTemplate const* proto = sObjectMgr->GetItemTemplate(uint32(miscValue1));
- if (!proto || proto->GetQuality() < ITEM_QUALITY_EPIC)
- return false;
- break;
- }
- case ACHIEVEMENT_CRITERIA_TYPE_HK_CLASS:
- if (!miscValue1 || miscValue1 != achievementCriteria->Entry->Asset.ClassID)
- return false;
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_HK_RACE:
- if (!miscValue1 || miscValue1 != achievementCriteria->Entry->Asset.RaceID)
- return false;
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE:
- if (!miscValue1 || miscValue1 != achievementCriteria->Entry->Asset.ObjectiveId)
- return false;
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL_AT_AREA:
- if (!miscValue1 || miscValue1 != achievementCriteria->Entry->Asset.AreaID)
- return false;
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_CURRENCY:
- if (!miscValue1 || !miscValue2 || int64(miscValue2) < 0
- || miscValue1 != achievementCriteria->Entry->Asset.CurrencyID)
- return false;
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_WIN_ARENA:
- if (miscValue1 != achievementCriteria->Entry->Asset.MapID)
- return false;
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_TEAM_RATING:
- return false;
- case ACHIEVEMENT_CRITERIA_TYPE_PLACE_GARRISON_BUILDING:
- if (miscValue1 != achievementCriteria->Entry->Asset.GarrBuildingID)
- return false;
- break;
- default:
- break;
- }
- return true;
+ _owner->BroadcastPacketIfTrackingAchievement(guildCriteriaUpdate.Write(), entry->ID);
}
-template<class T>
-bool AchievementMgr<T>::AdditionalRequirementsSatisfied(ModifierTreeNode const* tree, uint64 miscValue1, uint64 miscValue2, Unit const* unit, Player* referencePlayer) const
+void GuildAchievementMgr::SendCriteriaProgressRemoved(uint32 criteriaId)
{
- for (ModifierTreeNode const* node : tree->Children)
- if (!AdditionalRequirementsSatisfied(node, miscValue1, miscValue2, unit, referencePlayer))
- return false;
-
- uint32 reqType = tree->Entry->Type;
- if (!reqType)
- return true;
-
- uint32 reqValue = tree->Entry->Asset[0];
+ WorldPackets::Achievement::GuildCriteriaDeleted guildCriteriaDeleted;
+ guildCriteriaDeleted.GuildGUID = _owner->GetGUID();
+ guildCriteriaDeleted.CriteriaID = criteriaId;
+ SendPacket(guildCriteriaDeleted.Write());
+}
- switch (AchievementCriteriaAdditionalCondition(reqType))
+void GuildAchievementMgr::SendAchievementEarned(AchievementEntry const* achievement) const
+{
+ if (achievement->Flags & (ACHIEVEMENT_FLAG_REALM_FIRST_KILL | ACHIEVEMENT_FLAG_REALM_FIRST_REACH))
{
- case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_CREATURE_ENTRY: // 4
- if (!unit || unit->GetEntry() != reqValue)
- return false;
- break;
- case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_MUST_BE_PLAYER: // 5
- if (!unit || unit->GetTypeId() != TYPEID_PLAYER)
- return false;
- break;
- case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_MUST_BE_DEAD: // 6
- if (!unit || unit->IsAlive())
- return false;
- break;
- case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_MUST_BE_ENEMY: // 7
- if (!unit || !referencePlayer->IsHostileTo(unit))
- return false;
- break;
- case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_SOURCE_HAS_AURA: // 8
- if (!referencePlayer->HasAura(reqValue))
- return false;
- break;
- case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_HAS_AURA: // 10
- if (!unit || !unit->HasAura(reqValue))
- return false;
- case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_HAS_AURA_TYPE: // 11
- if (!unit || !unit->HasAuraType(AuraType(reqValue)))
- return false;
- break;
- case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_ITEM_QUALITY_MIN: // 14
- {
- // miscValue1 is itemid
- ItemTemplate const* const item = sObjectMgr->GetItemTemplate(uint32(miscValue1));
- if (!item || item->GetQuality() < reqValue)
- return false;
- break;
- }
- case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_ITEM_QUALITY_EQUALS: // 15
- {
- // miscValue1 is itemid
- ItemTemplate const* const item = sObjectMgr->GetItemTemplate(uint32(miscValue1));
- if (!item || item->GetQuality() != reqValue)
- return false;
- break;
- }
- case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_SOURCE_AREA_OR_ZONE: // 17
- {
- uint32 zoneId, areaId;
- referencePlayer->GetZoneAndAreaId(zoneId, areaId);
- if (zoneId != reqValue && areaId != reqValue)
- return false;
- break;
- }
- case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_AREA_OR_ZONE: // 18
- {
- if (!unit)
- return false;
- uint32 zoneId, areaId;
- unit->GetZoneAndAreaId(zoneId, areaId);
- if (zoneId != reqValue && areaId != reqValue)
- return false;
- break;
- }
- case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_MAP_DIFFICULTY: // 20
- if (uint32(referencePlayer->GetMap()->GetDifficultyID()) != reqValue)
- return false;
- break;
- case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_ARENA_TYPE:
- {
- Battleground* bg = referencePlayer->GetBattleground();
- if (!bg || !bg->isArena() || bg->GetArenaType() != reqValue)
- return false;
- break;
- }
- case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_SOURCE_RACE: // 25
- if (referencePlayer->getRace() != reqValue)
- return false;
- break;
- case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_SOURCE_CLASS: // 26
- if (referencePlayer->getClass() != reqValue)
- return false;
- break;
- case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_RACE: // 27
- if (!unit || unit->GetTypeId() != TYPEID_PLAYER || unit->getRace() != reqValue)
- return false;
- break;
- case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_CLASS: // 28
- if (!unit || unit->GetTypeId() != TYPEID_PLAYER || unit->getClass() != reqValue)
- return false;
- break;
- case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_MAX_GROUP_MEMBERS: // 29
- if (referencePlayer->GetGroup() && referencePlayer->GetGroup()->GetMembersCount() >= reqValue)
- return false;
- break;
- case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_CREATURE_TYPE: // 30
- {
- if (!unit)
- return false;
- Creature const* const creature = unit->ToCreature();
- if (!creature || creature->GetCreatureType() != reqValue)
- return false;
- break;
- }
- case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_SOURCE_MAP: // 32
- if (referencePlayer->GetMapId() != reqValue)
- return false;
- break;
- case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TITLE_BIT_INDEX: // 38
- // miscValue1 is title's bit index
- if (miscValue1 != reqValue)
- return false;
- break;
- case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_SOURCE_LEVEL: // 39
- if (referencePlayer->getLevel() != reqValue)
- return false;
- break;
- case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_LEVEL: // 40
- if (!unit || unit->getLevel() != reqValue)
- return false;
- break;
- case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_ZONE: // 41
- if (!unit || unit->GetZoneId() != reqValue)
- return false;
- break;
- case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_HEALTH_PERCENT_BELOW: // 46
- if (!unit || unit->GetHealthPct() >= reqValue)
- return false;
- break;
- case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_BATTLE_PET_SPECIES: // 91
- if (miscValue1 != reqValue)
- return false;
- break;
- case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_GARRISON_FOLLOWER_QUALITY: // 145
- {
- if (!referencePlayer)
- return false;
- Garrison* garrison = referencePlayer->GetGarrison();
- if (!garrison)
- return false;
- Garrison::Follower const* follower = garrison->GetFollower(miscValue1);
- if (!follower || follower->PacketInfo.Quality != reqValue)
- return false;
-
- break;
- }
- case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_GARRISON_FOLLOWER_LEVEL: // 146
- {
- if (!referencePlayer)
- return false;
- Garrison* garrison = referencePlayer->GetGarrison();
- if (!garrison)
- return false;
- Garrison::Follower const* follower = garrison->GetFollower(miscValue1);
- if (!follower || follower->PacketInfo.FollowerLevel < reqValue)
- return false;
-
- break;
- }
- case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_GARRISON_FOLLOWER_ILVL: // 184
- {
- if (!referencePlayer)
- return false;
- Garrison* garrison = referencePlayer->GetGarrison();
- if (!garrison)
- return false;
- Garrison::Follower const* follower = garrison->GetFollower(miscValue1);
- if (!follower || follower->GetItemLevel() < reqValue)
- return false;
- break;
- }
- default:
- break;
+ // broadcast realm first reached
+ WorldPackets::Achievement::ServerFirstAchievement serverFirstAchievement;
+ serverFirstAchievement.Name = _owner->GetName();
+ serverFirstAchievement.PlayerGUID = _owner->GetGUID();
+ serverFirstAchievement.AchievementID = achievement->ID;
+ serverFirstAchievement.GuildAchievement = true;
+ sWorld->SendGlobalMessage(serverFirstAchievement.Write());
}
- return true;
+
+ WorldPackets::Achievement::GuildAchievementEarned guildAchievementEarned;
+ guildAchievementEarned.AchievementID = achievement->ID;
+ guildAchievementEarned.GuildGUID = _owner->GetGUID();
+ guildAchievementEarned.TimeEarned = time(NULL);
+ SendPacket(guildAchievementEarned.Write());
}
-template class TC_GAME_API AchievementMgr<Player>;
-template class TC_GAME_API AchievementMgr<Guild>;
+void GuildAchievementMgr::SendPacket(WorldPacket const* data) const
+{
+ _owner->BroadcastPacket(data);
+}
-char const* AchievementGlobalMgr::GetCriteriaTypeString(uint32 type)
+CriteriaList const& GuildAchievementMgr::GetCriteriaByType(CriteriaTypes type) const
{
- return GetCriteriaTypeString(AchievementCriteriaTypes(type));
+ return sCriteriaMgr->GetGuildCriteriaByType(type);
}
-char const* AchievementGlobalMgr::GetCriteriaTypeString(AchievementCriteriaTypes type)
+std::string PlayerAchievementMgr::GetOwnerInfo() const
{
- switch (type)
- {
- case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE:
- return "KILL_CREATURE";
- case ACHIEVEMENT_CRITERIA_TYPE_WIN_BG:
- return "TYPE_WIN_BG";
- case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ARCHAEOLOGY_PROJECTS:
- return "COMPLETE_RESEARCH";
- case ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL:
- return "REACH_LEVEL";
- case ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL:
- return "REACH_SKILL_LEVEL";
- case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT:
- return "COMPLETE_ACHIEVEMENT";
- case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT:
- return "COMPLETE_QUEST_COUNT";
- case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST_DAILY:
- return "COMPLETE_DAILY_QUEST_DAILY";
- case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE:
- return "COMPLETE_QUESTS_IN_ZONE";
- case ACHIEVEMENT_CRITERIA_TYPE_CURRENCY:
- return "CURRENCY";
- case ACHIEVEMENT_CRITERIA_TYPE_DAMAGE_DONE:
- return "DAMAGE_DONE";
- case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST:
- return "COMPLETE_DAILY_QUEST";
- case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND:
- return "COMPLETE_BATTLEGROUND";
- case ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP:
- return "DEATH_AT_MAP";
- case ACHIEVEMENT_CRITERIA_TYPE_DEATH:
- return "DEATH";
- case ACHIEVEMENT_CRITERIA_TYPE_DEATH_IN_DUNGEON:
- return "DEATH_IN_DUNGEON";
- case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_RAID:
- return "COMPLETE_RAID";
- case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE:
- return "KILLED_BY_CREATURE";
- case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER:
- return "KILLED_BY_PLAYER";
- case ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING:
- return "FALL_WITHOUT_DYING";
- case ACHIEVEMENT_CRITERIA_TYPE_DEATHS_FROM:
- return "DEATHS_FROM";
- case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST:
- return "COMPLETE_QUEST";
- case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET:
- return "BE_SPELL_TARGET";
- case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL:
- return "CAST_SPELL";
- case ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE:
- return "BG_OBJECTIVE_CAPTURE";
- case ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL_AT_AREA:
- return "HONORABLE_KILL_AT_AREA";
- case ACHIEVEMENT_CRITERIA_TYPE_WIN_ARENA:
- return "WIN_ARENA";
- case ACHIEVEMENT_CRITERIA_TYPE_PLAY_ARENA:
- return "PLAY_ARENA";
- case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL:
- return "LEARN_SPELL";
- case ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL:
- return "HONORABLE_KILL";
- case ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM:
- return "OWN_ITEM";
- case ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA:
- return "WIN_RATED_ARENA";
- case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_TEAM_RATING:
- return "HIGHEST_TEAM_RATING";
- case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_PERSONAL_RATING:
- return "HIGHEST_PERSONAL_RATING";
- case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL:
- return "LEARN_SKILL_LEVEL";
- case ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM:
- return "USE_ITEM";
- case ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM:
- return "LOOT_ITEM";
- case ACHIEVEMENT_CRITERIA_TYPE_EXPLORE_AREA:
- return "EXPLORE_AREA";
- case ACHIEVEMENT_CRITERIA_TYPE_OWN_RANK:
- return "OWN_RANK";
- case ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT:
- return "BUY_BANK_SLOT";
- case ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION:
- return "GAIN_REPUTATION";
- case ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION:
- return "GAIN_EXALTED_REPUTATION";
- case ACHIEVEMENT_CRITERIA_TYPE_VISIT_BARBER_SHOP:
- return "VISIT_BARBER_SHOP";
- case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM:
- return "EQUIP_EPIC_ITEM";
- case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT:
- return "ROLL_NEED_ON_LOOT";
- case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT:
- return "GREED_ON_LOOT";
- case ACHIEVEMENT_CRITERIA_TYPE_HK_CLASS:
- return "HK_CLASS";
- case ACHIEVEMENT_CRITERIA_TYPE_HK_RACE:
- return "HK_RACE";
- case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE:
- return "DO_EMOTE";
- case ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE:
- return "HEALING_DONE";
- case ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS:
- return "GET_KILLING_BLOWS";
- case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM:
- return "EQUIP_ITEM";
- case ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_VENDORS:
- return "MONEY_FROM_VENDORS";
- case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TALENTS:
- return "GOLD_SPENT_FOR_TALENTS";
- case ACHIEVEMENT_CRITERIA_TYPE_NUMBER_OF_TALENT_RESETS:
- return "NUMBER_OF_TALENT_RESETS";
- case ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD:
- return "MONEY_FROM_QUEST_REWARD";
- case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TRAVELLING:
- return "GOLD_SPENT_FOR_TRAVELLING";
- case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_AT_BARBER:
- return "GOLD_SPENT_AT_BARBER";
- case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_MAIL:
- return "GOLD_SPENT_FOR_MAIL";
- case ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY:
- return "LOOT_MONEY";
- case ACHIEVEMENT_CRITERIA_TYPE_USE_GAMEOBJECT:
- return "USE_GAMEOBJECT";
- case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2:
- return "BE_SPELL_TARGET2";
- case ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL:
- return "SPECIAL_PVP_KILL";
- case ACHIEVEMENT_CRITERIA_TYPE_FISH_IN_GAMEOBJECT:
- return "FISH_IN_GAMEOBJECT";
- case ACHIEVEMENT_CRITERIA_TYPE_ON_LOGIN:
- return "ON_LOGIN";
- case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS:
- return "LEARN_SKILLLINE_SPELLS";
- case ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL:
- return "WIN_DUEL";
- case ACHIEVEMENT_CRITERIA_TYPE_LOSE_DUEL:
- return "LOSE_DUEL";
- case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE:
- return "KILL_CREATURE_TYPE";
- case ACHIEVEMENT_CRITERIA_TYPE_GOLD_EARNED_BY_AUCTIONS:
- return "GOLD_EARNED_BY_AUCTIONS";
- case ACHIEVEMENT_CRITERIA_TYPE_CREATE_AUCTION:
- return "CREATE_AUCTION";
- case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_BID:
- return "HIGHEST_AUCTION_BID";
- case ACHIEVEMENT_CRITERIA_TYPE_WON_AUCTIONS:
- return "WON_AUCTIONS";
- case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_SOLD:
- return "HIGHEST_AUCTION_SOLD";
- case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_GOLD_VALUE_OWNED:
- return "HIGHEST_GOLD_VALUE_OWNED";
- case ACHIEVEMENT_CRITERIA_TYPE_GAIN_REVERED_REPUTATION:
- return "GAIN_REVERED_REPUTATION";
- case ACHIEVEMENT_CRITERIA_TYPE_GAIN_HONORED_REPUTATION:
- return "GAIN_HONORED_REPUTATION";
- case ACHIEVEMENT_CRITERIA_TYPE_KNOWN_FACTIONS:
- return "KNOWN_FACTIONS";
- case ACHIEVEMENT_CRITERIA_TYPE_LOOT_EPIC_ITEM:
- return "LOOT_EPIC_ITEM";
- case ACHIEVEMENT_CRITERIA_TYPE_RECEIVE_EPIC_ITEM:
- return "RECEIVE_EPIC_ITEM";
- case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED:
- return "ROLL_NEED";
- case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED:
- return "ROLL_GREED";
- case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_DEALT:
- return "HIT_DEALT";
- case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_RECEIVED:
- return "HIT_RECEIVED";
- case ACHIEVEMENT_CRITERIA_TYPE_TOTAL_DAMAGE_RECEIVED:
- return "TOTAL_DAMAGE_RECEIVED";
- case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEAL_CAST:
- return "HIGHEST_HEAL_CAST";
- case ACHIEVEMENT_CRITERIA_TYPE_TOTAL_HEALING_RECEIVED:
- return "TOTAL_HEALING_RECEIVED";
- case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEALING_RECEIVED:
- return "HIGHEST_HEALING_RECEIVED";
- case ACHIEVEMENT_CRITERIA_TYPE_QUEST_ABANDONED:
- return "QUEST_ABANDONED";
- case ACHIEVEMENT_CRITERIA_TYPE_FLIGHT_PATHS_TAKEN:
- return "FLIGHT_PATHS_TAKEN";
- case ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE:
- return "LOOT_TYPE";
- case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2:
- return "CAST_SPELL2";
- case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LINE:
- return "LEARN_SKILL_LINE";
- case ACHIEVEMENT_CRITERIA_TYPE_EARN_HONORABLE_KILL:
- return "EARN_HONORABLE_KILL";
- case ACHIEVEMENT_CRITERIA_TYPE_ACCEPTED_SUMMONINGS:
- return "ACCEPTED_SUMMONINGS";
- case ACHIEVEMENT_CRITERIA_TYPE_EARN_ACHIEVEMENT_POINTS:
- return "EARN_ACHIEVEMENT_POINTS";
- case ACHIEVEMENT_CRITERIA_TYPE_USE_LFD_TO_GROUP_WITH_PLAYERS:
- return "USE_LFD_TO_GROUP_WITH_PLAYERS";
- case ACHIEVEMENT_CRITERIA_TYPE_SPENT_GOLD_GUILD_REPAIRS:
- return "SPENT_GOLD_GUILD_REPAIRS";
- case ACHIEVEMENT_CRITERIA_TYPE_REACH_GUILD_LEVEL:
- return "REACH_GUILD_LEVEL";
- case ACHIEVEMENT_CRITERIA_TYPE_CRAFT_ITEMS_GUILD:
- return "CRAFT_ITEMS_GUILD";
- case ACHIEVEMENT_CRITERIA_TYPE_CATCH_FROM_POOL:
- return "CATCH_FROM_POOL";
- case ACHIEVEMENT_CRITERIA_TYPE_BUY_GUILD_BANK_SLOTS:
- return "BUY_GUILD_BANK_SLOTS";
- case ACHIEVEMENT_CRITERIA_TYPE_EARN_GUILD_ACHIEVEMENT_POINTS:
- return "EARN_GUILD_ACHIEVEMENT_POINTS";
- case ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_BATTLEGROUND:
- return "WIN_RATED_BATTLEGROUND";
- case ACHIEVEMENT_CRITERIA_TYPE_REACH_BG_RATING:
- return "REACH_BG_RATING";
- case ACHIEVEMENT_CRITERIA_TYPE_BUY_GUILD_TABARD:
- return "BUY_GUILD_TABARD";
- case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_GUILD:
- return "COMPLETE_QUESTS_GUILD";
- case ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILLS_GUILD:
- return "HONORABLE_KILLS_GUILD";
- case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE_GUILD:
- return "KILL_CREATURE_TYPE_GUILD";
- case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_GUILD_CHALLENGE_TYPE:
- return "GUILD_CHALLENGE_TYPE";
- case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_GUILD_CHALLENGE:
- return "GUILD_CHALLENGE";
- case ACHIEVEMENT_CRITERIA_TYPE_LFR_DUNGEONS_COMPLETED:
- return "LFR_DUNGEONS_COMPLETED";
- case ACHIEVEMENT_CRITERIA_TYPE_LFR_LEAVES:
- return "LFR_LEAVES";
- case ACHIEVEMENT_CRITERIA_TYPE_LFR_VOTE_KICKS_INITIATED_BY_PLAYER:
- return "LFR_VOTE_KICKS_INITIATED_BY_PLAYER";
- case ACHIEVEMENT_CRITERIA_TYPE_LFR_VOTE_KICKS_NOT_INIT_BY_PLAYER:
- return "LFR_VOTE_KICKS_NOT_INIT_BY_PLAYER";
- case ACHIEVEMENT_CRITERIA_TYPE_BE_KICKED_FROM_LFR:
- return "BE_KICKED_FROM_LFR";
- case ACHIEVEMENT_CRITERIA_TYPE_COUNT_OF_LFR_QUEUE_BOOSTS_BY_TANK:
- return "COUNT_OF_LFR_QUEUE_BOOSTS_BY_TANK";
- case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_SCENARIO_COUNT:
- return "COMPLETE_SCENARIO_COUNT";
- case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_SCENARIO:
- return "COMPLETE_SCENARIO";
- case ACHIEVEMENT_CRITERIA_TYPE_OWN_BATTLE_PET:
- return "OWN_BATTLE_PET";
- case ACHIEVEMENT_CRITERIA_TYPE_OWN_BATTLE_PET_COUNT:
- return "OWN_BATTLE_PET_COUNT";
- case ACHIEVEMENT_CRITERIA_TYPE_CAPTURE_BATTLE_PET:
- return "CAPTURE_BATTLE_PET";
- case ACHIEVEMENT_CRITERIA_TYPE_WIN_PET_BATTLE:
- return "WIN_PET_BATTLE";
- case ACHIEVEMENT_CRITERIA_TYPE_LEVEL_BATTLE_PET:
- return "LEVEL_BATTLE_PET";
- case ACHIEVEMENT_CRITERIA_TYPE_CAPTURE_BATTLE_PET_CREDIT:
- return "CAPTURE_BATTLE_PET_CREDIT";
- case ACHIEVEMENT_CRITERIA_TYPE_LEVEL_BATTLE_PET_CREDIT:
- return "LEVEL_BATTLE_PET_CREDIT";
- case ACHIEVEMENT_CRITERIA_TYPE_ENTER_AREA:
- return "ENTER_AREA";
- case ACHIEVEMENT_CRITERIA_TYPE_LEAVE_AREA:
- return "LEAVE_AREA";
- case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DUNGEON_ENCOUNTER:
- return "COMPLETE_DUNGEON_ENCOUNTER";
- case ACHIEVEMENT_CRITERIA_TYPE_PLACE_GARRISON_BUILDING:
- return "PLACE_GARRISON_BUILDING";
- case ACHIEVEMENT_CRITERIA_TYPE_UPGRADE_GARRISON_BUILDING:
- return "UPGRADE_GARRISON_BUILDING";
- case ACHIEVEMENT_CRITERIA_TYPE_CONSTRUCT_GARRISON_BUILDING:
- return "CONSTRUCT_GARRISON_BUILDING";
- case ACHIEVEMENT_CRITERIA_TYPE_UPGRADE_GARRISON:
- return "UPGRADE_GARRISON";
- case ACHIEVEMENT_CRITERIA_TYPE_START_GARRISON_MISSION:
- return "START_GARRISON_MISSION";
- case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_GARRISON_MISSION_COUNT:
- return "COMPLETE_GARRISON_MISSION_COUNT";
- case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_GARRISON_MISSION:
- return "COMPLETE_GARRISON_MISSION";
- case ACHIEVEMENT_CRITERIA_TYPE_RECRUIT_GARRISON_FOLLOWER_COUNT:
- return "RECRUIT_GARRISON_FOLLOWER_COUNT";
- case ACHIEVEMENT_CRITERIA_TYPE_LEARN_GARRISON_BLUEPRINT_COUNT:
- return "LEARN_GARRISON_BLUEPRINT_COUNT";
- case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_GARRISON_SHIPMENT:
- return "COMPLETE_GARRISON_SHIPMENT";
- case ACHIEVEMENT_CRITERIA_TYPE_RAISE_GARRISON_FOLLOWER_ITEM_LEVEL:
- return "RAISE_GARRISON_FOLLOWER_ITEM_LEVEL";
- case ACHIEVEMENT_CRITERIA_TYPE_RAISE_GARRISON_FOLLOWER_LEVEL:
- return "RAISE_GARRISON_FOLLOWER_LEVEL";
- case ACHIEVEMENT_CRITERIA_TYPE_OWN_TOY:
- return "OWN_TOY";
- case ACHIEVEMENT_CRITERIA_TYPE_OWN_TOY_COUNT:
- return "OWN_TOY_COUNT";
- case ACHIEVEMENT_CRITERIA_TYPE_RECRUIT_GARRISON_FOLLOWER:
- return "RECRUIT_GARRISON_FOLLOWER";
- case ACHIEVEMENT_CRITERIA_TYPE_OWN_HEIRLOOMS:
- return "OWN_HEIRLOOMS";
- }
- return "MISSING_TYPE";
+ return Trinity::StringFormat("%s %s", _owner->GetGUID().ToString().c_str(), _owner->GetName().c_str());
}
-AchievementGlobalMgr* AchievementGlobalMgr::instance()
+std::string GuildAchievementMgr::GetOwnerInfo() const
+{
+ return Trinity::StringFormat("Guild ID " UI64FMTD " %s", _owner->GetId(), _owner->GetName().c_str());
+}
+
+AchievementGlobalMgr* AchievementGlobalMgr::Instance()
{
static AchievementGlobalMgr instance;
return &instance;
}
-//==========================================================
-AchievementGlobalMgr::~AchievementGlobalMgr()
+std::vector<AchievementEntry const*> const* AchievementGlobalMgr::GetAchievementByReferencedId(uint32 id) const
{
- for (AchievementCriteriaTreeMap::iterator itr = _achievementCriteriaTrees.begin(); itr != _achievementCriteriaTrees.end(); ++itr)
- delete itr->second;
-
- for (AchievementCriteriaMap::iterator itr = _achievementCriteria.begin(); itr != _achievementCriteria.end(); ++itr)
- delete itr->second;
-
- for (ModifierTreeMap::iterator itr = _criteriaModifiers.begin(); itr != _criteriaModifiers.end(); ++itr)
- delete itr->second;
+ auto itr = _achievementListByReferencedId.find(id);
+ return itr != _achievementListByReferencedId.end() ? &itr->second : NULL;
}
-void AchievementGlobalMgr::LoadAchievementCriteriaModifiersTree()
+AchievementReward const* AchievementGlobalMgr::GetAchievementReward(AchievementEntry const* achievement) const
{
- uint32 oldMSTime = getMSTime();
-
- if (sModifierTreeStore.GetNumRows() == 0)
- {
- TC_LOG_ERROR("server.loading", ">> Loaded 0 achievement criteria modifiers.");
- return;
- }
+ auto iter = _achievementRewards.find(achievement->ID);
+ return iter != _achievementRewards.end() ? &iter->second : NULL;
+}
- // Load modifier tree nodes
- for (uint32 i = 0; i < sModifierTreeStore.GetNumRows(); ++i)
- {
- ModifierTreeEntry const* tree = sModifierTreeStore.LookupEntry(i);
- if (!tree)
- continue;
+AchievementRewardLocale const* AchievementGlobalMgr::GetAchievementRewardLocale(AchievementEntry const* achievement) const
+{
+ auto iter = _achievementRewardLocales.find(achievement->ID);
+ return iter != _achievementRewardLocales.end() ? &iter->second : NULL;
+}
- ModifierTreeNode* node = new ModifierTreeNode();
- node->Entry = tree;
- _criteriaModifiers[node->Entry->ID] = node;
- }
+bool AchievementGlobalMgr::IsRealmCompleted(AchievementEntry const* achievement) const
+{
+ auto itr = _allCompletedAchievements.find(achievement->ID);
+ if (itr == _allCompletedAchievements.end())
+ return false;
- // Build tree
- for (auto itr = _criteriaModifiers.begin(); itr != _criteriaModifiers.end(); ++itr)
- {
- if (!itr->second->Entry->Parent)
- continue;
+ if (itr->second == std::chrono::system_clock::time_point::min())
+ return false;
- auto parent = _criteriaModifiers.find(itr->second->Entry->Parent);
- if (parent != _criteriaModifiers.end())
- parent->second->Children.push_back(itr->second);
- }
+ // Allow completing the realm first kill for entire minute after first person did it
+ // it may allow more than one group to achieve it (highly unlikely)
+ // but apparently this is how blizz handles it as well
+ if (achievement->Flags & ACHIEVEMENT_FLAG_REALM_FIRST_KILL)
+ return (std::chrono::system_clock::now() - itr->second) > Minutes(1);
- TC_LOG_INFO("server.loading", ">> Loaded %u achievement criteria modifiers in %u ms", uint32(_criteriaModifiers.size()), GetMSTimeDiffToNow(oldMSTime));
+ return true;
}
-void AchievementGlobalMgr::LoadAchievementCriteriaList()
+void AchievementGlobalMgr::SetRealmCompleted(AchievementEntry const* achievement)
{
- uint32 oldMSTime = getMSTime();
-
- if (sCriteriaTreeStore.GetNumRows() == 0)
- {
- TC_LOG_ERROR("server.loading", ">> Loaded 0 achievement criteria.");
+ if (IsRealmCompleted(achievement))
return;
- }
-
- std::unordered_map<uint32 /*criteriaTreeID*/, AchievementEntry const*> achievementCriteriaTreeIds;
- for (uint32 i = 0; i < sAchievementStore.GetNumRows(); ++i)
- if (AchievementEntry const* achievement = sAchievementStore.LookupEntry(i))
- if (achievement->CriteriaTree)
- achievementCriteriaTreeIds[achievement->CriteriaTree] = achievement;
-
- // Load criteria tree nodes
- for (uint32 i = 0; i < sCriteriaTreeStore.GetNumRows(); ++i)
- {
- CriteriaTreeEntry const* tree = sCriteriaTreeStore.LookupEntry(i);
- if (!tree)
- continue;
-
- // Find linked achievement
- auto achievementItr = achievementCriteriaTreeIds.find(tree->ID);
- CriteriaTreeEntry const* cur = tree;
- while (achievementItr == achievementCriteriaTreeIds.end())
- {
- if (!cur->Parent)
- break;
-
- cur = sCriteriaTreeStore.LookupEntry(cur->Parent);
- if (!cur)
- break;
-
- achievementItr = achievementCriteriaTreeIds.find(cur->ID);
- }
-
- if (achievementItr == achievementCriteriaTreeIds.end())
- continue;
-
- AchievementCriteriaTree* achievementCriteriaTree = new AchievementCriteriaTree();
- achievementCriteriaTree->ID = i;
- achievementCriteriaTree->Achievement = achievementItr->second;
- achievementCriteriaTree->Entry = tree;
-
- _achievementCriteriaTrees[achievementCriteriaTree->Entry->ID] = achievementCriteriaTree;
- }
-
- // Build tree
- for (auto itr = _achievementCriteriaTrees.begin(); itr != _achievementCriteriaTrees.end(); ++itr)
- {
- if (!itr->second->Entry->Parent)
- continue;
-
- auto parent = _achievementCriteriaTrees.find(itr->second->Entry->Parent);
- if (parent != _achievementCriteriaTrees.end())
- {
- parent->second->Children.push_back(itr->second);
- while (parent != _achievementCriteriaTrees.end())
- {
- auto cur = parent;
- parent = _achievementCriteriaTrees.find(parent->second->Entry->Parent);
- if (parent == _achievementCriteriaTrees.end())
- {
- if (sCriteriaStore.LookupEntry(itr->second->Entry->CriteriaID))
- _achievementCriteriaTreeByCriteria[itr->second->Entry->CriteriaID].push_back(cur->second);
- }
- }
- }
- else if (sCriteriaStore.LookupEntry(itr->second->Entry->CriteriaID))
- _achievementCriteriaTreeByCriteria[itr->second->Entry->CriteriaID].push_back(itr->second);
- }
-
- // Load criteria
- uint32 criterias = 0;
- uint32 guildCriterias = 0;
- for (uint32 i = 0; i < sCriteriaStore.GetNumRows(); ++i)
- {
- CriteriaEntry const* criteria = sCriteriaStore.LookupEntry(i);
- if (!criteria)
- continue;
-
- auto treeItr = _achievementCriteriaTreeByCriteria.find(i);
- if (treeItr == _achievementCriteriaTreeByCriteria.end())
- continue;
-
- AchievementCriteria* achievementCriteria = new AchievementCriteria();
- achievementCriteria->ID = i;
- achievementCriteria->Entry = criteria;
- auto mod = _criteriaModifiers.find(criteria->ModifierTreeId);
- if (mod != _criteriaModifiers.end())
- achievementCriteria->Modifier = mod->second;
-
- _achievementCriteria[achievementCriteria->ID] = achievementCriteria;
-
- for (AchievementCriteriaTree const* tree : treeItr->second)
- {
- if (tree->Achievement->Flags & ACHIEVEMENT_FLAG_GUILD)
- achievementCriteria->FlagsCu |= ACHIEVEMENT_CRITERIA_FLAG_CU_GUILD;
- else if (tree->Achievement->Flags & ACHIEVEMENT_FLAG_ACCOUNT)
- achievementCriteria->FlagsCu |= ACHIEVEMENT_CRITERIA_FLAG_CU_ACCOUNT;
- else
- achievementCriteria->FlagsCu |= ACHIEVEMENT_CRITERIA_FLAG_CU_PLAYER;
- }
-
- if (achievementCriteria->FlagsCu & ACHIEVEMENT_CRITERIA_FLAG_CU_GUILD)
- {
- ++guildCriterias;
- _guildAchievementCriteriasByType[criteria->Type].push_back(achievementCriteria);
- }
-
- if (achievementCriteria->FlagsCu & (ACHIEVEMENT_CRITERIA_FLAG_CU_PLAYER | ACHIEVEMENT_CRITERIA_FLAG_CU_ACCOUNT))
- {
- ++criterias;
- _achievementCriteriasByType[criteria->Type].push_back(achievementCriteria);
- }
- if (criteria->StartTimer)
- _achievementCriteriasByTimedType[criteria->StartEvent].push_back(achievementCriteria);
- }
-
- for (auto& p : _achievementCriteriaTrees)
- const_cast<AchievementCriteriaTree*>(p.second)->Criteria = GetAchievementCriteria(p.second->Entry->CriteriaID);
-
- TC_LOG_INFO("server.loading", ">> Loaded %u achievement criteria and %u guild achievement crieteria in %u ms.", criterias, guildCriterias, GetMSTimeDiffToNow(oldMSTime));
+ _allCompletedAchievements[achievement->ID] = std::chrono::system_clock::now();
}
+//==========================================================
void AchievementGlobalMgr::LoadAchievementReferenceList()
{
uint32 oldMSTime = getMSTime();
@@ -3081,7 +999,7 @@ void AchievementGlobalMgr::LoadAchievementReferenceList()
for (uint32 entryId = 0; entryId < sAchievementStore.GetNumRows(); ++entryId)
{
- AchievementEntry const* achievement = sAchievementMgr->GetAchievement(entryId);
+ AchievementEntry const* achievement = sAchievementStore.LookupEntry(entryId);
if (!achievement || !achievement->SharesCriteria)
continue;
@@ -3090,77 +1008,23 @@ void AchievementGlobalMgr::LoadAchievementReferenceList()
}
// Once Bitten, Twice Shy (10 player) - Icecrown Citadel
- if (AchievementEntry const* achievement = sAchievementMgr->GetAchievement(4539))
+ if (AchievementEntry const* achievement = sAchievementStore.LookupEntry(4539))
const_cast<AchievementEntry*>(achievement)->MapID = 631; // Correct map requirement (currently has Ulduar); 6.0.3 note - it STILL has ulduar requirement
TC_LOG_INFO("server.loading", ">> Loaded %u achievement references in %u ms.", count, GetMSTimeDiffToNow(oldMSTime));
}
-void AchievementGlobalMgr::LoadAchievementCriteriaData()
-{
- uint32 oldMSTime = getMSTime();
-
- _criteriaDataMap.clear(); // need for reload case
-
- QueryResult result = WorldDatabase.Query("SELECT criteria_id, type, value1, value2, ScriptName FROM achievement_criteria_data");
-
- if (!result)
- {
- TC_LOG_INFO("server.loading", ">> Loaded 0 additional achievement criteria data. DB table `achievement_criteria_data` is empty.");
- return;
- }
-
- uint32 count = 0;
-
- do
- {
- Field* fields = result->Fetch();
- uint32 criteria_id = fields[0].GetUInt32();
-
- AchievementCriteria const* criteria = sAchievementMgr->GetAchievementCriteria(criteria_id);
-
- if (!criteria)
- {
- TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` contains data for non-existing criteria (Entry: %u). Ignored.", criteria_id);
- continue;
- }
-
- uint32 dataType = fields[1].GetUInt8();
- std::string scriptName = fields[4].GetString();
- uint32 scriptId = 0;
- if (!scriptName.empty())
- {
- if (dataType != ACHIEVEMENT_CRITERIA_DATA_TYPE_SCRIPT)
- TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` contains a ScriptName for non-scripted data type (Entry: %u, type %u), useless data.", criteria_id, dataType);
- else
- scriptId = sObjectMgr->GetScriptId(scriptName);
- }
-
- AchievementCriteriaData data(dataType, fields[2].GetUInt32(), fields[3].GetUInt32(), scriptId);
-
- if (!data.IsValid(criteria))
- continue;
-
- // this will allocate empty data set storage
- AchievementCriteriaDataSet& dataSet = _criteriaDataMap[criteria_id];
- dataSet.SetCriteriaId(criteria_id);
-
- // add real data only for not NONE data types
- if (data.dataType != ACHIEVEMENT_CRITERIA_DATA_TYPE_NONE)
- dataSet.Add(data);
-
- // counting data by and data types
- ++count;
- }
- while (result->NextRow());
-
- TC_LOG_INFO("server.loading", ">> Loaded %u additional achievement criteria data in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
-}
-
void AchievementGlobalMgr::LoadCompletedAchievements()
{
uint32 oldMSTime = getMSTime();
+ // Populate _allCompletedAchievements with all realm first achievement ids to make multithreaded access safer
+ // while it will not prevent races, it will prevent crashes that happen because std::unordered_map key was added
+ // instead the only potential race will happen on value associated with the key
+ for (AchievementEntry const* achievement : sAchievementStore)
+ if (achievement->Flags & (ACHIEVEMENT_FLAG_REALM_FIRST_REACH | ACHIEVEMENT_FLAG_REALM_FIRST_KILL))
+ _allCompletedAchievements[achievement->ID] = std::chrono::system_clock::time_point::min();
+
QueryResult result = CharacterDatabase.Query("SELECT achievement FROM character_achievement GROUP BY achievement");
if (!result)
@@ -3173,21 +1037,21 @@ void AchievementGlobalMgr::LoadCompletedAchievements()
{
Field* fields = result->Fetch();
- uint16 achievementId = fields[0].GetUInt16();
- const AchievementEntry* achievement = sAchievementMgr->GetAchievement(achievementId);
+ uint32 achievementId = fields[0].GetUInt32();
+ AchievementEntry const* achievement = sAchievementStore.LookupEntry(achievementId);
if (!achievement)
{
// Remove non-existing achievements from all characters
- TC_LOG_ERROR("achievement", "Non-existing achievement %u data has been removed from the table `character_achievement`.", achievementId);
+ TC_LOG_ERROR("criteria.achievement", "Non-existing achievement %u data has been removed from the table `character_achievement`.", achievementId);
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_INVALID_ACHIEVMENT);
- stmt->setUInt16(0, uint16(achievementId));
+ stmt->setUInt32(0, achievementId);
CharacterDatabase.Execute(stmt);
continue;
}
else if (achievement->Flags & (ACHIEVEMENT_FLAG_REALM_FIRST_REACH | ACHIEVEMENT_FLAG_REALM_FIRST_KILL))
- _allCompletedAchievements[achievementId] = uint32(0xFFFFFFFF);
+ _allCompletedAchievements[achievementId] = std::chrono::system_clock::time_point::max();
}
while (result->NextRow());
@@ -3215,7 +1079,7 @@ void AchievementGlobalMgr::LoadRewards()
{
Field* fields = result->Fetch();
uint32 entry = fields[0].GetUInt32();
- AchievementEntry const* achievement = GetAchievement(entry);
+ AchievementEntry const* achievement = sAchievementStore.LookupEntry(entry);
if (!achievement)
{
TC_LOG_ERROR("sql.sql", "Table `achievement_reward` contains a wrong achievement entry (Entry: %u), ignored.", entry);
@@ -3223,85 +1087,85 @@ void AchievementGlobalMgr::LoadRewards()
}
AchievementReward reward;
- reward.titleId[0] = fields[1].GetUInt32();
- reward.titleId[1] = fields[2].GetUInt32();
- reward.itemId = fields[3].GetUInt32();
- reward.sender = fields[4].GetUInt32();
- reward.subject = fields[5].GetString();
- reward.text = fields[6].GetString();
- reward.mailTemplate = fields[7].GetUInt32();
+ reward.TitleId[0] = fields[1].GetUInt32();
+ reward.TitleId[1] = fields[2].GetUInt32();
+ reward.ItemId = fields[3].GetUInt32();
+ reward.SenderCreatureId = fields[4].GetUInt32();
+ reward.Subject = fields[5].GetString();
+ reward.Body = fields[6].GetString();
+ reward.MailTemplateId = fields[7].GetUInt32();
// must be title or mail at least
- if (!reward.titleId[0] && !reward.titleId[1] && !reward.sender)
+ if (!reward.TitleId[0] && !reward.TitleId[1] && !reward.SenderCreatureId)
{
TC_LOG_ERROR("sql.sql", "Table `achievement_reward` (Entry: %u) does not contain title or item reward data. Ignored.", entry);
continue;
}
- if (achievement->Faction == ACHIEVEMENT_FACTION_ANY && (!reward.titleId[0] ^ !reward.titleId[1]))
- TC_LOG_ERROR("sql.sql", "Table `achievement_reward` (Entry: %u) contains the title (A: %u H: %u) for only one team.", entry, reward.titleId[0], reward.titleId[1]);
+ if (achievement->Faction == ACHIEVEMENT_FACTION_ANY && (!reward.TitleId[0] ^ !reward.TitleId[1]))
+ TC_LOG_ERROR("sql.sql", "Table `achievement_reward` (Entry: %u) contains the title (A: %u H: %u) for only one team.", entry, reward.TitleId[0], reward.TitleId[1]);
- if (reward.titleId[0])
+ if (reward.TitleId[0])
{
- CharTitlesEntry const* titleEntry = sCharTitlesStore.LookupEntry(reward.titleId[0]);
+ CharTitlesEntry const* titleEntry = sCharTitlesStore.LookupEntry(reward.TitleId[0]);
if (!titleEntry)
{
- TC_LOG_ERROR("sql.sql", "Table `achievement_reward` (Entry: %u) contains an invalid title id (%u) in `title_A`, set to 0", entry, reward.titleId[0]);
- reward.titleId[0] = 0;
+ TC_LOG_ERROR("sql.sql", "Table `achievement_reward` (Entry: %u) contains an invalid title id (%u) in `title_A`, set to 0", entry, reward.TitleId[0]);
+ reward.TitleId[0] = 0;
}
}
- if (reward.titleId[1])
+ if (reward.TitleId[1])
{
- CharTitlesEntry const* titleEntry = sCharTitlesStore.LookupEntry(reward.titleId[1]);
+ CharTitlesEntry const* titleEntry = sCharTitlesStore.LookupEntry(reward.TitleId[1]);
if (!titleEntry)
{
- TC_LOG_ERROR("sql.sql", "Table `achievement_reward` (Entry: %u) contains an invalid title id (%u) in `title_H`, set to 0", entry, reward.titleId[1]);
- reward.titleId[1] = 0;
+ TC_LOG_ERROR("sql.sql", "Table `achievement_reward` (Entry: %u) contains an invalid title id (%u) in `title_H`, set to 0", entry, reward.TitleId[1]);
+ reward.TitleId[1] = 0;
}
}
//check mail data before item for report including wrong item case
- if (reward.sender)
+ if (reward.SenderCreatureId)
{
- if (!sObjectMgr->GetCreatureTemplate(reward.sender))
+ if (!sObjectMgr->GetCreatureTemplate(reward.SenderCreatureId))
{
- TC_LOG_ERROR("sql.sql", "Table `achievement_reward` (Entry: %u) contains an invalid creature entry %u as sender, mail reward skipped.", entry, reward.sender);
- reward.sender = 0;
+ TC_LOG_ERROR("sql.sql", "Table `achievement_reward` (Entry: %u) contains an invalid creature entry %u as sender, mail reward skipped.", entry, reward.SenderCreatureId);
+ reward.SenderCreatureId = 0;
}
}
else
{
- if (reward.itemId)
+ if (reward.ItemId)
TC_LOG_ERROR("sql.sql", "Table `achievement_reward` (Entry: %u) does not have sender data, but contains an item reward. Item will not be rewarded.", entry);
- if (!reward.subject.empty())
+ if (!reward.Subject.empty())
TC_LOG_ERROR("sql.sql", "Table `achievement_reward` (Entry: %u) does not have sender data, but contains a mail subject.", entry);
- if (!reward.text.empty())
+ if (!reward.Body.empty())
TC_LOG_ERROR("sql.sql", "Table `achievement_reward` (Entry: %u) does not have sender data, but contains mail text.", entry);
- if (reward.mailTemplate)
- TC_LOG_ERROR("sql.sql", "Table `achievement_reward` (Entry: %u) does not have sender data, but has a mailTemplate.", entry);
+ if (reward.MailTemplateId)
+ TC_LOG_ERROR("sql.sql", "Table `achievement_reward` (Entry: %u) does not have sender data, but has a MailTemplateId.", entry);
}
- if (reward.mailTemplate)
+ if (reward.MailTemplateId)
{
- if (!sMailTemplateStore.LookupEntry(reward.mailTemplate))
+ if (!sMailTemplateStore.LookupEntry(reward.MailTemplateId))
{
- TC_LOG_ERROR("sql.sql", "Table `achievement_reward` (Entry: %u) is using an invalid mailTemplate (%u).", entry, reward.mailTemplate);
- reward.mailTemplate = 0;
+ TC_LOG_ERROR("sql.sql", "Table `achievement_reward` (Entry: %u) is using an invalid MailTemplateId (%u).", entry, reward.MailTemplateId);
+ reward.MailTemplateId = 0;
}
- else if (!reward.subject.empty() || !reward.text.empty())
- TC_LOG_ERROR("sql.sql", "Table `achievement_reward` (Entry: %u) is using mailTemplate (%u) and mail subject/text.", entry, reward.mailTemplate);
+ else if (!reward.Subject.empty() || !reward.Body.empty())
+ TC_LOG_ERROR("sql.sql", "Table `achievement_reward` (Entry: %u) is using MailTemplateId (%u) and mail subject/text.", entry, reward.MailTemplateId);
}
- if (reward.itemId)
+ if (reward.ItemId)
{
- if (!sObjectMgr->GetItemTemplate(reward.itemId))
+ if (!sObjectMgr->GetItemTemplate(reward.ItemId))
{
- TC_LOG_ERROR("sql.sql", "Table `achievement_reward` (Entry: %u) contains an invalid item id %u, reward mail will not contain the rewarded item.", entry, reward.itemId);
- reward.itemId = 0;
+ TC_LOG_ERROR("sql.sql", "Table `achievement_reward` (Entry: %u) contains an invalid item id %u, reward mail will not contain the rewarded item.", entry, reward.ItemId);
+ reward.ItemId = 0;
}
}
@@ -3346,41 +1210,11 @@ void AchievementGlobalMgr::LoadRewardLocales()
for (uint8 i = OLD_TOTAL_LOCALES - 1; i > 0; --i)
{
LocaleConstant locale = (LocaleConstant) i;
- ObjectMgr::AddLocaleString(fields[1 + 2 * (i - 1)].GetString(), locale, data.subject);
- ObjectMgr::AddLocaleString(fields[1 + 2 * (i - 1) + 1].GetString(), locale, data.text);
+ ObjectMgr::AddLocaleString(fields[1 + 2 * (i - 1)].GetString(), locale, data.Subject);
+ ObjectMgr::AddLocaleString(fields[1 + 2 * (i - 1) + 1].GetString(), locale, data.Body);
}
}
while (result->NextRow());
TC_LOG_INFO("server.loading", ">> Loaded %u achievement reward locale strings in %u ms.", uint32(_achievementRewardLocales.size()), GetMSTimeDiffToNow(oldMSTime));
}
-
-AchievementEntry const* AchievementGlobalMgr::GetAchievement(uint32 achievementId) const
-{
- return sAchievementStore.LookupEntry(achievementId);
-}
-
-AchievementCriteriaTree const* AchievementGlobalMgr::GetAchievementCriteriaTree(uint32 criteriaTreeId) const
-{
- auto itr = _achievementCriteriaTrees.find(criteriaTreeId);
- if (itr == _achievementCriteriaTrees.end())
- return nullptr;
-
- return itr->second;
-}
-
-AchievementCriteria const* AchievementGlobalMgr::GetAchievementCriteria(uint32 criteriaId) const
-{
- auto itr = _achievementCriteria.find(criteriaId);
- if (itr == _achievementCriteria.end())
- return nullptr;
-
- return itr->second;
-}
-
-void AchievementGlobalMgr::OnInstanceDestroyed(uint32 instanceId)
-{
- for (auto& realmCompletion : _allCompletedAchievements)
- if (realmCompletion.second == instanceId)
- realmCompletion.second = uint32(0xFFFFFFFF);
-}
diff --git a/src/server/game/Achievements/AchievementMgr.h b/src/server/game/Achievements/AchievementMgr.h
index 16f4d20614a..f009b202af4 100644
--- a/src/server/game/Achievements/AchievementMgr.h
+++ b/src/server/game/Achievements/AchievementMgr.h
@@ -19,485 +19,158 @@
#ifndef __TRINITY_ACHIEVEMENTMGR_H
#define __TRINITY_ACHIEVEMENTMGR_H
-#include <map>
-#include <string>
+#include "CriteriaHandler.h"
-#include "Common.h"
-#include "DatabaseEnv.h"
-#include "DBCEnums.h"
-#include "DBCStores.h"
-#include "ObjectGuid.h"
-
-class Unit;
-class Player;
class Guild;
-class WorldPacket;
-struct ModifierTreeNode
+struct AchievementReward
{
- ModifierTreeEntry const* Entry;
- std::vector<ModifierTreeNode const*> Children;
+ uint32 TitleId[2];
+ uint32 ItemId;
+ uint32 SenderCreatureId;
+ std::string Subject;
+ std::string Body;
+ uint32 MailTemplateId;
};
-typedef std::unordered_map<uint32, ModifierTreeNode*> ModifierTreeMap;
-
-enum AchievementCriteriaFlagsCu
+struct AchievementRewardLocale
{
- ACHIEVEMENT_CRITERIA_FLAG_CU_PLAYER = 0x1,
- ACHIEVEMENT_CRITERIA_FLAG_CU_ACCOUNT = 0x2,
- ACHIEVEMENT_CRITERIA_FLAG_CU_GUILD = 0x4
+ std::vector<std::string> Subject;
+ std::vector<std::string> Body;
};
-struct AchievementCriteria
+struct CompletedAchievementData
{
- uint32 ID = 0;
- CriteriaEntry const* Entry = nullptr;
- ModifierTreeNode const* Modifier = nullptr;
- uint32 FlagsCu = 0;
+ std::time_t Date = std::time_t(0);
+ GuidSet CompletingPlayers;
+ bool Changed;
};
-typedef std::vector<AchievementCriteria const*> AchievementCriteriaList;
-typedef std::unordered_map<uint32, AchievementCriteria*> AchievementCriteriaMap;
-
-struct AchievementCriteriaTree
+class TC_GAME_API AchievementMgr : public CriteriaHandler
{
- uint32 ID = 0;
- CriteriaTreeEntry const* Entry = nullptr;
- AchievementEntry const* Achievement = nullptr;
- AchievementCriteria const* Criteria = nullptr;
- std::vector<AchievementCriteriaTree const*> Children;
-};
+public:
+ AchievementMgr();
+ ~AchievementMgr();
-typedef std::unordered_map<uint32, AchievementCriteriaTree*> AchievementCriteriaTreeMap;
-typedef std::vector<AchievementCriteriaTree const*> AchievementCriteriaTreeList;
-typedef std::vector<AchievementEntry const*> AchievementEntryList;
-typedef std::unordered_map<uint32, AchievementCriteriaTreeList> AchievementCriteriaTreeByCriteriaMap;
+ void CheckAllAchievementCriteria(Player* referencePlayer);
-typedef std::unordered_map<uint32, AchievementEntryList> AchievementListByReferencedId;
+ virtual void CompletedAchievement(AchievementEntry const* entry, Player* referencePlayer) = 0;
+ bool HasAchieved(uint32 achievementId) const;
+ uint32 GetAchievementPoints() const;
-struct CriteriaProgress
-{
- uint64 counter = 0;
- time_t date = time_t(0); // latest update time.
- ObjectGuid PlayerGUID; // GUID of the player that last updated the criteria
- bool changed = false;
-};
+protected:
+ bool CanUpdateCriteriaTree(Criteria const* criteria, CriteriaTree const* tree, Player* referencePlayer) const override;
+ bool CanCompleteCriteriaTree(CriteriaTree const* tree) override;
+ void CompletedCriteriaTree(CriteriaTree const* tree, Player* referencePlayer) override;
+ void AfterCriteriaTreeUpdate(CriteriaTree const* tree, Player* referencePlayer) override;
-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
-};
+ bool IsCompletedAchievement(AchievementEntry const* entry);
-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(AchievementCriteria const* criteria);
- bool Meets(uint32 criteria_id, Player const* source, Unit const* target, uint32 miscValue1 = 0) const;
-};
+ bool RequiredAchievementSatisfied(uint32 achievementId) const override;
-struct TC_GAME_API 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;
+protected:
+ std::unordered_map<uint32, CompletedAchievementData> _completedAchievements;
+ uint32 _achievementPoints;
};
-typedef std::map<uint32, AchievementCriteriaDataSet> AchievementCriteriaDataMap;
-
-struct AchievementReward
+class TC_GAME_API PlayerAchievementMgr : public AchievementMgr
{
- uint32 titleId[2];
- uint32 itemId;
- uint32 sender;
- std::string subject;
- std::string text;
- uint32 mailTemplate;
-};
+public:
+ explicit PlayerAchievementMgr(Player* owner);
-typedef std::unordered_map<uint32, AchievementReward> AchievementRewards;
+ void Reset() override;
-struct AchievementRewardLocale
-{
- std::vector<std::string> subject;
- std::vector<std::string> text;
-};
+ static void DeleteFromDB(ObjectGuid const& guid);
+ void LoadFromDB(PreparedQueryResult achievementResult, PreparedQueryResult criteriaResult);
+ void SaveToDB(SQLTransaction& trans);
-typedef std::unordered_map<uint32, AchievementRewardLocale> AchievementRewardLocales;
+ void ResetCriteria(CriteriaTypes type, uint64 miscValue1 = 0, uint64 miscValue2 = 0, bool evenIfCriteriaComplete = false);
-struct CompletedAchievementData
-{
- time_t date;
- GuidSet guids;
- bool changed;
-};
+ void SendAllData(Player const* receiver) const override;
+ void SendAchievementInfo(Player* receiver, uint32 achievementId = 0) const;
-typedef std::unordered_map<uint32, CriteriaProgress> CriteriaProgressMap;
-typedef std::unordered_map<uint32, CompletedAchievementData> CompletedAchievementMap;
+ void CompletedAchievement(AchievementEntry const* entry, Player* referencePlayer);
-enum ProgressType
-{
- PROGRESS_SET,
- PROGRESS_ACCUMULATE,
- PROGRESS_HIGHEST
-};
+protected:
+ void SendCriteriaUpdate(Criteria const* entry, CriteriaProgress const* progress, uint32 timeElapsed, bool timedCompleted) const override;
+ void SendCriteriaProgressRemoved(uint32 criteriaId) override;
-// Hackfix to solve an unresolved issue in clang that the visibility
-// flag is ignored in some explicit template specializations,
-// which prevents clang from exporting the `DeleteFromDB` symbol.
-// https://llvm.org/bugs/show_bug.cgi?id=24815
-// https://llvm.org/bugs/show_bug.cgi?id=23667
-TC_GAME_API void DeletePlayerAchievementsFromDB(ObjectGuid guid);
-TC_GAME_API void DeleteGuildAchievementsFromDB(ObjectGuid guid);
+ void SendAchievementEarned(AchievementEntry const* achievement) const;
-template<typename T>
-struct AchievementMgrDeleterBase;
+ void SendPacket(WorldPacket const* data) const;
-template<>
-struct AchievementMgrDeleterBase<Player>
-{
- static void DeleteFromDB(ObjectGuid lowguid) { DeletePlayerAchievementsFromDB(lowguid); }
-};
+ std::string GetOwnerInfo() const override;
+ CriteriaList const& GetCriteriaByType(CriteriaTypes type) const override;
-template<>
-struct AchievementMgrDeleterBase<Guild>
-{
- static void DeleteFromDB(ObjectGuid lowguid) { DeleteGuildAchievementsFromDB(lowguid); }
+private:
+ Player* _owner;
};
-template<class T>
-class TC_GAME_API AchievementMgr
- : public AchievementMgrDeleterBase<T>
+class TC_GAME_API GuildAchievementMgr : public AchievementMgr
{
- public:
- AchievementMgr(T* owner);
- ~AchievementMgr();
-
- void Reset();
-
- using AchievementMgrDeleterBase<T>::DeleteFromDB;
-
- 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(AchievementCriteria const* entry, CriteriaProgress const* progress, uint32 timeElapsed, bool timedCompleted) const;
- CriteriaProgress* GetCriteriaProgress(AchievementCriteria const* entry);
- void SetCriteriaProgress(AchievementCriteria const* entry, uint64 changeValue, Player* referencePlayer, ProgressType ptype = PROGRESS_SET);
- void RemoveCriteriaProgress(AchievementCriteria const* entry);
- void CompletedCriteriaFor(AchievementEntry const* achievement, Player* referencePlayer);
- bool IsCompletedCriteriaTree(AchievementCriteriaTree const* tree);
- bool IsCompletedCriteria(AchievementCriteria const* achievementCriteria, uint64 requiredAmount);
- bool IsCompletedAchievement(AchievementEntry const* entry);
- bool CanUpdateCriteria(AchievementCriteria const* criteria, AchievementCriteriaTreeList const* trees, uint64 miscValue1, uint64 miscValue2, uint64 miscValue3, Unit const* unit, Player* referencePlayer);
- void SendPacket(WorldPacket const* data) const;
-
- bool ConditionsSatisfied(AchievementCriteria const* criteria, Player* referencePlayer) const;
- bool RequirementsSatisfied(AchievementCriteria const* criteria, uint64 miscValue1, uint64 miscValue2, uint64 miscValue3, Unit const* unit, Player* referencePlayer) const;
- bool AdditionalRequirementsSatisfied(ModifierTreeNode const* parent, 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 tree id/time left in MS
- uint32 _achievementPoints;
+public:
+ explicit GuildAchievementMgr(Guild* owner);
+
+ void Reset() override;
+
+ static void DeleteFromDB(ObjectGuid const& guid);
+ void LoadFromDB(PreparedQueryResult achievementResult, PreparedQueryResult criteriaResult);
+ void SaveToDB(SQLTransaction& trans);
+
+ void SendAllData(Player const* receiver) const override;
+ void SendAchievementInfo(Player* receiver, uint32 achievementId = 0) const;
+ void SendAllTrackedCriterias(Player* receiver, std::set<uint32> const& trackedCriterias) const;
+
+ void CompletedAchievement(AchievementEntry const* entry, Player* referencePlayer);
+
+protected:
+ void SendCriteriaUpdate(Criteria const* entry, CriteriaProgress const* progress, uint32 timeElapsed, bool timedCompleted) const override;
+ void SendCriteriaProgressRemoved(uint32 criteriaId) override;
+
+ void SendAchievementEarned(AchievementEntry const* achievement) const;
+
+ void SendPacket(WorldPacket const* data) const;
+
+ std::string GetOwnerInfo() const override;
+ CriteriaList const& GetCriteriaByType(CriteriaTypes type) const override;
+
+private:
+ Guild* _owner;
};
class TC_GAME_API AchievementGlobalMgr
{
- AchievementGlobalMgr() { }
- ~AchievementGlobalMgr();
-
- public:
- static char const* GetCriteriaTypeString(AchievementCriteriaTypes type);
- static char const* GetCriteriaTypeString(uint32 type);
-
- static AchievementGlobalMgr* instance();
-
- AchievementCriteriaTreeList const* GetAchievementCriteriaTreesByCriteria(uint32 criteriaId) const
- {
- auto itr = _achievementCriteriaTreeByCriteria.find(criteriaId);
- return itr != _achievementCriteriaTreeByCriteria.end() ? &itr->second : nullptr;
- }
-
- AchievementCriteriaList const& GetAchievementCriteriaByType(AchievementCriteriaTypes type, bool guild = false) const
- {
- return guild ? _guildAchievementCriteriasByType[type] : _achievementCriteriasByType[type];
- }
-
- AchievementCriteriaList const& GetTimedAchievementCriteriaByType(AchievementCriteriaTimedTypes type) const
- {
- return _achievementCriteriasByTimedType[type];
- }
-
- AchievementEntryList const* GetAchievementByReferencedId(uint32 id) const
- {
- AchievementListByReferencedId::const_iterator itr = _achievementListByReferencedId.find(id);
- return itr != _achievementListByReferencedId.end() ? &itr->second : NULL;
- }
-
- AchievementReward const* GetAchievementReward(AchievementEntry const* achievement) const
- {
- AchievementRewards::const_iterator iter = _achievementRewards.find(achievement->ID);
- return iter != _achievementRewards.end() ? &iter->second : NULL;
- }
-
- AchievementRewardLocale const* GetAchievementRewardLocale(AchievementEntry const* achievement) const
- {
- AchievementRewardLocales::const_iterator iter = _achievementRewardLocales.find(achievement->ID);
- return iter != _achievementRewardLocales.end() ? &iter->second : NULL;
- }
-
- AchievementCriteriaDataSet const* GetCriteriaDataSet(AchievementCriteria const* achievementCriteria) const
- {
- AchievementCriteriaDataMap::const_iterator iter = _criteriaDataMap.find(achievementCriteria->ID);
- return iter != _criteriaDataMap.end() ? &iter->second : NULL;
- }
-
- bool IsRealmCompleted(AchievementEntry const* achievement, uint32 instanceId) const
- {
- AllCompletedAchievements::const_iterator itr = _allCompletedAchievements.find(achievement->ID);
- if (itr == _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;
-
- _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;
- }
-
- template<typename Func>
- void WalkCriteriaTree(AchievementCriteriaTree const* tree, Func const& func) const
- {
- for (AchievementCriteriaTree const* node : tree->Children)
- WalkCriteriaTree(node, func);
-
- func(tree);
- }
-
- // Removes instanceId as valid id to complete realm first kill achievements
- void OnInstanceDestroyed(uint32 instanceId);
-
- void LoadAchievementCriteriaModifiersTree();
- void LoadAchievementCriteriaList();
- void LoadAchievementCriteriaData();
- void LoadAchievementReferenceList();
- void LoadCompletedAchievements();
- void LoadRewards();
- void LoadRewardLocales();
- AchievementEntry const* GetAchievement(uint32 achievementId) const;
- AchievementCriteriaTree const* GetAchievementCriteriaTree(uint32 criteriaTreeId) const;
- AchievementCriteria const* GetAchievementCriteria(uint32 criteriaId) const;
- private:
- AchievementCriteriaDataMap _criteriaDataMap;
-
- AchievementCriteriaTreeMap _achievementCriteriaTrees;
- AchievementCriteriaMap _achievementCriteria;
- ModifierTreeMap _criteriaModifiers;
-
- AchievementCriteriaTreeByCriteriaMap _achievementCriteriaTreeByCriteria;
-
- // store achievement criterias by type to speed up lookup
- AchievementCriteriaList _achievementCriteriasByType[ACHIEVEMENT_CRITERIA_TYPE_TOTAL];
- AchievementCriteriaList _guildAchievementCriteriasByType[ACHIEVEMENT_CRITERIA_TYPE_TOTAL];
-
- AchievementCriteriaList _achievementCriteriasByTimedType[ACHIEVEMENT_TIMED_TYPE_MAX];
-
- // store achievements by referenced achievement id to speed up lookup
- AchievementListByReferencedId _achievementListByReferencedId;
-
- typedef std::map<uint32 /*achievementId*/, uint32 /*instanceId*/> AllCompletedAchievements;
- AllCompletedAchievements _allCompletedAchievements;
-
- AchievementRewards _achievementRewards;
- AchievementRewardLocales _achievementRewardLocales;
+ AchievementGlobalMgr() { }
+ ~AchievementGlobalMgr() { }
+
+public:
+ static AchievementGlobalMgr* Instance();
+
+ std::vector<AchievementEntry const*> const* GetAchievementByReferencedId(uint32 id) const;
+ AchievementReward const* GetAchievementReward(AchievementEntry const* achievement) const;
+ AchievementRewardLocale const* GetAchievementRewardLocale(AchievementEntry const* achievement) const;
+
+ bool IsRealmCompleted(AchievementEntry const* achievement) const;
+ void SetRealmCompleted(AchievementEntry const* achievement);
+
+ void LoadAchievementReferenceList();
+ void LoadCompletedAchievements();
+ void LoadRewards();
+ void LoadRewardLocales();
+
+private:
+ // store achievements by referenced achievement id to speed up lookup
+ std::unordered_map<uint32, std::vector<AchievementEntry const*>> _achievementListByReferencedId;
+
+ // store realm first achievements
+ // std::chrono::system_clock::time_point::min() is a placeholder value for realm firsts not yet completed
+ // std::chrono::system_clock::time_point::max() is a value assigned to realm firsts complete before worldserver started
+ std::unordered_map<uint32 /*achievementId*/, std::chrono::system_clock::time_point /*completionTime*/> _allCompletedAchievements;
+
+ std::unordered_map<uint32, AchievementReward> _achievementRewards;
+ std::unordered_map<uint32, AchievementRewardLocale> _achievementRewardLocales;
};
-#define sAchievementMgr AchievementGlobalMgr::instance()
+#define sAchievementMgr AchievementGlobalMgr::Instance()
#endif
diff --git a/src/server/game/Achievements/CriteriaHandler.cpp b/src/server/game/Achievements/CriteriaHandler.cpp
new file mode 100644
index 00000000000..4bd51eb6d79
--- /dev/null
+++ b/src/server/game/Achievements/CriteriaHandler.cpp
@@ -0,0 +1,2218 @@
+/*
+ * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/>
+ *
+ * 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/>.
+ */
+
+#include "CriteriaHandler.h"
+#include "ArenaTeamMgr.h"
+#include "Battleground.h"
+#include "DBCStores.h"
+#include "DB2Stores.h"
+#include "DisableMgr.h"
+#include "GameEventMgr.h"
+#include "Garrison.h"
+#include "Group.h"
+#include "InstanceScript.h"
+#include "MapManager.h"
+#include "ObjectMgr.h"
+#include "Player.h"
+#include "ReputationMgr.h"
+#include "ScriptMgr.h"
+#include "SpellInfo.h"
+#include "SpellMgr.h"
+
+bool CriteriaData::IsValid(Criteria const* criteria)
+{
+ if (DataType >= MAX_CRITERIA_DATA_TYPE)
+ {
+ TC_LOG_ERROR("sql.sql", "Table `criteria_data` for criteria (Entry: %u) contains a wrong data type (%u), ignored.", criteria->ID, DataType);
+ return false;
+ }
+
+ switch (criteria->Entry->Type)
+ {
+ case CRITERIA_TYPE_KILL_CREATURE:
+ case CRITERIA_TYPE_KILL_CREATURE_TYPE:
+ case CRITERIA_TYPE_WIN_BG:
+ case CRITERIA_TYPE_FALL_WITHOUT_DYING:
+ case CRITERIA_TYPE_COMPLETE_QUEST: // only hardcoded list
+ case CRITERIA_TYPE_CAST_SPELL:
+ case CRITERIA_TYPE_WIN_RATED_ARENA:
+ case CRITERIA_TYPE_DO_EMOTE:
+ case CRITERIA_TYPE_SPECIAL_PVP_KILL:
+ case CRITERIA_TYPE_WIN_DUEL:
+ case CRITERIA_TYPE_LOOT_TYPE:
+ case CRITERIA_TYPE_CAST_SPELL2:
+ case CRITERIA_TYPE_BE_SPELL_TARGET:
+ case CRITERIA_TYPE_BE_SPELL_TARGET2:
+ case CRITERIA_TYPE_EQUIP_EPIC_ITEM:
+ case CRITERIA_TYPE_ROLL_NEED_ON_LOOT:
+ case CRITERIA_TYPE_ROLL_GREED_ON_LOOT:
+ case CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE:
+ case CRITERIA_TYPE_HONORABLE_KILL:
+ case CRITERIA_TYPE_COMPLETE_DAILY_QUEST: // only Children's Week achievements
+ case CRITERIA_TYPE_USE_ITEM: // only Children's Week achievements
+ case CRITERIA_TYPE_GET_KILLING_BLOWS:
+ case CRITERIA_TYPE_REACH_LEVEL:
+ case CRITERIA_TYPE_ON_LOGIN:
+ break;
+ default:
+ if (DataType != CRITERIA_DATA_TYPE_SCRIPT)
+ {
+ TC_LOG_ERROR("sql.sql", "Table `criteria_data` contains data for a non-supported criteria type (Entry: %u Type: %u), ignored.", criteria->ID, criteria->Entry->Type);
+ return false;
+ }
+ break;
+ }
+
+ switch (DataType)
+ {
+ case CRITERIA_DATA_TYPE_NONE:
+ case CRITERIA_DATA_TYPE_INSTANCE_SCRIPT:
+ return true;
+ case CRITERIA_DATA_TYPE_T_CREATURE:
+ if (!Creature.Id || !sObjectMgr->GetCreatureTemplate(Creature.Id))
+ {
+ TC_LOG_ERROR("sql.sql", "Table `criteria_data` (Entry: %u Type: %u) for data type CRITERIA_DATA_TYPE_CREATURE (%u) contains a non-existing creature id in value1 (%u), ignored.",
+ criteria->ID, criteria->Entry->Type, DataType, Creature.Id);
+ return false;
+ }
+ return true;
+ case CRITERIA_DATA_TYPE_T_PLAYER_CLASS_RACE:
+ if (!ClassRace.Class && !ClassRace.Race)
+ {
+ TC_LOG_ERROR("sql.sql", "Table `criteria_data` (Entry: %u Type: %u) for data type CRITERIA_DATA_TYPE_T_PLAYER_CLASS_RACE (%u) must not have 0 in either value field, ignored.",
+ criteria->ID, criteria->Entry->Type, DataType);
+ return false;
+ }
+ if (ClassRace.Class && ((1 << (ClassRace.Class-1)) & CLASSMASK_ALL_PLAYABLE) == 0)
+ {
+ TC_LOG_ERROR("sql.sql", "Table `criteria_data` (Entry: %u Type: %u) for data type CRITERIA_DATA_TYPE_T_PLAYER_CLASS_RACE (%u) contains a non-existing class in value1 (%u), ignored.",
+ criteria->ID, criteria->Entry->Type, DataType, ClassRace.Class);
+ return false;
+ }
+ if (ClassRace.Race && ((1 << (ClassRace.Race-1)) & RACEMASK_ALL_PLAYABLE) == 0)
+ {
+ TC_LOG_ERROR("sql.sql", "Table `criteria_data` (Entry: %u Type: %u) for data type CRITERIA_DATA_TYPE_T_PLAYER_CLASS_RACE (%u) contains a non-existing race in value2 (%u), ignored.",
+ criteria->ID, criteria->Entry->Type, DataType, ClassRace.Race);
+ return false;
+ }
+ return true;
+ case CRITERIA_DATA_TYPE_T_PLAYER_LESS_HEALTH:
+ if (Health.Percent < 1 || Health.Percent > 100)
+ {
+ TC_LOG_ERROR("sql.sql", "Table `criteria_data` (Entry: %u Type: %u) for data type CRITERIA_DATA_TYPE_PLAYER_LESS_HEALTH (%u) contains a wrong percent value in value1 (%u), ignored.",
+ criteria->ID, criteria->Entry->Type, DataType, Health.Percent);
+ return false;
+ }
+ return true;
+ case CRITERIA_DATA_TYPE_S_AURA:
+ case CRITERIA_DATA_TYPE_T_AURA:
+ {
+ SpellInfo const* spellEntry = sSpellMgr->GetSpellInfo(Aura.SpellId);
+ if (!spellEntry)
+ {
+ TC_LOG_ERROR("sql.sql", "Table `criteria_data` (Entry: %u Type: %u) for data type %s (%u) contains a wrong spell id in value1 (%u), ignored.",
+ criteria->ID, criteria->Entry->Type, (DataType == CRITERIA_DATA_TYPE_S_AURA ? "CRITERIA_DATA_TYPE_S_AURA" : "CRITERIA_DATA_TYPE_T_AURA"), DataType, Aura.SpellId);
+ return false;
+ }
+ SpellEffectInfo const* effect = spellEntry->GetEffect(DIFFICULTY_NONE, Aura.EffectIndex);
+ if (!effect)
+ {
+ TC_LOG_ERROR("sql.sql", "Table `criteria_data` (Entry: %u Type: %u) for data type %s (%u) contains a wrong spell effect index in value2 (%u), ignored.",
+ criteria->ID, criteria->Entry->Type, (DataType == CRITERIA_DATA_TYPE_S_AURA ? "CRITERIA_DATA_TYPE_S_AURA" : "CRITERIA_DATA_TYPE_T_AURA"), DataType, Aura.EffectIndex);
+ return false;
+ }
+ if (!effect->ApplyAuraName)
+ {
+ TC_LOG_ERROR("sql.sql", "Table `criteria_data` (Entry: %u Type: %u) for data type %s (%u) contains a non-aura spell effect (ID: %u Effect: %u), ignored.",
+ criteria->ID, criteria->Entry->Type, (DataType == CRITERIA_DATA_TYPE_S_AURA ? "CRITERIA_DATA_TYPE_S_AURA" : "CRITERIA_DATA_TYPE_T_AURA"), DataType, Aura.SpellId, Aura.EffectIndex);
+ return false;
+ }
+ return true;
+ }
+ case CRITERIA_DATA_TYPE_VALUE:
+ if (Value.ComparisonType >= COMP_TYPE_MAX)
+ {
+ TC_LOG_ERROR("sql.sql", "Table `criteria_data` (Entry: %u Type: %u) for data type CRITERIA_DATA_TYPE_VALUE (%u) contains a wrong ComparisionType in value2 (%u), ignored.",
+ criteria->ID, criteria->Entry->Type, DataType, Value.ComparisonType);
+ return false;
+ }
+ return true;
+ case CRITERIA_DATA_TYPE_T_LEVEL:
+ if (Level.Min > STRONG_MAX_LEVEL)
+ {
+ TC_LOG_ERROR("sql.sql", "Table `CRITERIA_DATA` (Entry: %u Type: %u) for data type CRITERIA_DATA_TYPE_T_LEVEL (%u) contains a wrong minlevel in value1 (%u), ignored.",
+ criteria->ID, criteria->Entry->Type, DataType, Level.Min);
+ return false;
+ }
+ return true;
+ case CRITERIA_DATA_TYPE_T_GENDER:
+ if (Gender.Gender > GENDER_NONE)
+ {
+ TC_LOG_ERROR("sql.sql", "Table `criteria_data` (Entry: %u Type: %u) for data type CRITERIA_DATA_TYPE_T_GENDER (%u) contains a wrong gender value in value1 (%u), ignored.",
+ criteria->ID, criteria->Entry->Type, DataType, Gender.Gender);
+ return false;
+ }
+ return true;
+ case CRITERIA_DATA_TYPE_SCRIPT:
+ if (!ScriptId)
+ {
+ TC_LOG_ERROR("sql.sql", "Table `criteria_data` (Entry: %u Type: %u) for data type CRITERIA_DATA_TYPE_SCRIPT (%u) does not have a ScriptName set, ignored.",
+ criteria->ID, criteria->Entry->Type, DataType);
+ return false;
+ }
+ return true;
+ case CRITERIA_DATA_TYPE_MAP_PLAYER_COUNT:
+ if (MapPlayers.MaxCount <= 0)
+ {
+ TC_LOG_ERROR("sql.sql", "Table `criteria_data` (Entry: %u Type: %u) for data type CRITERIA_DATA_TYPE_MAP_PLAYER_COUNT (%u) contains a wrong max players count in value1 (%u), ignored.",
+ criteria->ID, criteria->Entry->Type, DataType, MapPlayers.MaxCount);
+ return false;
+ }
+ return true;
+ case CRITERIA_DATA_TYPE_T_TEAM:
+ if (Team.Team != ALLIANCE && Team.Team != HORDE)
+ {
+ TC_LOG_ERROR("sql.sql", "Table `criteria_data` (Entry: %u Type: %u) for data type CRITERIA_DATA_TYPE_T_TEAM (%u) contains an unknown team value in value1 (%u), ignored.",
+ criteria->ID, criteria->Entry->Type, DataType, Team.Team);
+ return false;
+ }
+ return true;
+ case CRITERIA_DATA_TYPE_S_DRUNK:
+ if (Drunk.State >= MAX_DRUNKEN)
+ {
+ TC_LOG_ERROR("sql.sql", "Table `criteria_data` (Entry: %u Type: %u) for data type CRITERIA_DATA_TYPE_S_DRUNK (%u) contains an unknown drunken state value in value1 (%u), ignored.",
+ criteria->ID, criteria->Entry->Type, DataType, Drunk.State);
+ return false;
+ }
+ return true;
+ case CRITERIA_DATA_TYPE_HOLIDAY:
+ if (!sHolidaysStore.LookupEntry(Holiday.Id))
+ {
+ TC_LOG_ERROR("sql.sql", "Table `criteria_data` (Entry: %u Type: %u) for data type CRITERIA_DATA_TYPE_HOLIDAY (%u) contains an unknown holiday entry in value1 (%u), ignored.",
+ criteria->ID, criteria->Entry->Type, DataType, Holiday.Id);
+ return false;
+ }
+ return true;
+ case CRITERIA_DATA_TYPE_GAME_EVENT:
+ {
+ GameEventMgr::GameEventDataMap const& events = sGameEventMgr->GetEventMap();
+ if (GameEvent.Id < 1 || GameEvent.Id >= events.size())
+ {
+ TC_LOG_ERROR("sql.sql", "Table `criteria_data` (Entry: %u Type: %u) for data type CRITERIA_DATA_TYPE_GAME_EVENT (%u) has unknown game_event in value1 (%u), ignored.",
+ criteria->ID, criteria->Entry->Type, DataType, GameEvent.Id);
+ return false;
+ }
+ return true;
+ }
+ case CRITERIA_DATA_TYPE_BG_LOSS_TEAM_SCORE:
+ return true; // not check correctness node indexes
+ case CRITERIA_DATA_TYPE_S_EQUIPED_ITEM:
+ if (EquippedItem.Quality >= MAX_ITEM_QUALITY)
+ {
+ TC_LOG_ERROR("sql.sql", "Table `criteria_data` (Entry: %u Type: %u) for data type CRITERIA_DATA_TYPE_S_EQUIPED_ITEM (%u) contains an unknown quality state value in value1 (%u), ignored.",
+ criteria->ID, criteria->Entry->Type, DataType, EquippedItem.Quality);
+ return false;
+ }
+ return true;
+ case CRITERIA_DATA_TYPE_MAP_ID:
+ if (!sMapStore.LookupEntry(Map.Id))
+ {
+ TC_LOG_ERROR("sql.sql", "Table `criteria_data` (Entry: %u Type: %u) for data type CRITERIA_DATA_TYPE_MAP_ID (%u) contains an unknown map entry in value1 (%u), ignored.",
+ criteria->ID, criteria->Entry->Type, DataType, Map.Id);
+ }
+ return true;
+ case CRITERIA_DATA_TYPE_S_PLAYER_CLASS_RACE:
+ if (!ClassRace.Class && !ClassRace.Race)
+ {
+ TC_LOG_ERROR("sql.sql", "Table `criteria_data` (Entry: %u Type: %u) for data type CRITERIA_DATA_TYPE_S_PLAYER_CLASS_RACE (%u) should not have 0 in either value field. Ignored.",
+ criteria->ID, criteria->Entry->Type, DataType);
+ return false;
+ }
+ if (ClassRace.Class && ((1 << (ClassRace.Class-1)) & CLASSMASK_ALL_PLAYABLE) == 0)
+ {
+ TC_LOG_ERROR("sql.sql", "Table `criteria_data` (Entry: %u Type: %u) for data type CRITERIA_DATA_TYPE_S_PLAYER_CLASS_RACE (%u) contains a non-existing class entry in value1 (%u), ignored.",
+ criteria->ID, criteria->Entry->Type, DataType, ClassRace.Class);
+ return false;
+ }
+ if (ClassRace.Race && ((1 << (ClassRace.Race-1)) & RACEMASK_ALL_PLAYABLE) == 0)
+ {
+ TC_LOG_ERROR("sql.sql", "Table `criteria_data` (Entry: %u Type: %u) for data type CRITERIA_DATA_TYPE_S_PLAYER_CLASS_RACE (%u) contains a non-existing race entry in value2 (%u), ignored.",
+ criteria->ID, criteria->Entry->Type, DataType, ClassRace.Race);
+ return false;
+ }
+ return true;
+ case CRITERIA_DATA_TYPE_S_KNOWN_TITLE:
+ if (!sCharTitlesStore.LookupEntry(KnownTitle.Id))
+ {
+ TC_LOG_ERROR("sql.sql", "Table `criteria_data` (Entry: %u Type: %u) for data type CRITERIA_DATA_TYPE_S_KNOWN_TITLE (%u) contains an unknown title_id in value1 (%u), ignore.",
+ criteria->ID, criteria->Entry->Type, DataType, KnownTitle.Id);
+ return false;
+ }
+ return true;
+ default:
+ TC_LOG_ERROR("sql.sql", "Table `criteria_data` (Entry: %u Type: %u) contains data of a non-supported data type (%u), ignored.", criteria->ID, criteria->Entry->Type, DataType);
+ return false;
+ }
+}
+
+bool CriteriaData::Meets(uint32 criteriaId, Player const* source, Unit const* target, uint32 miscValue1 /*= 0*/) const
+{
+ switch (DataType)
+ {
+ case CRITERIA_DATA_TYPE_NONE:
+ return true;
+ case CRITERIA_DATA_TYPE_T_CREATURE:
+ if (!target || target->GetTypeId() != TYPEID_UNIT)
+ return false;
+ return target->GetEntry() == Creature.Id;
+ case CRITERIA_DATA_TYPE_T_PLAYER_CLASS_RACE:
+ if (!target || target->GetTypeId() != TYPEID_PLAYER)
+ return false;
+ if (ClassRace.Class && ClassRace.Class != target->ToPlayer()->getClass())
+ return false;
+ if (ClassRace.Race && ClassRace.Race != target->ToPlayer()->getRace())
+ return false;
+ return true;
+ case CRITERIA_DATA_TYPE_S_PLAYER_CLASS_RACE:
+ if (source->GetTypeId() != TYPEID_PLAYER)
+ return false;
+ if (ClassRace.Class && ClassRace.Class != source->ToPlayer()->getClass())
+ return false;
+ if (ClassRace.Race && ClassRace.Race != source->ToPlayer()->getRace())
+ return false;
+ return true;
+ case CRITERIA_DATA_TYPE_T_PLAYER_LESS_HEALTH:
+ if (!target || target->GetTypeId() != TYPEID_PLAYER)
+ return false;
+ return !target->HealthAbovePct(Health.Percent);
+ case CRITERIA_DATA_TYPE_S_AURA:
+ return source->HasAuraEffect(Aura.SpellId, uint8(Aura.EffectIndex));
+ case CRITERIA_DATA_TYPE_T_AURA:
+ return target && target->HasAuraEffect(Aura.SpellId, uint8(Aura.EffectIndex));
+ case CRITERIA_DATA_TYPE_VALUE:
+ return CompareValues(ComparisionType(Value.ComparisonType), miscValue1, Value.Value);
+ case CRITERIA_DATA_TYPE_T_LEVEL:
+ if (!target)
+ return false;
+ return target->getLevel() >= Level.Min;
+ case CRITERIA_DATA_TYPE_T_GENDER:
+ if (!target)
+ return false;
+ return target->getGender() == Gender.Gender;
+ case CRITERIA_DATA_TYPE_SCRIPT:
+ return sScriptMgr->OnCriteriaCheck(ScriptId, const_cast<Player*>(source), const_cast<Unit*>(target));
+ case CRITERIA_DATA_TYPE_MAP_PLAYER_COUNT:
+ return source->GetMap()->GetPlayersCountExceptGMs() <= MapPlayers.MaxCount;
+ case CRITERIA_DATA_TYPE_T_TEAM:
+ if (!target || target->GetTypeId() != TYPEID_PLAYER)
+ return false;
+ return target->ToPlayer()->GetTeam() == Team.Team;
+ case CRITERIA_DATA_TYPE_S_DRUNK:
+ return Player::GetDrunkenstateByValue(source->GetDrunkValue()) >= DrunkenState(Drunk.State);
+ case CRITERIA_DATA_TYPE_HOLIDAY:
+ return IsHolidayActive(HolidayIds(Holiday.Id));
+ case CRITERIA_DATA_TYPE_GAME_EVENT:
+ return IsEventActive(uint16(GameEvent.Id));
+ case CRITERIA_DATA_TYPE_BG_LOSS_TEAM_SCORE:
+ {
+ Battleground* bg = source->GetBattleground();
+ if (!bg)
+ return false;
+
+ uint32 score = bg->GetTeamScore(source->GetTeamId() == TEAM_ALLIANCE ? TEAM_HORDE : TEAM_ALLIANCE);
+ return score >= BattlegroundScore.Min && score <= BattlegroundScore.Max;
+ }
+ case CRITERIA_DATA_TYPE_INSTANCE_SCRIPT:
+ {
+ if (!source->IsInWorld())
+ return false;
+ class Map* map = source->GetMap();
+ if (!map->IsDungeon())
+ {
+ TC_LOG_ERROR("criteria", "Criteria system call CRITERIA_DATA_TYPE_INSTANCE_SCRIPT (%u) for criteria %u in a non-dungeon/non-raid map %u",
+ DataType, criteriaId, map->GetId());
+ return false;
+ }
+ InstanceScript* instance = map->ToInstanceMap()->GetInstanceScript();
+ if (!instance)
+ {
+ TC_LOG_ERROR("criteria", "Criteria system call CRITERIA_DATA_TYPE_INSTANCE_SCRIPT (%u) for criteria %u in map %u, but the map does not have an instance script.",
+ DataType, criteriaId, map->GetId());
+ return false;
+ }
+ return instance->CheckAchievementCriteriaMeet(criteriaId, source, target, miscValue1);
+ }
+ case CRITERIA_DATA_TYPE_S_EQUIPED_ITEM:
+ {
+ ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(miscValue1);
+ if (!pProto)
+ return false;
+ return pProto->GetBaseItemLevel() >= EquippedItem.ItemLevel && pProto->GetQuality() >= EquippedItem.Quality;
+ }
+ case CRITERIA_DATA_TYPE_MAP_ID:
+ return source->GetMapId() == Map.Id;
+ case CRITERIA_DATA_TYPE_S_KNOWN_TITLE:
+ {
+ if (CharTitlesEntry const* titleInfo = sCharTitlesStore.LookupEntry(KnownTitle.Id))
+ return source && source->HasTitle(titleInfo->MaskID);
+
+ return false;
+ }
+ default:
+ break;
+ }
+ return false;
+}
+
+bool CriteriaDataSet::Meets(Player const* source, Unit const* target, uint32 miscValue /*= 0*/) const
+{
+ for (CriteriaData const& data : _storage)
+ if (!data.Meets(_criteriaId, source, target, miscValue))
+ return false;
+
+ return true;
+}
+
+CriteriaHandler::CriteriaHandler() { }
+
+CriteriaHandler::~CriteriaHandler() { }
+
+void CriteriaHandler::Reset()
+{
+ for (auto iter = _criteriaProgress.begin(); iter != _criteriaProgress.end(); ++iter)
+ SendCriteriaProgressRemoved(iter->first);
+
+ _criteriaProgress.clear();
+}
+
+/**
+ * this function will be called whenever the user might have done a criteria relevant action
+ */
+void CriteriaHandler::UpdateCriteria(CriteriaTypes type, uint64 miscValue1 /*= 0*/, uint64 miscValue2 /*= 0*/, uint64 miscValue3 /*= 0*/, Unit const* unit /*= nullptr*/, Player* referencePlayer /*= nullptr*/)
+{
+ if (type >= CRITERIA_TYPE_TOTAL)
+ {
+ TC_LOG_DEBUG("criteria", "CriteriaHandler::UpdateCriteria: Wrong criteria type %u", type);
+ return;
+ }
+
+ if (!referencePlayer)
+ {
+ TC_LOG_DEBUG("criteria", "CriteriaHandler::UpdateCriteria: Player is NULL! Cant update criteria");
+ return;
+ }
+
+ // disable for gamemasters with GM-mode enabled
+ if (referencePlayer->IsGameMaster())
+ {
+ TC_LOG_DEBUG("criteria", "CriteriaHandler::UpdateCriteria: [Player %s GM mode on] %s, %s (%u), " UI64FMTD ", " UI64FMTD ", " UI64FMTD,
+ referencePlayer->GetName().c_str(), GetOwnerInfo().c_str(), CriteriaMgr::GetCriteriaTypeString(type), type, miscValue1, miscValue2, miscValue3);
+ return;
+ }
+
+ TC_LOG_DEBUG("criteria", "CriteriaHandler::UpdateCriteria(%s, " UI64FMTD ", " UI64FMTD ", " UI64FMTD ") %s",
+ CriteriaMgr::GetCriteriaTypeString(type), type, miscValue1, miscValue2, miscValue3, GetOwnerInfo().c_str());
+
+ CriteriaList const& criteriaList = GetCriteriaByType(type);
+ for (Criteria const* criteria : criteriaList)
+ {
+ CriteriaTreeList const* trees = sCriteriaMgr->GetCriteriaTreesByCriteria(criteria->ID);
+ if (!CanUpdateCriteria(criteria, trees, miscValue1, miscValue2, miscValue3, unit, referencePlayer))
+ continue;
+
+ // requirements not found in the dbc
+ if (CriteriaDataSet const* data = sCriteriaMgr->GetCriteriaDataSet(criteria))
+ if (!data->Meets(referencePlayer, unit, uint32(miscValue1)))
+ continue;
+
+ switch (type)
+ {
+ // std. case: increment at 1
+ case CRITERIA_TYPE_NUMBER_OF_TALENT_RESETS:
+ case CRITERIA_TYPE_LOSE_DUEL:
+ case CRITERIA_TYPE_CREATE_AUCTION:
+ case CRITERIA_TYPE_WON_AUCTIONS: /* FIXME: for online player only currently */
+ case CRITERIA_TYPE_ROLL_NEED:
+ case CRITERIA_TYPE_ROLL_GREED:
+ case CRITERIA_TYPE_QUEST_ABANDONED:
+ case CRITERIA_TYPE_FLIGHT_PATHS_TAKEN:
+ case CRITERIA_TYPE_ACCEPTED_SUMMONINGS:
+ case CRITERIA_TYPE_LOOT_EPIC_ITEM:
+ case CRITERIA_TYPE_RECEIVE_EPIC_ITEM:
+ case CRITERIA_TYPE_DEATH:
+ case CRITERIA_TYPE_COMPLETE_DAILY_QUEST:
+ case CRITERIA_TYPE_DEATH_AT_MAP:
+ case CRITERIA_TYPE_DEATH_IN_DUNGEON:
+ case CRITERIA_TYPE_KILLED_BY_CREATURE:
+ case CRITERIA_TYPE_KILLED_BY_PLAYER:
+ case CRITERIA_TYPE_DEATHS_FROM:
+ case CRITERIA_TYPE_BE_SPELL_TARGET:
+ case CRITERIA_TYPE_BE_SPELL_TARGET2:
+ case CRITERIA_TYPE_CAST_SPELL:
+ case CRITERIA_TYPE_CAST_SPELL2:
+ case CRITERIA_TYPE_WIN_RATED_ARENA:
+ case CRITERIA_TYPE_USE_ITEM:
+ case CRITERIA_TYPE_ROLL_NEED_ON_LOOT:
+ case CRITERIA_TYPE_ROLL_GREED_ON_LOOT:
+ case CRITERIA_TYPE_DO_EMOTE:
+ case CRITERIA_TYPE_USE_GAMEOBJECT:
+ case CRITERIA_TYPE_FISH_IN_GAMEOBJECT:
+ case CRITERIA_TYPE_WIN_DUEL:
+ case CRITERIA_TYPE_HK_CLASS:
+ case CRITERIA_TYPE_HK_RACE:
+ case CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE:
+ case CRITERIA_TYPE_HONORABLE_KILL:
+ case CRITERIA_TYPE_SPECIAL_PVP_KILL:
+ case CRITERIA_TYPE_GET_KILLING_BLOWS:
+ case CRITERIA_TYPE_HONORABLE_KILL_AT_AREA:
+ case CRITERIA_TYPE_WIN_ARENA: // This also behaves like CRITERIA_TYPE_WIN_RATED_ARENA
+ case CRITERIA_TYPE_ON_LOGIN:
+ case CRITERIA_TYPE_PLACE_GARRISON_BUILDING:
+ case CRITERIA_TYPE_OWN_BATTLE_PET_COUNT:
+ SetCriteriaProgress(criteria, 1, referencePlayer, PROGRESS_ACCUMULATE);
+ break;
+ // std case: increment at miscValue1
+ case CRITERIA_TYPE_MONEY_FROM_VENDORS:
+ case CRITERIA_TYPE_GOLD_SPENT_FOR_TALENTS:
+ case CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD:
+ case CRITERIA_TYPE_GOLD_SPENT_FOR_TRAVELLING:
+ case CRITERIA_TYPE_GOLD_SPENT_AT_BARBER:
+ case CRITERIA_TYPE_GOLD_SPENT_FOR_MAIL:
+ case CRITERIA_TYPE_LOOT_MONEY:
+ case CRITERIA_TYPE_GOLD_EARNED_BY_AUCTIONS:/* FIXME: for online player only currently */
+ case CRITERIA_TYPE_TOTAL_DAMAGE_RECEIVED:
+ case CRITERIA_TYPE_TOTAL_HEALING_RECEIVED:
+ case CRITERIA_TYPE_USE_LFD_TO_GROUP_WITH_PLAYERS:
+ case CRITERIA_TYPE_WIN_BG:
+ case CRITERIA_TYPE_COMPLETE_BATTLEGROUND:
+ case CRITERIA_TYPE_DAMAGE_DONE:
+ case CRITERIA_TYPE_HEALING_DONE:
+ SetCriteriaProgress(criteria, miscValue1, referencePlayer, PROGRESS_ACCUMULATE);
+ break;
+ case CRITERIA_TYPE_KILL_CREATURE:
+ case CRITERIA_TYPE_KILL_CREATURE_TYPE:
+ case CRITERIA_TYPE_LOOT_TYPE:
+ case CRITERIA_TYPE_OWN_ITEM:
+ case CRITERIA_TYPE_LOOT_ITEM:
+ case CRITERIA_TYPE_CURRENCY:
+ SetCriteriaProgress(criteria, miscValue2, referencePlayer, PROGRESS_ACCUMULATE);
+ break;
+ // std case: high value at miscValue1
+ case CRITERIA_TYPE_HIGHEST_AUCTION_BID:
+ case CRITERIA_TYPE_HIGHEST_AUCTION_SOLD: /* FIXME: for online player only currently */
+ case CRITERIA_TYPE_HIGHEST_HIT_DEALT:
+ case CRITERIA_TYPE_HIGHEST_HIT_RECEIVED:
+ case CRITERIA_TYPE_HIGHEST_HEAL_CAST:
+ case CRITERIA_TYPE_HIGHEST_HEALING_RECEIVED:
+ SetCriteriaProgress(criteria, miscValue1, referencePlayer, PROGRESS_HIGHEST);
+ break;
+ case CRITERIA_TYPE_REACH_LEVEL:
+ SetCriteriaProgress(criteria, referencePlayer->getLevel(), referencePlayer);
+ break;
+ case CRITERIA_TYPE_REACH_SKILL_LEVEL:
+ if (uint32 skillvalue = referencePlayer->GetBaseSkillValue(criteria->Entry->Asset.SkillID))
+ SetCriteriaProgress(criteria, skillvalue, referencePlayer);
+ break;
+ case CRITERIA_TYPE_LEARN_SKILL_LEVEL:
+ if (uint32 maxSkillvalue = referencePlayer->GetPureMaxSkillValue(criteria->Entry->Asset.SkillID))
+ SetCriteriaProgress(criteria, maxSkillvalue, referencePlayer);
+ break;
+ case CRITERIA_TYPE_COMPLETE_QUEST_COUNT:
+ SetCriteriaProgress(criteria, referencePlayer->GetRewardedQuestCount(), referencePlayer);
+ break;
+ case CRITERIA_TYPE_COMPLETE_DAILY_QUEST_DAILY:
+ {
+ time_t nextDailyResetTime = sWorld->GetNextDailyQuestsResetTime();
+ CriteriaProgress *progress = GetCriteriaProgress(criteria);
+
+ if (!miscValue1) // Login case.
+ {
+ // reset if player missed one day.
+ if (progress && progress->Date < (nextDailyResetTime - 2 * DAY))
+ SetCriteriaProgress(criteria, 0, referencePlayer, PROGRESS_SET);
+ continue;
+ }
+
+ ProgressType progressType;
+ if (!progress)
+ // 1st time. Start count.
+ progressType = PROGRESS_SET;
+ else if (progress->Date < (nextDailyResetTime - 2 * DAY))
+ // last progress is older than 2 days. Player missed 1 day => Restart count.
+ progressType = PROGRESS_SET;
+ else if (progress->Date < (nextDailyResetTime - DAY))
+ // last progress is between 1 and 2 days. => 1st time of the day.
+ progressType = PROGRESS_ACCUMULATE;
+ else
+ // last progress is within the day before the reset => Already counted today.
+ continue;
+
+ SetCriteriaProgress(criteria, 1, referencePlayer, progressType);
+ break;
+ }
+ case CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE:
+ {
+ uint32 counter = 0;
+
+ const RewardedQuestSet &rewQuests = referencePlayer->getRewardedQuests();
+ for (RewardedQuestSet::const_iterator itr = rewQuests.begin(); itr != rewQuests.end(); ++itr)
+ {
+ Quest const* quest = sObjectMgr->GetQuestTemplate(*itr);
+ if (quest && quest->GetZoneOrSort() >= 0 && uint32(quest->GetZoneOrSort()) == criteria->Entry->Asset.ZoneID)
+ ++counter;
+ }
+ SetCriteriaProgress(criteria, counter, referencePlayer);
+ break;
+ }
+ case CRITERIA_TYPE_FALL_WITHOUT_DYING:
+ // miscValue1 is the ingame fallheight*100 as stored in dbc
+ SetCriteriaProgress(criteria, miscValue1, referencePlayer);
+ break;
+ case CRITERIA_TYPE_COMPLETE_QUEST:
+ case CRITERIA_TYPE_LEARN_SPELL:
+ case CRITERIA_TYPE_EXPLORE_AREA:
+ case CRITERIA_TYPE_VISIT_BARBER_SHOP:
+ case CRITERIA_TYPE_EQUIP_EPIC_ITEM:
+ case CRITERIA_TYPE_EQUIP_ITEM:
+ case CRITERIA_TYPE_COMPLETE_ACHIEVEMENT:
+ case CRITERIA_TYPE_RECRUIT_GARRISON_FOLLOWER:
+ case CRITERIA_TYPE_OWN_BATTLE_PET:
+ SetCriteriaProgress(criteria, 1, referencePlayer);
+ break;
+ case CRITERIA_TYPE_BUY_BANK_SLOT:
+ SetCriteriaProgress(criteria, referencePlayer->GetBankBagSlotCount(), referencePlayer);
+ break;
+ case CRITERIA_TYPE_GAIN_REPUTATION:
+ {
+ int32 reputation = referencePlayer->GetReputationMgr().GetReputation(criteria->Entry->Asset.FactionID);
+ if (reputation > 0)
+ SetCriteriaProgress(criteria, reputation, referencePlayer);
+ break;
+ }
+ case CRITERIA_TYPE_GAIN_EXALTED_REPUTATION:
+ SetCriteriaProgress(criteria, referencePlayer->GetReputationMgr().GetExaltedFactionCount(), referencePlayer);
+ break;
+ case CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS:
+ case CRITERIA_TYPE_LEARN_SKILL_LINE:
+ {
+ uint32 spellCount = 0;
+ for (PlayerSpellMap::const_iterator spellIter = referencePlayer->GetSpellMap().begin();
+ spellIter != referencePlayer->GetSpellMap().end();
+ ++spellIter)
+ {
+ SkillLineAbilityMapBounds bounds = sSpellMgr->GetSkillLineAbilityMapBounds(spellIter->first);
+ for (SkillLineAbilityMap::const_iterator skillIter = bounds.first; skillIter != bounds.second; ++skillIter)
+ {
+ if (skillIter->second->SkillLine == criteria->Entry->Asset.SkillID)
+ spellCount++;
+ }
+ }
+ SetCriteriaProgress(criteria, spellCount, referencePlayer);
+ break;
+ }
+ case CRITERIA_TYPE_GAIN_REVERED_REPUTATION:
+ SetCriteriaProgress(criteria, referencePlayer->GetReputationMgr().GetReveredFactionCount(), referencePlayer);
+ break;
+ case CRITERIA_TYPE_GAIN_HONORED_REPUTATION:
+ SetCriteriaProgress(criteria, referencePlayer->GetReputationMgr().GetHonoredFactionCount(), referencePlayer);
+ break;
+ case CRITERIA_TYPE_KNOWN_FACTIONS:
+ SetCriteriaProgress(criteria, referencePlayer->GetReputationMgr().GetVisibleFactionCount(), referencePlayer);
+ break;
+ case CRITERIA_TYPE_EARN_HONORABLE_KILL:
+ SetCriteriaProgress(criteria, referencePlayer->GetUInt32Value(PLAYER_FIELD_LIFETIME_HONORABLE_KILLS), referencePlayer);
+ break;
+ case CRITERIA_TYPE_HIGHEST_GOLD_VALUE_OWNED:
+ SetCriteriaProgress(criteria, referencePlayer->GetMoney(), referencePlayer, PROGRESS_HIGHEST);
+ break;
+ case CRITERIA_TYPE_EARN_ACHIEVEMENT_POINTS:
+ if (!miscValue1)
+ continue;
+ SetCriteriaProgress(criteria, miscValue1, referencePlayer, PROGRESS_ACCUMULATE);
+ break;
+ case CRITERIA_TYPE_HIGHEST_PERSONAL_RATING:
+ {
+ uint32 reqTeamType = criteria->Entry->Asset.TeamType;
+
+ if (miscValue1)
+ {
+ if (miscValue2 != reqTeamType)
+ continue;
+
+ SetCriteriaProgress(criteria, miscValue1, referencePlayer, PROGRESS_HIGHEST);
+ }
+ else // login case
+ {
+ for (uint8 arena_slot = 0; arena_slot < MAX_ARENA_SLOT; ++arena_slot)
+ {
+ uint32 teamId = referencePlayer->GetArenaTeamId(arena_slot);
+ if (!teamId)
+ continue;
+
+ ArenaTeam* team = sArenaTeamMgr->GetArenaTeamById(teamId);
+ if (!team || team->GetType() != reqTeamType)
+ continue;
+
+ if (ArenaTeamMember const* member = team->GetMember(referencePlayer->GetGUID()))
+ {
+ SetCriteriaProgress(criteria, member->PersonalRating, referencePlayer, PROGRESS_HIGHEST);
+ break;
+ }
+ }
+ }
+ break;
+ }
+ case CRITERIA_TYPE_REACH_GUILD_LEVEL:
+ SetCriteriaProgress(criteria, miscValue1, referencePlayer);
+ break;
+ // FIXME: not triggered in code as result, need to implement
+ case CRITERIA_TYPE_COMPLETE_RAID:
+ case CRITERIA_TYPE_PLAY_ARENA:
+ case CRITERIA_TYPE_HIGHEST_TEAM_RATING:
+ case CRITERIA_TYPE_OWN_RANK:
+ case CRITERIA_TYPE_SPENT_GOLD_GUILD_REPAIRS:
+ case CRITERIA_TYPE_CRAFT_ITEMS_GUILD:
+ case CRITERIA_TYPE_CATCH_FROM_POOL:
+ case CRITERIA_TYPE_BUY_GUILD_BANK_SLOTS:
+ case CRITERIA_TYPE_EARN_GUILD_ACHIEVEMENT_POINTS:
+ case CRITERIA_TYPE_WIN_RATED_BATTLEGROUND:
+ case CRITERIA_TYPE_REACH_BG_RATING:
+ case CRITERIA_TYPE_BUY_GUILD_TABARD:
+ case CRITERIA_TYPE_COMPLETE_QUESTS_GUILD:
+ case CRITERIA_TYPE_HONORABLE_KILLS_GUILD:
+ case CRITERIA_TYPE_KILL_CREATURE_TYPE_GUILD:
+ case CRITERIA_TYPE_COMPLETE_ARCHAEOLOGY_PROJECTS:
+ case CRITERIA_TYPE_COMPLETE_GUILD_CHALLENGE_TYPE:
+ case CRITERIA_TYPE_COMPLETE_GUILD_CHALLENGE:
+ case CRITERIA_TYPE_LFR_DUNGEONS_COMPLETED:
+ case CRITERIA_TYPE_LFR_LEAVES:
+ case CRITERIA_TYPE_LFR_VOTE_KICKS_INITIATED_BY_PLAYER:
+ case CRITERIA_TYPE_LFR_VOTE_KICKS_NOT_INIT_BY_PLAYER:
+ case CRITERIA_TYPE_BE_KICKED_FROM_LFR:
+ case CRITERIA_TYPE_COUNT_OF_LFR_QUEUE_BOOSTS_BY_TANK:
+ case CRITERIA_TYPE_COMPLETE_SCENARIO_COUNT:
+ case CRITERIA_TYPE_COMPLETE_SCENARIO:
+ case CRITERIA_TYPE_CAPTURE_BATTLE_PET:
+ case CRITERIA_TYPE_WIN_PET_BATTLE:
+ case CRITERIA_TYPE_LEVEL_BATTLE_PET:
+ case CRITERIA_TYPE_CAPTURE_BATTLE_PET_CREDIT:
+ case CRITERIA_TYPE_LEVEL_BATTLE_PET_CREDIT:
+ case CRITERIA_TYPE_ENTER_AREA:
+ case CRITERIA_TYPE_LEAVE_AREA:
+ case CRITERIA_TYPE_COMPLETE_DUNGEON_ENCOUNTER:
+ case CRITERIA_TYPE_UPGRADE_GARRISON_BUILDING:
+ case CRITERIA_TYPE_CONSTRUCT_GARRISON_BUILDING:
+ case CRITERIA_TYPE_UPGRADE_GARRISON:
+ case CRITERIA_TYPE_START_GARRISON_MISSION:
+ case CRITERIA_TYPE_COMPLETE_GARRISON_MISSION_COUNT:
+ case CRITERIA_TYPE_COMPLETE_GARRISON_MISSION:
+ case CRITERIA_TYPE_RECRUIT_GARRISON_FOLLOWER_COUNT:
+ case CRITERIA_TYPE_LEARN_GARRISON_BLUEPRINT_COUNT:
+ case CRITERIA_TYPE_COMPLETE_GARRISON_SHIPMENT:
+ case CRITERIA_TYPE_RAISE_GARRISON_FOLLOWER_ITEM_LEVEL:
+ case CRITERIA_TYPE_RAISE_GARRISON_FOLLOWER_LEVEL:
+ case CRITERIA_TYPE_OWN_TOY:
+ case CRITERIA_TYPE_OWN_TOY_COUNT:
+ case CRITERIA_TYPE_OWN_HEIRLOOMS:
+ break; // Not implemented yet :(
+ }
+
+ for (CriteriaTree const* tree : *trees)
+ {
+ if (IsCompletedCriteriaTree(tree))
+ CompletedCriteriaTree(tree, referencePlayer);
+
+ AfterCriteriaTreeUpdate(tree, referencePlayer);
+ }
+ }
+}
+
+void CriteriaHandler::UpdateTimedCriteria(uint32 timeDiff)
+{
+ if (!_timeCriteriaTrees.empty())
+ {
+ for (auto itr = _timeCriteriaTrees.begin(); itr != _timeCriteriaTrees.end();)
+ {
+ // Time is up, remove timer and reset progress
+ if (itr->second <= timeDiff)
+ {
+ CriteriaTree const* criteriaTree = sCriteriaMgr->GetCriteriaTree(itr->first);
+ if (criteriaTree->Criteria)
+ RemoveCriteriaProgress(criteriaTree->Criteria);
+
+ itr = _timeCriteriaTrees.erase(itr);
+ }
+ else
+ {
+ itr->second -= timeDiff;
+ ++itr;
+ }
+ }
+ }
+}
+
+void CriteriaHandler::StartCriteriaTimer(CriteriaTimedTypes type, uint32 entry, uint32 timeLost /* = 0 */)
+{
+ CriteriaList const& criteriaList = sCriteriaMgr->GetTimedCriteriaByType(type);
+ for (Criteria const* criteria : criteriaList)
+ {
+ if (criteria->Entry->StartAsset != entry)
+ continue;
+
+ CriteriaTreeList const* trees = sCriteriaMgr->GetCriteriaTreesByCriteria(criteria->ID);
+ bool canStart = false;
+ for (CriteriaTree const* tree : *trees)
+ {
+ if (_timeCriteriaTrees.find(tree->ID) == _timeCriteriaTrees.end() && !IsCompletedCriteriaTree(tree))
+ {
+ // Start the timer
+ if (criteria->Entry->StartTimer * IN_MILLISECONDS > timeLost)
+ {
+ _timeCriteriaTrees[tree->ID] = criteria->Entry->StartTimer * IN_MILLISECONDS - timeLost;
+ canStart = true;
+ }
+ }
+ }
+
+ if (!canStart)
+ continue;
+
+ // and at client too
+ SetCriteriaProgress(criteria, 0, nullptr, PROGRESS_SET);
+ }
+}
+
+void CriteriaHandler::RemoveCriteriaTimer(CriteriaTimedTypes type, uint32 entry)
+{
+ CriteriaList const& criteriaList = sCriteriaMgr->GetTimedCriteriaByType(type);
+ for (Criteria const* criteria : criteriaList)
+ {
+ if (criteria->Entry->StartAsset != entry)
+ continue;
+
+ CriteriaTreeList const* trees = sCriteriaMgr->GetCriteriaTreesByCriteria(criteria->ID);
+ // Remove the timer from all trees
+ for (CriteriaTree const* tree : *trees)
+ _timeCriteriaTrees.erase(tree->ID);
+
+ // remove progress
+ RemoveCriteriaProgress(criteria);
+ }
+}
+
+CriteriaProgress* CriteriaHandler::GetCriteriaProgress(Criteria const* entry)
+{
+ auto iter = _criteriaProgress.find(entry->ID);
+ if (iter == _criteriaProgress.end())
+ return nullptr;
+
+ return &iter->second;
+}
+
+void CriteriaHandler::SetCriteriaProgress(Criteria const* criteria, uint64 changeValue, Player* referencePlayer, ProgressType progressType)
+{
+ // Don't allow to cheat - doing timed criteria without timer active
+ CriteriaTreeList const* trees = nullptr;
+ if (criteria->Entry->StartTimer)
+ {
+ trees = sCriteriaMgr->GetCriteriaTreesByCriteria(criteria->ID);
+ if (!trees)
+ return;
+
+ bool hasTreeForTimed = false;
+ for (CriteriaTree const* tree : *trees)
+ {
+ auto timedIter = _timeCriteriaTrees.find(tree->ID);
+ if (timedIter != _timeCriteriaTrees.end())
+ {
+ hasTreeForTimed = true;
+ break;
+ }
+ }
+
+ if (!hasTreeForTimed)
+ return;
+ }
+
+ TC_LOG_DEBUG("criteria", "CriteriaHandler::SetCriteriaProgress(%u, " UI64FMTD ") for %s", criteria->ID, changeValue, GetOwnerInfo().c_str());
+
+ CriteriaProgress* progress = GetCriteriaProgress(criteria);
+ if (!progress)
+ {
+ // not create record for 0 counter but allow it for timed criteria
+ // we will need to send 0 progress to client to start the timer
+ if (changeValue == 0 && !criteria->Entry->StartTimer)
+ return;
+
+ progress = &_criteriaProgress[criteria->ID];
+ progress->Counter = changeValue;
+ }
+ else
+ {
+ uint64 newValue = 0;
+ switch (progressType)
+ {
+ case PROGRESS_SET:
+ newValue = changeValue;
+ break;
+ case PROGRESS_ACCUMULATE:
+ {
+ // avoid overflow
+ uint64 max_value = std::numeric_limits<uint64>::max();
+ newValue = max_value - progress->Counter > changeValue ? progress->Counter + changeValue : max_value;
+ break;
+ }
+ case PROGRESS_HIGHEST:
+ newValue = progress->Counter < changeValue ? changeValue : progress->Counter;
+ break;
+ }
+
+ // not update (not mark as changed) if counter will have same value
+ if (progress->Counter == newValue && !criteria->Entry->StartTimer)
+ return;
+
+ progress->Counter = newValue;
+ }
+
+ progress->Changed = true;
+ progress->Date = time(NULL); // set the date to the latest update.
+ progress->PlayerGUID = referencePlayer ? referencePlayer->GetGUID() : ObjectGuid::Empty;
+
+ uint32 timeElapsed = 0;
+
+ if (criteria->Entry->StartTimer)
+ {
+ ASSERT(trees);
+
+ for (CriteriaTree const* tree : *trees)
+ {
+ auto timedIter = _timeCriteriaTrees.find(tree->ID);
+ if (timedIter != _timeCriteriaTrees.end())
+ {
+ // Client expects this in packet
+ timeElapsed = criteria->Entry->StartTimer - (timedIter->second / IN_MILLISECONDS);
+
+ // Remove the timer, we wont need it anymore
+ if (IsCompletedCriteriaTree(tree))
+ _timeCriteriaTrees.erase(timedIter);
+ }
+ }
+ }
+
+ SendCriteriaUpdate(criteria, progress, timeElapsed, true);
+}
+
+void CriteriaHandler::RemoveCriteriaProgress(Criteria const* criteria)
+{
+ if (!criteria)
+ return;
+
+ auto criteriaProgress = _criteriaProgress.find(criteria->ID);
+ if (criteriaProgress == _criteriaProgress.end())
+ return;
+
+ SendCriteriaProgressRemoved(criteria->ID);
+
+ _criteriaProgress.erase(criteriaProgress);
+}
+
+bool CriteriaHandler::IsCompletedCriteriaTree(CriteriaTree const* tree)
+{
+ if (!CanCompleteCriteriaTree(tree))
+ return false;
+
+ uint64 requiredCount = tree->Entry->Amount;
+ uint64 completedCount = 0;
+ uint32 op = tree->Entry->Operator;
+ bool hasAll = true;
+
+ // Check criteria we depend on first
+ for (CriteriaTree const* node : tree->Children)
+ {
+ if (IsCompletedCriteriaTree(node))
+ ++completedCount;
+ else
+ hasAll = false;
+
+ if (op & CRITERIA_TREE_OPERATOR_ANY && completedCount >= requiredCount)
+ {
+ if (!tree->Criteria)
+ return true;
+
+ break;
+ }
+ }
+
+ if (op & CRITERIA_TREE_OPERATOR_ANY && completedCount < requiredCount)
+ return false;
+
+ if (op & CRITERIA_TREE_OPERATOR_ALL && !hasAll)
+ return false;
+
+ if (!tree->Criteria)
+ return true;
+
+ return IsCompletedCriteria(tree->Criteria, requiredCount);
+}
+
+bool CriteriaHandler::CanCompleteCriteriaTree(CriteriaTree const* /*tree*/)
+{
+ return true;
+}
+
+bool CriteriaHandler::IsCompletedCriteria(Criteria const* criteria, uint64 requiredAmount)
+{
+ CriteriaProgress const* progress = GetCriteriaProgress(criteria);
+ if (!progress)
+ return false;
+
+ switch (CriteriaTypes(criteria->Entry->Type))
+ {
+ case CRITERIA_TYPE_WIN_BG:
+ case CRITERIA_TYPE_KILL_CREATURE:
+ case CRITERIA_TYPE_REACH_LEVEL:
+ case CRITERIA_TYPE_REACH_GUILD_LEVEL:
+ case CRITERIA_TYPE_REACH_SKILL_LEVEL:
+ case CRITERIA_TYPE_COMPLETE_QUEST_COUNT:
+ case CRITERIA_TYPE_COMPLETE_DAILY_QUEST_DAILY:
+ case CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE:
+ case CRITERIA_TYPE_DAMAGE_DONE:
+ case CRITERIA_TYPE_HEALING_DONE:
+ case CRITERIA_TYPE_COMPLETE_DAILY_QUEST:
+ case CRITERIA_TYPE_FALL_WITHOUT_DYING:
+ case CRITERIA_TYPE_BE_SPELL_TARGET:
+ case CRITERIA_TYPE_BE_SPELL_TARGET2:
+ case CRITERIA_TYPE_CAST_SPELL:
+ case CRITERIA_TYPE_CAST_SPELL2:
+ case CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE:
+ case CRITERIA_TYPE_HONORABLE_KILL_AT_AREA:
+ case CRITERIA_TYPE_HONORABLE_KILL:
+ case CRITERIA_TYPE_EARN_HONORABLE_KILL:
+ case CRITERIA_TYPE_OWN_ITEM:
+ case CRITERIA_TYPE_WIN_RATED_ARENA:
+ case CRITERIA_TYPE_HIGHEST_PERSONAL_RATING:
+ case CRITERIA_TYPE_USE_ITEM:
+ case CRITERIA_TYPE_LOOT_ITEM:
+ case CRITERIA_TYPE_BUY_BANK_SLOT:
+ case CRITERIA_TYPE_GAIN_REPUTATION:
+ case CRITERIA_TYPE_GAIN_EXALTED_REPUTATION:
+ case CRITERIA_TYPE_VISIT_BARBER_SHOP:
+ case CRITERIA_TYPE_EQUIP_EPIC_ITEM:
+ case CRITERIA_TYPE_ROLL_NEED_ON_LOOT:
+ case CRITERIA_TYPE_ROLL_GREED_ON_LOOT:
+ case CRITERIA_TYPE_HK_CLASS:
+ case CRITERIA_TYPE_HK_RACE:
+ case CRITERIA_TYPE_DO_EMOTE:
+ case CRITERIA_TYPE_EQUIP_ITEM:
+ case CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD:
+ case CRITERIA_TYPE_LOOT_MONEY:
+ case CRITERIA_TYPE_USE_GAMEOBJECT:
+ case CRITERIA_TYPE_SPECIAL_PVP_KILL:
+ case CRITERIA_TYPE_FISH_IN_GAMEOBJECT:
+ case CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS:
+ case CRITERIA_TYPE_WIN_DUEL:
+ case CRITERIA_TYPE_LOOT_TYPE:
+ case CRITERIA_TYPE_LEARN_SKILL_LINE:
+ case CRITERIA_TYPE_USE_LFD_TO_GROUP_WITH_PLAYERS:
+ case CRITERIA_TYPE_GET_KILLING_BLOWS:
+ case CRITERIA_TYPE_CURRENCY:
+ case CRITERIA_TYPE_PLACE_GARRISON_BUILDING:
+ case CRITERIA_TYPE_OWN_BATTLE_PET_COUNT:
+ return progress->Counter >= requiredAmount;
+ case CRITERIA_TYPE_COMPLETE_ACHIEVEMENT:
+ case CRITERIA_TYPE_COMPLETE_QUEST:
+ case CRITERIA_TYPE_LEARN_SPELL:
+ case CRITERIA_TYPE_EXPLORE_AREA:
+ case CRITERIA_TYPE_RECRUIT_GARRISON_FOLLOWER:
+ case CRITERIA_TYPE_OWN_BATTLE_PET:
+ return progress->Counter >= 1;
+ case CRITERIA_TYPE_LEARN_SKILL_LEVEL:
+ return progress->Counter >= (requiredAmount * 75);
+ case CRITERIA_TYPE_EARN_ACHIEVEMENT_POINTS:
+ return progress->Counter >= 9000;
+ case CRITERIA_TYPE_WIN_ARENA:
+ return requiredAmount && progress->Counter >= requiredAmount;
+ case CRITERIA_TYPE_ON_LOGIN:
+ return true;
+ // handle all statistic-only criteria here
+ case CRITERIA_TYPE_COMPLETE_BATTLEGROUND:
+ case CRITERIA_TYPE_DEATH_AT_MAP:
+ case CRITERIA_TYPE_DEATH:
+ case CRITERIA_TYPE_DEATH_IN_DUNGEON:
+ case CRITERIA_TYPE_KILLED_BY_CREATURE:
+ case CRITERIA_TYPE_KILLED_BY_PLAYER:
+ case CRITERIA_TYPE_DEATHS_FROM:
+ case CRITERIA_TYPE_HIGHEST_TEAM_RATING:
+ case CRITERIA_TYPE_MONEY_FROM_VENDORS:
+ case CRITERIA_TYPE_GOLD_SPENT_FOR_TALENTS:
+ case CRITERIA_TYPE_NUMBER_OF_TALENT_RESETS:
+ case CRITERIA_TYPE_GOLD_SPENT_AT_BARBER:
+ case CRITERIA_TYPE_GOLD_SPENT_FOR_MAIL:
+ case CRITERIA_TYPE_LOSE_DUEL:
+ case CRITERIA_TYPE_KILL_CREATURE_TYPE:
+ case CRITERIA_TYPE_GOLD_EARNED_BY_AUCTIONS:
+ case CRITERIA_TYPE_CREATE_AUCTION:
+ case CRITERIA_TYPE_HIGHEST_AUCTION_BID:
+ case CRITERIA_TYPE_HIGHEST_AUCTION_SOLD:
+ case CRITERIA_TYPE_HIGHEST_GOLD_VALUE_OWNED:
+ case CRITERIA_TYPE_WON_AUCTIONS:
+ case CRITERIA_TYPE_GAIN_REVERED_REPUTATION:
+ case CRITERIA_TYPE_GAIN_HONORED_REPUTATION:
+ case CRITERIA_TYPE_KNOWN_FACTIONS:
+ case CRITERIA_TYPE_LOOT_EPIC_ITEM:
+ case CRITERIA_TYPE_RECEIVE_EPIC_ITEM:
+ case CRITERIA_TYPE_ROLL_NEED:
+ case CRITERIA_TYPE_ROLL_GREED:
+ case CRITERIA_TYPE_QUEST_ABANDONED:
+ case CRITERIA_TYPE_FLIGHT_PATHS_TAKEN:
+ case CRITERIA_TYPE_ACCEPTED_SUMMONINGS:
+ default:
+ break;
+ }
+
+ return false;
+}
+
+bool CriteriaHandler::CanUpdateCriteria(Criteria const* criteria, CriteriaTreeList const* trees, uint64 miscValue1, uint64 miscValue2, uint64 miscValue3, Unit const* unit, Player* referencePlayer)
+{
+ if (DisableMgr::IsDisabledFor(DISABLE_TYPE_CRITERIA, criteria->ID, nullptr))
+ {
+ TC_LOG_TRACE("criteria", "CriteriaHandler::CanUpdateCriteria: (Id: %u Type %s) Disabled", criteria->ID, CriteriaMgr::GetCriteriaTypeString(criteria->Entry->Type));
+ return false;
+ }
+
+ bool treeRequirementPassed = false;
+ for (CriteriaTree const* tree : *trees)
+ {
+ if (!CanUpdateCriteriaTree(criteria, tree, referencePlayer))
+ continue;
+
+ treeRequirementPassed = true;
+ break;
+ }
+
+ if (!treeRequirementPassed)
+ return false;
+
+ if (!RequirementsSatisfied(criteria, miscValue1, miscValue2, miscValue3, unit, referencePlayer))
+ {
+ TC_LOG_TRACE("criteria", "CriteriaHandler::CanUpdateCriteria: (Id: %u Type %s) Requirements not satisfied", criteria->ID, CriteriaMgr::GetCriteriaTypeString(criteria->Entry->Type));
+ return false;
+ }
+
+ if (criteria->Modifier && !AdditionalRequirementsSatisfied(criteria->Modifier, miscValue1, miscValue2, unit, referencePlayer))
+ {
+ TC_LOG_TRACE("criteria", "CriteriaHandler::CanUpdateCriteria: (Id: %u Type %s) Requirements have not been satisfied", criteria->ID, CriteriaMgr::GetCriteriaTypeString(criteria->Entry->Type));
+ return false;
+ }
+
+ if (!ConditionsSatisfied(criteria, referencePlayer))
+ {
+ TC_LOG_TRACE("criteria", "CriteriaHandler::CanUpdateCriteria: (Id: %u Type %s) Conditions have not been satisfied", criteria->ID, CriteriaMgr::GetCriteriaTypeString(criteria->Entry->Type));
+ return false;
+ }
+
+ return true;
+}
+
+bool CriteriaHandler::ConditionsSatisfied(Criteria const* criteria, Player* referencePlayer) const
+{
+ if (!criteria->Entry->FailEvent)
+ return true;
+
+ switch (criteria->Entry->FailEvent)
+ {
+ case CRITERIA_CONDITION_BG_MAP:
+ if (!referencePlayer->InBattleground())
+ return false;
+ break;
+ case CRITERIA_CONDITION_NOT_IN_GROUP:
+ if (referencePlayer->GetGroup())
+ return false;
+ break;
+ default:
+ break;
+ }
+
+ return true;
+}
+
+bool CriteriaHandler::RequirementsSatisfied(Criteria const* criteria, uint64 miscValue1, uint64 miscValue2, uint64 miscValue3, Unit const* unit, Player* referencePlayer) const
+{
+ switch (CriteriaTypes(criteria->Entry->Type))
+ {
+ case CRITERIA_TYPE_ACCEPTED_SUMMONINGS:
+ case CRITERIA_TYPE_COMPLETE_DAILY_QUEST:
+ case CRITERIA_TYPE_CREATE_AUCTION:
+ case CRITERIA_TYPE_FALL_WITHOUT_DYING:
+ case CRITERIA_TYPE_FLIGHT_PATHS_TAKEN:
+ case CRITERIA_TYPE_GET_KILLING_BLOWS:
+ case CRITERIA_TYPE_GOLD_EARNED_BY_AUCTIONS:
+ case CRITERIA_TYPE_GOLD_SPENT_AT_BARBER:
+ case CRITERIA_TYPE_GOLD_SPENT_FOR_MAIL:
+ case CRITERIA_TYPE_GOLD_SPENT_FOR_TALENTS:
+ case CRITERIA_TYPE_GOLD_SPENT_FOR_TRAVELLING:
+ case CRITERIA_TYPE_HIGHEST_AUCTION_BID:
+ case CRITERIA_TYPE_HIGHEST_AUCTION_SOLD:
+ case CRITERIA_TYPE_HIGHEST_HEALING_RECEIVED:
+ case CRITERIA_TYPE_HIGHEST_HEAL_CAST:
+ case CRITERIA_TYPE_HIGHEST_HIT_DEALT:
+ case CRITERIA_TYPE_HIGHEST_HIT_RECEIVED:
+ case CRITERIA_TYPE_HONORABLE_KILL:
+ case CRITERIA_TYPE_LOOT_MONEY:
+ case CRITERIA_TYPE_LOSE_DUEL:
+ case CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD:
+ case CRITERIA_TYPE_MONEY_FROM_VENDORS:
+ case CRITERIA_TYPE_NUMBER_OF_TALENT_RESETS:
+ case CRITERIA_TYPE_QUEST_ABANDONED:
+ case CRITERIA_TYPE_REACH_GUILD_LEVEL:
+ case CRITERIA_TYPE_ROLL_GREED:
+ case CRITERIA_TYPE_ROLL_NEED:
+ case CRITERIA_TYPE_SPECIAL_PVP_KILL:
+ case CRITERIA_TYPE_TOTAL_DAMAGE_RECEIVED:
+ case CRITERIA_TYPE_TOTAL_HEALING_RECEIVED:
+ case CRITERIA_TYPE_USE_LFD_TO_GROUP_WITH_PLAYERS:
+ case CRITERIA_TYPE_VISIT_BARBER_SHOP:
+ case CRITERIA_TYPE_WIN_DUEL:
+ case CRITERIA_TYPE_WIN_RATED_ARENA:
+ case CRITERIA_TYPE_WON_AUCTIONS:
+ if (!miscValue1)
+ return false;
+ break;
+ case CRITERIA_TYPE_BUY_BANK_SLOT:
+ case CRITERIA_TYPE_COMPLETE_DAILY_QUEST_DAILY:
+ case CRITERIA_TYPE_COMPLETE_QUEST_COUNT:
+ case CRITERIA_TYPE_EARN_ACHIEVEMENT_POINTS:
+ case CRITERIA_TYPE_GAIN_EXALTED_REPUTATION:
+ case CRITERIA_TYPE_GAIN_HONORED_REPUTATION:
+ case CRITERIA_TYPE_GAIN_REVERED_REPUTATION:
+ case CRITERIA_TYPE_HIGHEST_GOLD_VALUE_OWNED:
+ case CRITERIA_TYPE_HIGHEST_PERSONAL_RATING:
+ case CRITERIA_TYPE_KNOWN_FACTIONS:
+ case CRITERIA_TYPE_REACH_LEVEL:
+ case CRITERIA_TYPE_ON_LOGIN:
+ break;
+ case CRITERIA_TYPE_COMPLETE_ACHIEVEMENT:
+ if (!RequiredAchievementSatisfied(criteria->Entry->Asset.AchievementID))
+ return false;
+ break;
+ case CRITERIA_TYPE_WIN_BG:
+ if (!miscValue1 || criteria->Entry->Asset.MapID != referencePlayer->GetMapId())
+ return false;
+ break;
+ case CRITERIA_TYPE_KILL_CREATURE:
+ if (!miscValue1 || criteria->Entry->Asset.CreatureID != miscValue1)
+ return false;
+ break;
+ case CRITERIA_TYPE_REACH_SKILL_LEVEL:
+ case CRITERIA_TYPE_LEARN_SKILL_LEVEL:
+ // update at loading or specific skill update
+ if (miscValue1 && miscValue1 != criteria->Entry->Asset.SkillID)
+ return false;
+ break;
+ case CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE:
+ if (miscValue1 && miscValue1 != criteria->Entry->Asset.ZoneID)
+ return false;
+ break;
+ case CRITERIA_TYPE_COMPLETE_BATTLEGROUND:
+ case CRITERIA_TYPE_DEATH_AT_MAP:
+ if (!miscValue1 || referencePlayer->GetMapId() != criteria->Entry->Asset.MapID)
+ return false;
+ break;
+ case CRITERIA_TYPE_DEATH:
+ {
+ if (!miscValue1)
+ return false;
+ break;
+ }
+ case CRITERIA_TYPE_DEATH_IN_DUNGEON:
+ {
+ if (!miscValue1)
+ return false;
+
+ Map const* map = referencePlayer->IsInWorld() ? referencePlayer->GetMap() : sMapMgr->FindMap(referencePlayer->GetMapId(), referencePlayer->GetInstanceId());
+ if (!map || !map->IsDungeon())
+ return false;
+
+ //FIXME: work only for instances where max == min for players
+ if (map->ToInstanceMap()->GetMaxPlayers() != criteria->Entry->Asset.GroupSize)
+ return false;
+ break;
+ }
+ case CRITERIA_TYPE_KILLED_BY_CREATURE:
+ if (!miscValue1 || miscValue1 != criteria->Entry->Asset.CreatureID)
+ return false;
+ break;
+ case CRITERIA_TYPE_KILLED_BY_PLAYER:
+ if (!miscValue1 || !unit || unit->GetTypeId() != TYPEID_PLAYER)
+ return false;
+ break;
+ case CRITERIA_TYPE_DEATHS_FROM:
+ if (!miscValue1 || miscValue2 != criteria->Entry->Asset.DamageType)
+ return false;
+ break;
+ case CRITERIA_TYPE_COMPLETE_QUEST:
+ {
+ // if miscValues != 0, it contains the questID.
+ if (miscValue1)
+ {
+ if (miscValue1 != criteria->Entry->Asset.QuestID)
+ return false;
+ }
+ else
+ {
+ // login case.
+ if (!referencePlayer->GetQuestRewardStatus(criteria->Entry->Asset.QuestID))
+ return false;
+ }
+
+ if (CriteriaDataSet const* data = sCriteriaMgr->GetCriteriaDataSet(criteria))
+ if (!data->Meets(referencePlayer, unit))
+ return false;
+ break;
+ }
+ case CRITERIA_TYPE_BE_SPELL_TARGET:
+ case CRITERIA_TYPE_BE_SPELL_TARGET2:
+ case CRITERIA_TYPE_CAST_SPELL:
+ case CRITERIA_TYPE_CAST_SPELL2:
+ if (!miscValue1 || miscValue1 != criteria->Entry->Asset.SpellID)
+ return false;
+ break;
+ case CRITERIA_TYPE_LEARN_SPELL:
+ if (miscValue1 && miscValue1 != criteria->Entry->Asset.SpellID)
+ return false;
+
+ if (!referencePlayer->HasSpell(criteria->Entry->Asset.SpellID))
+ return false;
+ break;
+ case CRITERIA_TYPE_LOOT_TYPE:
+ // miscValue1 = itemId - miscValue2 = count of item loot
+ // miscValue3 = loot_type (note: 0 = LOOT_CORPSE and then it ignored)
+ if (!miscValue1 || !miscValue2 || !miscValue3 || miscValue3 != criteria->Entry->Asset.LootType)
+ return false;
+ break;
+ case CRITERIA_TYPE_OWN_ITEM:
+ if (miscValue1 && criteria->Entry->Asset.ItemID != miscValue1)
+ return false;
+ break;
+ case CRITERIA_TYPE_USE_ITEM:
+ case CRITERIA_TYPE_LOOT_ITEM:
+ case CRITERIA_TYPE_EQUIP_ITEM:
+ if (!miscValue1 || criteria->Entry->Asset.ItemID != miscValue1)
+ return false;
+ break;
+ case CRITERIA_TYPE_EXPLORE_AREA:
+ {
+ WorldMapOverlayEntry const* worldOverlayEntry = sWorldMapOverlayStore.LookupEntry(criteria->Entry->Asset.WorldMapOverlayID);
+ if (!worldOverlayEntry)
+ break;
+
+ bool matchFound = false;
+ for (int j = 0; j < MAX_WORLD_MAP_OVERLAY_AREA_IDX; ++j)
+ {
+ AreaTableEntry const* area = sAreaTableStore.LookupEntry(worldOverlayEntry->AreaID[j]);
+ if (!area)
+ break;
+
+ if (area->AreaBit < 0)
+ continue;
+
+ uint16 playerIndexOffset = uint16(uint32(area->AreaBit) / 32);
+ if (playerIndexOffset >= PLAYER_EXPLORED_ZONES_SIZE)
+ continue;
+
+ uint32 mask = 1 << (uint32(area->AreaBit) % 32);
+ if (referencePlayer->GetUInt32Value(PLAYER_EXPLORED_ZONES_1 + playerIndexOffset) & mask)
+ {
+ matchFound = true;
+ break;
+ }
+ }
+
+ if (!matchFound)
+ return false;
+ break;
+ }
+ case CRITERIA_TYPE_GAIN_REPUTATION:
+ if (miscValue1 && miscValue1 != criteria->Entry->Asset.FactionID)
+ return false;
+ break;
+ case CRITERIA_TYPE_EQUIP_EPIC_ITEM:
+ // miscValue1 = itemid miscValue2 = itemSlot
+ if (!miscValue1 || miscValue2 != criteria->Entry->Asset.ItemSlot)
+ return false;
+ break;
+ case CRITERIA_TYPE_ROLL_NEED_ON_LOOT:
+ case CRITERIA_TYPE_ROLL_GREED_ON_LOOT:
+ {
+ // miscValue1 = itemid miscValue2 = diced value
+ if (!miscValue1 || miscValue2 != criteria->Entry->Asset.RollValue)
+ return false;
+
+ ItemTemplate const* proto = sObjectMgr->GetItemTemplate(uint32(miscValue1));
+ if (!proto)
+ return false;
+ break;
+ }
+ case CRITERIA_TYPE_DO_EMOTE:
+ if (!miscValue1 || miscValue1 != criteria->Entry->Asset.EmoteID)
+ return false;
+ break;
+ case CRITERIA_TYPE_DAMAGE_DONE:
+ case CRITERIA_TYPE_HEALING_DONE:
+ if (!miscValue1)
+ return false;
+
+ if (criteria->Entry->FailEvent == CRITERIA_CONDITION_BG_MAP)
+ {
+ if (!referencePlayer->InBattleground())
+ return false;
+
+ // map specific case (BG in fact) expected player targeted damage/heal
+ if (!unit || unit->GetTypeId() != TYPEID_PLAYER)
+ return false;
+ }
+ break;
+ case CRITERIA_TYPE_USE_GAMEOBJECT:
+ case CRITERIA_TYPE_FISH_IN_GAMEOBJECT:
+ if (!miscValue1 || miscValue1 != criteria->Entry->Asset.GameObjectID)
+ return false;
+ break;
+ case CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS:
+ case CRITERIA_TYPE_LEARN_SKILL_LINE:
+ if (miscValue1 && miscValue1 != criteria->Entry->Asset.SkillID)
+ return false;
+ break;
+ case CRITERIA_TYPE_LOOT_EPIC_ITEM:
+ case CRITERIA_TYPE_RECEIVE_EPIC_ITEM:
+ {
+ if (!miscValue1)
+ return false;
+ ItemTemplate const* proto = sObjectMgr->GetItemTemplate(uint32(miscValue1));
+ if (!proto || proto->GetQuality() < ITEM_QUALITY_EPIC)
+ return false;
+ break;
+ }
+ case CRITERIA_TYPE_HK_CLASS:
+ if (!miscValue1 || miscValue1 != criteria->Entry->Asset.ClassID)
+ return false;
+ break;
+ case CRITERIA_TYPE_HK_RACE:
+ if (!miscValue1 || miscValue1 != criteria->Entry->Asset.RaceID)
+ return false;
+ break;
+ case CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE:
+ if (!miscValue1 || miscValue1 != criteria->Entry->Asset.ObjectiveId)
+ return false;
+ break;
+ case CRITERIA_TYPE_HONORABLE_KILL_AT_AREA:
+ if (!miscValue1 || miscValue1 != criteria->Entry->Asset.AreaID)
+ return false;
+ break;
+ case CRITERIA_TYPE_CURRENCY:
+ if (!miscValue1 || !miscValue2 || int64(miscValue2) < 0
+ || miscValue1 != criteria->Entry->Asset.CurrencyID)
+ return false;
+ break;
+ case CRITERIA_TYPE_WIN_ARENA:
+ if (miscValue1 != criteria->Entry->Asset.MapID)
+ return false;
+ break;
+ case CRITERIA_TYPE_HIGHEST_TEAM_RATING:
+ return false;
+ case CRITERIA_TYPE_PLACE_GARRISON_BUILDING:
+ if (miscValue1 != criteria->Entry->Asset.GarrBuildingID)
+ return false;
+ break;
+ default:
+ break;
+ }
+ return true;
+}
+
+bool CriteriaHandler::AdditionalRequirementsSatisfied(ModifierTreeNode const* tree, uint64 miscValue1, uint64 miscValue2, Unit const* unit, Player* referencePlayer) const
+{
+ for (ModifierTreeNode const* node : tree->Children)
+ if (!AdditionalRequirementsSatisfied(node, miscValue1, miscValue2, unit, referencePlayer))
+ return false;
+
+ uint32 reqType = tree->Entry->Type;
+ if (!reqType)
+ return true;
+
+ uint32 reqValue = tree->Entry->Asset[0];
+
+ switch (CriteriaAdditionalCondition(reqType))
+ {
+ case CRITERIA_ADDITIONAL_CONDITION_TARGET_CREATURE_ENTRY: // 4
+ if (!unit || unit->GetEntry() != reqValue)
+ return false;
+ break;
+ case CRITERIA_ADDITIONAL_CONDITION_TARGET_MUST_BE_PLAYER: // 5
+ if (!unit || unit->GetTypeId() != TYPEID_PLAYER)
+ return false;
+ break;
+ case CRITERIA_ADDITIONAL_CONDITION_TARGET_MUST_BE_DEAD: // 6
+ if (!unit || unit->IsAlive())
+ return false;
+ break;
+ case CRITERIA_ADDITIONAL_CONDITION_TARGET_MUST_BE_ENEMY: // 7
+ if (!unit || !referencePlayer->IsHostileTo(unit))
+ return false;
+ break;
+ case CRITERIA_ADDITIONAL_CONDITION_SOURCE_HAS_AURA: // 8
+ if (!referencePlayer->HasAura(reqValue))
+ return false;
+ break;
+ case CRITERIA_ADDITIONAL_CONDITION_TARGET_HAS_AURA: // 10
+ if (!unit || !unit->HasAura(reqValue))
+ return false;
+ case CRITERIA_ADDITIONAL_CONDITION_TARGET_HAS_AURA_TYPE: // 11
+ if (!unit || !unit->HasAuraType(AuraType(reqValue)))
+ return false;
+ break;
+ case CRITERIA_ADDITIONAL_CONDITION_ITEM_QUALITY_MIN: // 14
+ {
+ // miscValue1 is itemid
+ ItemTemplate const* const item = sObjectMgr->GetItemTemplate(uint32(miscValue1));
+ if (!item || item->GetQuality() < reqValue)
+ return false;
+ break;
+ }
+ case CRITERIA_ADDITIONAL_CONDITION_ITEM_QUALITY_EQUALS: // 15
+ {
+ // miscValue1 is itemid
+ ItemTemplate const* const item = sObjectMgr->GetItemTemplate(uint32(miscValue1));
+ if (!item || item->GetQuality() != reqValue)
+ return false;
+ break;
+ }
+ case CRITERIA_ADDITIONAL_CONDITION_SOURCE_AREA_OR_ZONE: // 17
+ {
+ uint32 zoneId, areaId;
+ referencePlayer->GetZoneAndAreaId(zoneId, areaId);
+ if (zoneId != reqValue && areaId != reqValue)
+ return false;
+ break;
+ }
+ case CRITERIA_ADDITIONAL_CONDITION_TARGET_AREA_OR_ZONE: // 18
+ {
+ if (!unit)
+ return false;
+ uint32 zoneId, areaId;
+ unit->GetZoneAndAreaId(zoneId, areaId);
+ if (zoneId != reqValue && areaId != reqValue)
+ return false;
+ break;
+ }
+ case CRITERIA_ADDITIONAL_CONDITION_MAP_DIFFICULTY: // 20
+ if (uint32(referencePlayer->GetMap()->GetDifficultyID()) != reqValue)
+ return false;
+ break;
+ case CRITERIA_ADDITIONAL_CONDITION_ARENA_TYPE:
+ {
+ Battleground* bg = referencePlayer->GetBattleground();
+ if (!bg || !bg->isArena() || bg->GetArenaType() != reqValue)
+ return false;
+ break;
+ }
+ case CRITERIA_ADDITIONAL_CONDITION_SOURCE_RACE: // 25
+ if (referencePlayer->getRace() != reqValue)
+ return false;
+ break;
+ case CRITERIA_ADDITIONAL_CONDITION_SOURCE_CLASS: // 26
+ if (referencePlayer->getClass() != reqValue)
+ return false;
+ break;
+ case CRITERIA_ADDITIONAL_CONDITION_TARGET_RACE: // 27
+ if (!unit || unit->GetTypeId() != TYPEID_PLAYER || unit->getRace() != reqValue)
+ return false;
+ break;
+ case CRITERIA_ADDITIONAL_CONDITION_TARGET_CLASS: // 28
+ if (!unit || unit->GetTypeId() != TYPEID_PLAYER || unit->getClass() != reqValue)
+ return false;
+ break;
+ case CRITERIA_ADDITIONAL_CONDITION_MAX_GROUP_MEMBERS: // 29
+ if (referencePlayer->GetGroup() && referencePlayer->GetGroup()->GetMembersCount() >= reqValue)
+ return false;
+ break;
+ case CRITERIA_ADDITIONAL_CONDITION_TARGET_CREATURE_TYPE: // 30
+ {
+ if (!unit)
+ return false;
+ Creature const* const creature = unit->ToCreature();
+ if (!creature || creature->GetCreatureType() != reqValue)
+ return false;
+ break;
+ }
+ case CRITERIA_ADDITIONAL_CONDITION_SOURCE_MAP: // 32
+ if (referencePlayer->GetMapId() != reqValue)
+ return false;
+ break;
+ case CRITERIA_ADDITIONAL_CONDITION_TITLE_BIT_INDEX: // 38
+ // miscValue1 is title's bit index
+ if (miscValue1 != reqValue)
+ return false;
+ break;
+ case CRITERIA_ADDITIONAL_CONDITION_SOURCE_LEVEL: // 39
+ if (referencePlayer->getLevel() != reqValue)
+ return false;
+ break;
+ case CRITERIA_ADDITIONAL_CONDITION_TARGET_LEVEL: // 40
+ if (!unit || unit->getLevel() != reqValue)
+ return false;
+ break;
+ case CRITERIA_ADDITIONAL_CONDITION_TARGET_ZONE: // 41
+ if (!unit || unit->GetZoneId() != reqValue)
+ return false;
+ break;
+ case CRITERIA_ADDITIONAL_CONDITION_TARGET_HEALTH_PERCENT_BELOW: // 46
+ if (!unit || unit->GetHealthPct() >= reqValue)
+ return false;
+ break;
+ case CRITERIA_ADDITIONAL_CONDITION_BATTLE_PET_SPECIES: // 91
+ if (miscValue1 != reqValue)
+ return false;
+ break;
+ case CRITERIA_ADDITIONAL_CONDITION_GARRISON_FOLLOWER_QUALITY: // 145
+ {
+ if (!referencePlayer)
+ return false;
+ Garrison* garrison = referencePlayer->GetGarrison();
+ if (!garrison)
+ return false;
+ Garrison::Follower const* follower = garrison->GetFollower(miscValue1);
+ if (!follower || follower->PacketInfo.Quality != reqValue)
+ return false;
+
+ break;
+ }
+ case CRITERIA_ADDITIONAL_CONDITION_GARRISON_FOLLOWER_LEVEL: // 146
+ {
+ if (!referencePlayer)
+ return false;
+ Garrison* garrison = referencePlayer->GetGarrison();
+ if (!garrison)
+ return false;
+ Garrison::Follower const* follower = garrison->GetFollower(miscValue1);
+ if (!follower || follower->PacketInfo.FollowerLevel < reqValue)
+ return false;
+
+ break;
+ }
+ case CRITERIA_ADDITIONAL_CONDITION_GARRISON_FOLLOWER_ILVL: // 184
+ {
+ if (!referencePlayer)
+ return false;
+ Garrison* garrison = referencePlayer->GetGarrison();
+ if (!garrison)
+ return false;
+ Garrison::Follower const* follower = garrison->GetFollower(miscValue1);
+ if (!follower || follower->GetItemLevel() < reqValue)
+ return false;
+ break;
+ }
+ default:
+ break;
+ }
+ return true;
+}
+
+char const* CriteriaMgr::GetCriteriaTypeString(uint32 type)
+{
+ return GetCriteriaTypeString(CriteriaTypes(type));
+}
+
+char const* CriteriaMgr::GetCriteriaTypeString(CriteriaTypes type)
+{
+ switch (type)
+ {
+ case CRITERIA_TYPE_KILL_CREATURE:
+ return "KILL_CREATURE";
+ case CRITERIA_TYPE_WIN_BG:
+ return "TYPE_WIN_BG";
+ case CRITERIA_TYPE_COMPLETE_ARCHAEOLOGY_PROJECTS:
+ return "COMPLETE_RESEARCH";
+ case CRITERIA_TYPE_REACH_LEVEL:
+ return "REACH_LEVEL";
+ case CRITERIA_TYPE_REACH_SKILL_LEVEL:
+ return "REACH_SKILL_LEVEL";
+ case CRITERIA_TYPE_COMPLETE_ACHIEVEMENT:
+ return "COMPLETE_ACHIEVEMENT";
+ case CRITERIA_TYPE_COMPLETE_QUEST_COUNT:
+ return "COMPLETE_QUEST_COUNT";
+ case CRITERIA_TYPE_COMPLETE_DAILY_QUEST_DAILY:
+ return "COMPLETE_DAILY_QUEST_DAILY";
+ case CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE:
+ return "COMPLETE_QUESTS_IN_ZONE";
+ case CRITERIA_TYPE_CURRENCY:
+ return "CURRENCY";
+ case CRITERIA_TYPE_DAMAGE_DONE:
+ return "DAMAGE_DONE";
+ case CRITERIA_TYPE_COMPLETE_DAILY_QUEST:
+ return "COMPLETE_DAILY_QUEST";
+ case CRITERIA_TYPE_COMPLETE_BATTLEGROUND:
+ return "COMPLETE_BATTLEGROUND";
+ case CRITERIA_TYPE_DEATH_AT_MAP:
+ return "DEATH_AT_MAP";
+ case CRITERIA_TYPE_DEATH:
+ return "DEATH";
+ case CRITERIA_TYPE_DEATH_IN_DUNGEON:
+ return "DEATH_IN_DUNGEON";
+ case CRITERIA_TYPE_COMPLETE_RAID:
+ return "COMPLETE_RAID";
+ case CRITERIA_TYPE_KILLED_BY_CREATURE:
+ return "KILLED_BY_CREATURE";
+ case CRITERIA_TYPE_KILLED_BY_PLAYER:
+ return "KILLED_BY_PLAYER";
+ case CRITERIA_TYPE_FALL_WITHOUT_DYING:
+ return "FALL_WITHOUT_DYING";
+ case CRITERIA_TYPE_DEATHS_FROM:
+ return "DEATHS_FROM";
+ case CRITERIA_TYPE_COMPLETE_QUEST:
+ return "COMPLETE_QUEST";
+ case CRITERIA_TYPE_BE_SPELL_TARGET:
+ return "BE_SPELL_TARGET";
+ case CRITERIA_TYPE_CAST_SPELL:
+ return "CAST_SPELL";
+ case CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE:
+ return "BG_OBJECTIVE_CAPTURE";
+ case CRITERIA_TYPE_HONORABLE_KILL_AT_AREA:
+ return "HONORABLE_KILL_AT_AREA";
+ case CRITERIA_TYPE_WIN_ARENA:
+ return "WIN_ARENA";
+ case CRITERIA_TYPE_PLAY_ARENA:
+ return "PLAY_ARENA";
+ case CRITERIA_TYPE_LEARN_SPELL:
+ return "LEARN_SPELL";
+ case CRITERIA_TYPE_HONORABLE_KILL:
+ return "HONORABLE_KILL";
+ case CRITERIA_TYPE_OWN_ITEM:
+ return "OWN_ITEM";
+ case CRITERIA_TYPE_WIN_RATED_ARENA:
+ return "WIN_RATED_ARENA";
+ case CRITERIA_TYPE_HIGHEST_TEAM_RATING:
+ return "HIGHEST_TEAM_RATING";
+ case CRITERIA_TYPE_HIGHEST_PERSONAL_RATING:
+ return "HIGHEST_PERSONAL_RATING";
+ case CRITERIA_TYPE_LEARN_SKILL_LEVEL:
+ return "LEARN_SKILL_LEVEL";
+ case CRITERIA_TYPE_USE_ITEM:
+ return "USE_ITEM";
+ case CRITERIA_TYPE_LOOT_ITEM:
+ return "LOOT_ITEM";
+ case CRITERIA_TYPE_EXPLORE_AREA:
+ return "EXPLORE_AREA";
+ case CRITERIA_TYPE_OWN_RANK:
+ return "OWN_RANK";
+ case CRITERIA_TYPE_BUY_BANK_SLOT:
+ return "BUY_BANK_SLOT";
+ case CRITERIA_TYPE_GAIN_REPUTATION:
+ return "GAIN_REPUTATION";
+ case CRITERIA_TYPE_GAIN_EXALTED_REPUTATION:
+ return "GAIN_EXALTED_REPUTATION";
+ case CRITERIA_TYPE_VISIT_BARBER_SHOP:
+ return "VISIT_BARBER_SHOP";
+ case CRITERIA_TYPE_EQUIP_EPIC_ITEM:
+ return "EQUIP_EPIC_ITEM";
+ case CRITERIA_TYPE_ROLL_NEED_ON_LOOT:
+ return "ROLL_NEED_ON_LOOT";
+ case CRITERIA_TYPE_ROLL_GREED_ON_LOOT:
+ return "GREED_ON_LOOT";
+ case CRITERIA_TYPE_HK_CLASS:
+ return "HK_CLASS";
+ case CRITERIA_TYPE_HK_RACE:
+ return "HK_RACE";
+ case CRITERIA_TYPE_DO_EMOTE:
+ return "DO_EMOTE";
+ case CRITERIA_TYPE_HEALING_DONE:
+ return "HEALING_DONE";
+ case CRITERIA_TYPE_GET_KILLING_BLOWS:
+ return "GET_KILLING_BLOWS";
+ case CRITERIA_TYPE_EQUIP_ITEM:
+ return "EQUIP_ITEM";
+ case CRITERIA_TYPE_MONEY_FROM_VENDORS:
+ return "MONEY_FROM_VENDORS";
+ case CRITERIA_TYPE_GOLD_SPENT_FOR_TALENTS:
+ return "GOLD_SPENT_FOR_TALENTS";
+ case CRITERIA_TYPE_NUMBER_OF_TALENT_RESETS:
+ return "NUMBER_OF_TALENT_RESETS";
+ case CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD:
+ return "MONEY_FROM_QUEST_REWARD";
+ case CRITERIA_TYPE_GOLD_SPENT_FOR_TRAVELLING:
+ return "GOLD_SPENT_FOR_TRAVELLING";
+ case CRITERIA_TYPE_GOLD_SPENT_AT_BARBER:
+ return "GOLD_SPENT_AT_BARBER";
+ case CRITERIA_TYPE_GOLD_SPENT_FOR_MAIL:
+ return "GOLD_SPENT_FOR_MAIL";
+ case CRITERIA_TYPE_LOOT_MONEY:
+ return "LOOT_MONEY";
+ case CRITERIA_TYPE_USE_GAMEOBJECT:
+ return "USE_GAMEOBJECT";
+ case CRITERIA_TYPE_BE_SPELL_TARGET2:
+ return "BE_SPELL_TARGET2";
+ case CRITERIA_TYPE_SPECIAL_PVP_KILL:
+ return "SPECIAL_PVP_KILL";
+ case CRITERIA_TYPE_FISH_IN_GAMEOBJECT:
+ return "FISH_IN_GAMEOBJECT";
+ case CRITERIA_TYPE_ON_LOGIN:
+ return "ON_LOGIN";
+ case CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS:
+ return "LEARN_SKILLLINE_SPELLS";
+ case CRITERIA_TYPE_WIN_DUEL:
+ return "WIN_DUEL";
+ case CRITERIA_TYPE_LOSE_DUEL:
+ return "LOSE_DUEL";
+ case CRITERIA_TYPE_KILL_CREATURE_TYPE:
+ return "KILL_CREATURE_TYPE";
+ case CRITERIA_TYPE_GOLD_EARNED_BY_AUCTIONS:
+ return "GOLD_EARNED_BY_AUCTIONS";
+ case CRITERIA_TYPE_CREATE_AUCTION:
+ return "CREATE_AUCTION";
+ case CRITERIA_TYPE_HIGHEST_AUCTION_BID:
+ return "HIGHEST_AUCTION_BID";
+ case CRITERIA_TYPE_WON_AUCTIONS:
+ return "WON_AUCTIONS";
+ case CRITERIA_TYPE_HIGHEST_AUCTION_SOLD:
+ return "HIGHEST_AUCTION_SOLD";
+ case CRITERIA_TYPE_HIGHEST_GOLD_VALUE_OWNED:
+ return "HIGHEST_GOLD_VALUE_OWNED";
+ case CRITERIA_TYPE_GAIN_REVERED_REPUTATION:
+ return "GAIN_REVERED_REPUTATION";
+ case CRITERIA_TYPE_GAIN_HONORED_REPUTATION:
+ return "GAIN_HONORED_REPUTATION";
+ case CRITERIA_TYPE_KNOWN_FACTIONS:
+ return "KNOWN_FACTIONS";
+ case CRITERIA_TYPE_LOOT_EPIC_ITEM:
+ return "LOOT_EPIC_ITEM";
+ case CRITERIA_TYPE_RECEIVE_EPIC_ITEM:
+ return "RECEIVE_EPIC_ITEM";
+ case CRITERIA_TYPE_ROLL_NEED:
+ return "ROLL_NEED";
+ case CRITERIA_TYPE_ROLL_GREED:
+ return "ROLL_GREED";
+ case CRITERIA_TYPE_HIGHEST_HIT_DEALT:
+ return "HIT_DEALT";
+ case CRITERIA_TYPE_HIGHEST_HIT_RECEIVED:
+ return "HIT_RECEIVED";
+ case CRITERIA_TYPE_TOTAL_DAMAGE_RECEIVED:
+ return "TOTAL_DAMAGE_RECEIVED";
+ case CRITERIA_TYPE_HIGHEST_HEAL_CAST:
+ return "HIGHEST_HEAL_CAST";
+ case CRITERIA_TYPE_TOTAL_HEALING_RECEIVED:
+ return "TOTAL_HEALING_RECEIVED";
+ case CRITERIA_TYPE_HIGHEST_HEALING_RECEIVED:
+ return "HIGHEST_HEALING_RECEIVED";
+ case CRITERIA_TYPE_QUEST_ABANDONED:
+ return "QUEST_ABANDONED";
+ case CRITERIA_TYPE_FLIGHT_PATHS_TAKEN:
+ return "FLIGHT_PATHS_TAKEN";
+ case CRITERIA_TYPE_LOOT_TYPE:
+ return "LOOT_TYPE";
+ case CRITERIA_TYPE_CAST_SPELL2:
+ return "CAST_SPELL2";
+ case CRITERIA_TYPE_LEARN_SKILL_LINE:
+ return "LEARN_SKILL_LINE";
+ case CRITERIA_TYPE_EARN_HONORABLE_KILL:
+ return "EARN_HONORABLE_KILL";
+ case CRITERIA_TYPE_ACCEPTED_SUMMONINGS:
+ return "ACCEPTED_SUMMONINGS";
+ case CRITERIA_TYPE_EARN_ACHIEVEMENT_POINTS:
+ return "EARN_ACHIEVEMENT_POINTS";
+ case CRITERIA_TYPE_USE_LFD_TO_GROUP_WITH_PLAYERS:
+ return "USE_LFD_TO_GROUP_WITH_PLAYERS";
+ case CRITERIA_TYPE_SPENT_GOLD_GUILD_REPAIRS:
+ return "SPENT_GOLD_GUILD_REPAIRS";
+ case CRITERIA_TYPE_REACH_GUILD_LEVEL:
+ return "REACH_GUILD_LEVEL";
+ case CRITERIA_TYPE_CRAFT_ITEMS_GUILD:
+ return "CRAFT_ITEMS_GUILD";
+ case CRITERIA_TYPE_CATCH_FROM_POOL:
+ return "CATCH_FROM_POOL";
+ case CRITERIA_TYPE_BUY_GUILD_BANK_SLOTS:
+ return "BUY_GUILD_BANK_SLOTS";
+ case CRITERIA_TYPE_EARN_GUILD_ACHIEVEMENT_POINTS:
+ return "EARN_GUILD_ACHIEVEMENT_POINTS";
+ case CRITERIA_TYPE_WIN_RATED_BATTLEGROUND:
+ return "WIN_RATED_BATTLEGROUND";
+ case CRITERIA_TYPE_REACH_BG_RATING:
+ return "REACH_BG_RATING";
+ case CRITERIA_TYPE_BUY_GUILD_TABARD:
+ return "BUY_GUILD_TABARD";
+ case CRITERIA_TYPE_COMPLETE_QUESTS_GUILD:
+ return "COMPLETE_QUESTS_GUILD";
+ case CRITERIA_TYPE_HONORABLE_KILLS_GUILD:
+ return "HONORABLE_KILLS_GUILD";
+ case CRITERIA_TYPE_KILL_CREATURE_TYPE_GUILD:
+ return "KILL_CREATURE_TYPE_GUILD";
+ case CRITERIA_TYPE_COMPLETE_GUILD_CHALLENGE_TYPE:
+ return "GUILD_CHALLENGE_TYPE";
+ case CRITERIA_TYPE_COMPLETE_GUILD_CHALLENGE:
+ return "GUILD_CHALLENGE";
+ case CRITERIA_TYPE_LFR_DUNGEONS_COMPLETED:
+ return "LFR_DUNGEONS_COMPLETED";
+ case CRITERIA_TYPE_LFR_LEAVES:
+ return "LFR_LEAVES";
+ case CRITERIA_TYPE_LFR_VOTE_KICKS_INITIATED_BY_PLAYER:
+ return "LFR_VOTE_KICKS_INITIATED_BY_PLAYER";
+ case CRITERIA_TYPE_LFR_VOTE_KICKS_NOT_INIT_BY_PLAYER:
+ return "LFR_VOTE_KICKS_NOT_INIT_BY_PLAYER";
+ case CRITERIA_TYPE_BE_KICKED_FROM_LFR:
+ return "BE_KICKED_FROM_LFR";
+ case CRITERIA_TYPE_COUNT_OF_LFR_QUEUE_BOOSTS_BY_TANK:
+ return "COUNT_OF_LFR_QUEUE_BOOSTS_BY_TANK";
+ case CRITERIA_TYPE_COMPLETE_SCENARIO_COUNT:
+ return "COMPLETE_SCENARIO_COUNT";
+ case CRITERIA_TYPE_COMPLETE_SCENARIO:
+ return "COMPLETE_SCENARIO";
+ case CRITERIA_TYPE_OWN_BATTLE_PET:
+ return "OWN_BATTLE_PET";
+ case CRITERIA_TYPE_OWN_BATTLE_PET_COUNT:
+ return "OWN_BATTLE_PET_COUNT";
+ case CRITERIA_TYPE_CAPTURE_BATTLE_PET:
+ return "CAPTURE_BATTLE_PET";
+ case CRITERIA_TYPE_WIN_PET_BATTLE:
+ return "WIN_PET_BATTLE";
+ case CRITERIA_TYPE_LEVEL_BATTLE_PET:
+ return "LEVEL_BATTLE_PET";
+ case CRITERIA_TYPE_CAPTURE_BATTLE_PET_CREDIT:
+ return "CAPTURE_BATTLE_PET_CREDIT";
+ case CRITERIA_TYPE_LEVEL_BATTLE_PET_CREDIT:
+ return "LEVEL_BATTLE_PET_CREDIT";
+ case CRITERIA_TYPE_ENTER_AREA:
+ return "ENTER_AREA";
+ case CRITERIA_TYPE_LEAVE_AREA:
+ return "LEAVE_AREA";
+ case CRITERIA_TYPE_COMPLETE_DUNGEON_ENCOUNTER:
+ return "COMPLETE_DUNGEON_ENCOUNTER";
+ case CRITERIA_TYPE_PLACE_GARRISON_BUILDING:
+ return "PLACE_GARRISON_BUILDING";
+ case CRITERIA_TYPE_UPGRADE_GARRISON_BUILDING:
+ return "UPGRADE_GARRISON_BUILDING";
+ case CRITERIA_TYPE_CONSTRUCT_GARRISON_BUILDING:
+ return "CONSTRUCT_GARRISON_BUILDING";
+ case CRITERIA_TYPE_UPGRADE_GARRISON:
+ return "UPGRADE_GARRISON";
+ case CRITERIA_TYPE_START_GARRISON_MISSION:
+ return "START_GARRISON_MISSION";
+ case CRITERIA_TYPE_COMPLETE_GARRISON_MISSION_COUNT:
+ return "COMPLETE_GARRISON_MISSION_COUNT";
+ case CRITERIA_TYPE_COMPLETE_GARRISON_MISSION:
+ return "COMPLETE_GARRISON_MISSION";
+ case CRITERIA_TYPE_RECRUIT_GARRISON_FOLLOWER_COUNT:
+ return "RECRUIT_GARRISON_FOLLOWER_COUNT";
+ case CRITERIA_TYPE_LEARN_GARRISON_BLUEPRINT_COUNT:
+ return "LEARN_GARRISON_BLUEPRINT_COUNT";
+ case CRITERIA_TYPE_COMPLETE_GARRISON_SHIPMENT:
+ return "COMPLETE_GARRISON_SHIPMENT";
+ case CRITERIA_TYPE_RAISE_GARRISON_FOLLOWER_ITEM_LEVEL:
+ return "RAISE_GARRISON_FOLLOWER_ITEM_LEVEL";
+ case CRITERIA_TYPE_RAISE_GARRISON_FOLLOWER_LEVEL:
+ return "RAISE_GARRISON_FOLLOWER_LEVEL";
+ case CRITERIA_TYPE_OWN_TOY:
+ return "OWN_TOY";
+ case CRITERIA_TYPE_OWN_TOY_COUNT:
+ return "OWN_TOY_COUNT";
+ case CRITERIA_TYPE_RECRUIT_GARRISON_FOLLOWER:
+ return "RECRUIT_GARRISON_FOLLOWER";
+ case CRITERIA_TYPE_OWN_HEIRLOOMS:
+ return "OWN_HEIRLOOMS";
+ }
+ return "MISSING_TYPE";
+}
+
+CriteriaMgr* CriteriaMgr::Instance()
+{
+ static CriteriaMgr instance;
+ return &instance;
+}
+
+//==========================================================
+CriteriaMgr::~CriteriaMgr()
+{
+ for (auto itr = _criteriaTrees.begin(); itr != _criteriaTrees.end(); ++itr)
+ delete itr->second;
+
+ for (auto itr = _criteria.begin(); itr != _criteria.end(); ++itr)
+ delete itr->second;
+
+ for (auto itr = _criteriaModifiers.begin(); itr != _criteriaModifiers.end(); ++itr)
+ delete itr->second;
+}
+
+void CriteriaMgr::LoadCriteriaModifiersTree()
+{
+ uint32 oldMSTime = getMSTime();
+
+ if (sModifierTreeStore.GetNumRows() == 0)
+ {
+ TC_LOG_ERROR("server.loading", ">> Loaded 0 criteria modifiers.");
+ return;
+ }
+
+ // Load modifier tree nodes
+ for (uint32 i = 0; i < sModifierTreeStore.GetNumRows(); ++i)
+ {
+ ModifierTreeEntry const* tree = sModifierTreeStore.LookupEntry(i);
+ if (!tree)
+ continue;
+
+ ModifierTreeNode* node = new ModifierTreeNode();
+ node->Entry = tree;
+ _criteriaModifiers[node->Entry->ID] = node;
+ }
+
+ // Build tree
+ for (auto itr = _criteriaModifiers.begin(); itr != _criteriaModifiers.end(); ++itr)
+ {
+ if (!itr->second->Entry->Parent)
+ continue;
+
+ auto parent = _criteriaModifiers.find(itr->second->Entry->Parent);
+ if (parent != _criteriaModifiers.end())
+ parent->second->Children.push_back(itr->second);
+ }
+
+ TC_LOG_INFO("server.loading", ">> Loaded %u criteria modifiers in %u ms", uint32(_criteriaModifiers.size()), GetMSTimeDiffToNow(oldMSTime));
+}
+
+template<typename T>
+T GetEntry(std::unordered_map<uint32, T> const& map, CriteriaTreeEntry const* tree)
+{
+ CriteriaTreeEntry const* cur = tree;
+ auto itr = map.find(tree->ID);
+ while (itr == map.end())
+ {
+ if (!cur->Parent)
+ break;
+
+ cur = sCriteriaTreeStore.LookupEntry(cur->Parent);
+ if (!cur)
+ break;
+
+ itr = map.find(cur->ID);
+ }
+
+ if (itr == map.end())
+ return nullptr;
+
+ return itr->second;
+};
+
+void CriteriaMgr::LoadCriteriaList()
+{
+ uint32 oldMSTime = getMSTime();
+
+ if (sCriteriaTreeStore.GetNumRows() == 0)
+ {
+ TC_LOG_ERROR("server.loading", ">> Loaded 0 criteria.");
+ return;
+ }
+
+ std::unordered_map<uint32 /*criteriaTreeID*/, AchievementEntry const*> achievementCriteriaTreeIds;
+ for (AchievementEntry const* achievement : sAchievementStore)
+ if (achievement->CriteriaTree)
+ achievementCriteriaTreeIds[achievement->CriteriaTree] = achievement;
+
+ std::unordered_map<uint32 /*criteriaTreeID*/, ScenarioStepEntry const*> scenarioCriteriaTreeIds;
+ //for (ScenarioStepEntry const* scenarioStep : sScenarioStepStore)
+ // if (scenarioStep->CriteriaTreeID)
+ // scenarioCriteriaTreeIds[scenarioStep->CriteriaTreeID] = scenarioStep;
+
+ // Load criteria tree nodes
+ for (CriteriaTreeEntry const* tree : sCriteriaTreeStore)
+ {
+ // Find linked achievement
+ AchievementEntry const* achievement = GetEntry(achievementCriteriaTreeIds, tree);
+ ScenarioStepEntry const* scenarioStep = GetEntry(scenarioCriteriaTreeIds, tree);
+ if (!achievement && !scenarioStep)
+ continue;
+
+ CriteriaTree* criteriaTree = new CriteriaTree();
+ criteriaTree->ID = tree->ID;
+ criteriaTree->Achievement = achievement;
+ criteriaTree->ScenarioStep = scenarioStep;
+ criteriaTree->Entry = tree;
+
+ _criteriaTrees[criteriaTree->Entry->ID] = criteriaTree;
+ }
+
+ // Build tree
+ for (auto itr = _criteriaTrees.begin(); itr != _criteriaTrees.end(); ++itr)
+ {
+ if (!itr->second->Entry->Parent)
+ continue;
+
+ auto parent = _criteriaTrees.find(itr->second->Entry->Parent);
+ if (parent != _criteriaTrees.end())
+ {
+ parent->second->Children.push_back(itr->second);
+ while (parent != _criteriaTrees.end())
+ {
+ auto cur = parent;
+ parent = _criteriaTrees.find(parent->second->Entry->Parent);
+ if (parent == _criteriaTrees.end())
+ {
+ if (sCriteriaStore.LookupEntry(itr->second->Entry->CriteriaID))
+ _criteriaTreeByCriteria[itr->second->Entry->CriteriaID].push_back(cur->second);
+ }
+ }
+ }
+ else if (sCriteriaStore.LookupEntry(itr->second->Entry->CriteriaID))
+ _criteriaTreeByCriteria[itr->second->Entry->CriteriaID].push_back(itr->second);
+ }
+
+ // Load criteria
+ uint32 criterias = 0;
+ uint32 guildCriterias = 0;
+ uint32 scenarioCriterias = 0;
+ for (CriteriaEntry const* criteriaEntry : sCriteriaStore)
+ {
+ auto treeItr = _criteriaTreeByCriteria.find(criteriaEntry->ID);
+ if (treeItr == _criteriaTreeByCriteria.end())
+ continue;
+
+ Criteria* criteria = new Criteria();
+ criteria->ID = criteriaEntry->ID;
+ criteria->Entry = criteriaEntry;
+ auto mod = _criteriaModifiers.find(criteriaEntry->ModifierTreeId);
+ if (mod != _criteriaModifiers.end())
+ criteria->Modifier = mod->second;
+
+ _criteria[criteria->ID] = criteria;
+
+ for (CriteriaTree const* tree : treeItr->second)
+ {
+ if (AchievementEntry const* achievement = tree->Achievement)
+ {
+ if (achievement->Flags & ACHIEVEMENT_FLAG_GUILD)
+ criteria->FlagsCu |= CRITERIA_FLAG_CU_GUILD;
+ else if (achievement->Flags & ACHIEVEMENT_FLAG_ACCOUNT)
+ criteria->FlagsCu |= CRITERIA_FLAG_CU_ACCOUNT;
+ else
+ criteria->FlagsCu |= CRITERIA_FLAG_CU_PLAYER;
+ }
+ else if (tree->ScenarioStep)
+ criteria->FlagsCu |= CRITERIA_FLAG_CU_SCENARIO;
+ }
+
+ if (criteria->FlagsCu & (CRITERIA_FLAG_CU_PLAYER | CRITERIA_FLAG_CU_ACCOUNT))
+ {
+ ++criterias;
+ _criteriasByType[criteriaEntry->Type].push_back(criteria);
+ }
+
+ if (criteria->FlagsCu & CRITERIA_FLAG_CU_GUILD)
+ {
+ ++guildCriterias;
+ _guildCriteriasByType[criteriaEntry->Type].push_back(criteria);
+ }
+
+ if (criteria->FlagsCu & CRITERIA_FLAG_CU_SCENARIO)
+ {
+ ++scenarioCriterias;
+ _scenarioCriteriasByType[criteriaEntry->Type].push_back(criteria);
+ }
+
+ if (criteriaEntry->StartTimer)
+ _criteriasByTimedType[criteriaEntry->StartEvent].push_back(criteria);
+ }
+
+ for (auto& p : _criteriaTrees)
+ const_cast<CriteriaTree*>(p.second)->Criteria = GetCriteria(p.second->Entry->CriteriaID);
+
+ TC_LOG_INFO("server.loading", ">> Loaded %u criteria, %u guild criteria and %u scenario criteria in %u ms.", criterias, guildCriterias, scenarioCriterias, GetMSTimeDiffToNow(oldMSTime));
+}
+
+void CriteriaMgr::LoadCriteriaData()
+{
+ uint32 oldMSTime = getMSTime();
+
+ _criteriaDataMap.clear(); // need for reload case
+
+ QueryResult result = WorldDatabase.Query("SELECT criteria_id, type, value1, value2, ScriptName FROM criteria_data");
+
+ if (!result)
+ {
+ TC_LOG_INFO("server.loading", ">> Loaded 0 additional criteria data. DB table `criteria_data` is empty.");
+ return;
+ }
+
+ uint32 count = 0;
+
+ do
+ {
+ Field* fields = result->Fetch();
+ uint32 criteria_id = fields[0].GetUInt32();
+
+ Criteria const* criteria = GetCriteria(criteria_id);
+
+ if (!criteria)
+ {
+ TC_LOG_ERROR("sql.sql", "Table `criteria_data` contains data for non-existing criteria (Entry: %u). Ignored.", criteria_id);
+ continue;
+ }
+
+ uint32 dataType = fields[1].GetUInt8();
+ std::string scriptName = fields[4].GetString();
+ uint32 scriptId = 0;
+ if (!scriptName.empty())
+ {
+ if (dataType != CRITERIA_DATA_TYPE_SCRIPT)
+ TC_LOG_ERROR("sql.sql", "Table `criteria_data` contains a ScriptName for non-scripted data type (Entry: %u, type %u), useless data.", criteria_id, dataType);
+ else
+ scriptId = sObjectMgr->GetScriptId(scriptName);
+ }
+
+ CriteriaData data(dataType, fields[2].GetUInt32(), fields[3].GetUInt32(), scriptId);
+
+ if (!data.IsValid(criteria))
+ continue;
+
+ // this will allocate empty data set storage
+ CriteriaDataSet& dataSet = _criteriaDataMap[criteria_id];
+ dataSet.SetCriteriaId(criteria_id);
+
+ // add real data only for not NONE data types
+ if (data.DataType != CRITERIA_DATA_TYPE_NONE)
+ dataSet.Add(data);
+
+ // counting data by and data types
+ ++count;
+ }
+ while (result->NextRow());
+
+ TC_LOG_INFO("server.loading", ">> Loaded %u additional criteria data in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
+}
+
+CriteriaTree const* CriteriaMgr::GetCriteriaTree(uint32 criteriaTreeId) const
+{
+ auto itr = _criteriaTrees.find(criteriaTreeId);
+ if (itr == _criteriaTrees.end())
+ return nullptr;
+
+ return itr->second;
+}
+
+Criteria const* CriteriaMgr::GetCriteria(uint32 criteriaId) const
+{
+ auto itr = _criteria.find(criteriaId);
+ if (itr == _criteria.end())
+ return nullptr;
+
+ return itr->second;
+}
diff --git a/src/server/game/Achievements/CriteriaHandler.h b/src/server/game/Achievements/CriteriaHandler.h
new file mode 100644
index 00000000000..0a12f5f6908
--- /dev/null
+++ b/src/server/game/Achievements/CriteriaHandler.h
@@ -0,0 +1,393 @@
+/*
+ * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/>
+ *
+ * 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 CriteriaHandler_h__
+#define CriteriaHandler_h__
+
+#include "DBCEnums.h"
+#include "ObjectGuid.h"
+#include "Transaction.h"
+#include "Common.h"
+
+class Player;
+class Unit;
+class WorldPacket;
+struct AchievementEntry;
+struct CriteriaEntry;
+struct CriteriaTreeEntry;
+struct ModifierTreeEntry;
+struct ScenarioStepEntry;
+
+struct ModifierTreeNode
+{
+ ModifierTreeEntry const* Entry;
+ std::vector<ModifierTreeNode const*> Children;
+};
+
+enum CriteriaFlagsCu
+{
+ CRITERIA_FLAG_CU_PLAYER = 0x1,
+ CRITERIA_FLAG_CU_ACCOUNT = 0x2,
+ CRITERIA_FLAG_CU_GUILD = 0x4,
+ CRITERIA_FLAG_CU_SCENARIO = 0x8
+};
+
+struct Criteria
+{
+ uint32 ID = 0;
+ CriteriaEntry const* Entry = nullptr;
+ ModifierTreeNode const* Modifier = nullptr;
+ uint32 FlagsCu = 0;
+};
+
+typedef std::vector<Criteria const*> CriteriaList;
+
+struct CriteriaTree
+{
+ uint32 ID = 0;
+ CriteriaTreeEntry const* Entry = nullptr;
+ AchievementEntry const* Achievement = nullptr;
+ ScenarioStepEntry const* ScenarioStep = nullptr;
+ Criteria const* Criteria = nullptr;
+ std::vector<CriteriaTree const*> Children;
+};
+
+typedef std::vector<CriteriaTree const*> CriteriaTreeList;
+
+struct CriteriaProgress
+{
+ uint64 Counter = 0;
+ std::time_t Date = std::time_t(0); // latest update time.
+ ObjectGuid PlayerGUID; // GUID of the player that last updated the criteria
+ bool Changed = false;
+};
+
+enum CriteriaDataType
+{ // value1 value2 comment
+ CRITERIA_DATA_TYPE_NONE = 0, // 0 0
+ CRITERIA_DATA_TYPE_T_CREATURE = 1, // CreatureId 0
+ CRITERIA_DATA_TYPE_T_PLAYER_CLASS_RACE = 2, // ClassId RaceId
+ CRITERIA_DATA_TYPE_T_PLAYER_LESS_HEALTH = 3, // HealthPercent 0
+ CRITERIA_DATA_TYPE_S_AURA = 5, // SpellId EffectIndex
+ CRITERIA_DATA_TYPE_T_AURA = 7, // SpellId EffectIndex
+ CRITERIA_DATA_TYPE_VALUE = 8, // Minvalue value provided with update must be not less that limit
+ CRITERIA_DATA_TYPE_T_LEVEL = 9, // Minlevel minlevel of target
+ CRITERIA_DATA_TYPE_T_GENDER = 10, // Gender 0=male; 1=female
+ CRITERIA_DATA_TYPE_SCRIPT = 11, // Scripted requirement
+ // REUSE
+ CRITERIA_DATA_TYPE_MAP_PLAYER_COUNT = 13, // Count "with less than %u people in the zone"
+ CRITERIA_DATA_TYPE_T_TEAM = 14, // Team HORDE(67), ALLIANCE(469)
+ CRITERIA_DATA_TYPE_S_DRUNK = 15, // DrunkenState 0 (enum DrunkenState) of player
+ CRITERIA_DATA_TYPE_HOLIDAY = 16, // HolidayId 0 event in holiday time
+ CRITERIA_DATA_TYPE_BG_LOSS_TEAM_SCORE = 17, // MinScore MaxScore player's team win bg and opposition team have team score in range
+ CRITERIA_DATA_TYPE_INSTANCE_SCRIPT = 18, // 0 0 maker instance script call for check current criteria requirements fit
+ CRITERIA_DATA_TYPE_S_EQUIPED_ITEM = 19, // ItemLevel Quality for equipped item in slot to check item level and quality
+ CRITERIA_DATA_TYPE_MAP_ID = 20, // MapId 0 player must be on map with id in map_id
+ CRITERIA_DATA_TYPE_S_PLAYER_CLASS_RACE = 21, // Class Race
+ // REUSE
+ CRITERIA_DATA_TYPE_S_KNOWN_TITLE = 23, // TitleId known (pvp) title, values from dbc
+ CRITERIA_DATA_TYPE_GAME_EVENT = 24, // GameEventId 0
+
+ MAX_CRITERIA_DATA_TYPE
+};
+
+struct CriteriaData
+{
+ CriteriaDataType DataType;
+ union
+ {
+ // CRITERIA_DATA_TYPE_NONE = 0 (no data)
+ // CRITERIA_DATA_TYPE_T_CREATURE = 1
+ struct
+ {
+ uint32 Id;
+ } Creature;
+ // CRITERIA_DATA_TYPE_T_PLAYER_CLASS_RACE = 2
+ // CRITERIA_DATA_TYPE_S_PLAYER_CLASS_RACE = 21
+ struct
+ {
+ uint32 Class;
+ uint32 Race;
+ } ClassRace;
+ // CRITERIA_DATA_TYPE_T_PLAYER_LESS_HEALTH = 3
+ struct
+ {
+ uint32 Percent;
+ } Health;
+ // CRITERIA_DATA_TYPE_S_AURA = 5
+ // CRITERIA_DATA_TYPE_T_AURA = 7
+ struct
+ {
+ uint32 SpellId;
+ uint32 EffectIndex;
+ } Aura;
+ // CRITERIA_DATA_TYPE_VALUE = 8
+ struct
+ {
+ uint32 Value;
+ uint32 ComparisonType;
+ } Value;
+ // CRITERIA_DATA_TYPE_T_LEVEL = 9
+ struct
+ {
+ uint32 Min;
+ } Level;
+ // CRITERIA_DATA_TYPE_T_GENDER = 10
+ struct
+ {
+ uint32 Gender;
+ } Gender;
+ // CRITERIA_DATA_TYPE_SCRIPT = 11 (no data)
+ // CRITERIA_DATA_TYPE_MAP_PLAYER_COUNT = 13
+ struct
+ {
+ uint32 MaxCount;
+ } MapPlayers;
+ // CRITERIA_DATA_TYPE_T_TEAM = 14
+ struct
+ {
+ uint32 Team;
+ } Team;
+ // CRITERIA_DATA_TYPE_S_DRUNK = 15
+ struct
+ {
+ uint32 State;
+ } Drunk;
+ // CRITERIA_DATA_TYPE_HOLIDAY = 16
+ struct
+ {
+ uint32 Id;
+ } Holiday;
+ // CRITERIA_DATA_TYPE_BG_LOSS_TEAM_SCORE= 17
+ struct
+ {
+ uint32 Min;
+ uint32 Max;
+ } BattlegroundScore;
+ // CRITERIA_DATA_TYPE_INSTANCE_SCRIPT = 18 (no data)
+ // CRITERIA_DATA_TYPE_S_EQUIPED_ITEM = 19
+ struct
+ {
+ uint32 ItemLevel;
+ uint32 Quality;
+ } EquippedItem;
+ // CRITERIA_DATA_TYPE_MAP_ID = 20
+ struct
+ {
+ uint32 Id;
+ } Map;
+ // CRITERIA_DATA_TYPE_KNOWN_TITLE = 22
+ struct
+ {
+ uint32 Id;
+ } KnownTitle;
+ // CRITERIA_DATA_TYPE_GAME_EVENT = 24
+ struct
+ {
+ uint32 Id;
+ } GameEvent;
+ // raw
+ struct
+ {
+ uint32 Value1;
+ uint32 Value2;
+ } Raw;
+ };
+ uint32 ScriptId;
+
+ CriteriaData() : DataType(CRITERIA_DATA_TYPE_NONE)
+ {
+ Raw.Value1 = 0;
+ Raw.Value2 = 0;
+ ScriptId = 0;
+ }
+
+ CriteriaData(uint32 _dataType, uint32 _value1, uint32 _value2, uint32 _scriptId) : DataType(CriteriaDataType(_dataType))
+ {
+ Raw.Value1 = _value1;
+ Raw.Value2 = _value2;
+ ScriptId = _scriptId;
+ }
+
+ bool IsValid(Criteria const* criteria);
+ bool Meets(uint32 criteriaId, Player const* source, Unit const* target, uint32 miscValue1 = 0) const;
+};
+
+struct CriteriaDataSet
+{
+ CriteriaDataSet() : _criteriaId(0) { }
+ void Add(CriteriaData const& data) { _storage.push_back(data); }
+ bool Meets(Player const* source, Unit const* target, uint32 miscValue = 0) const;
+ void SetCriteriaId(uint32 id) { _criteriaId = id; }
+private:
+ uint32 _criteriaId;
+ std::vector<CriteriaData> _storage;
+};
+
+typedef std::map<uint32, CriteriaDataSet> CriteriaDataMap;
+typedef std::unordered_map<uint32, CriteriaProgress> CriteriaProgressMap;
+
+enum ProgressType
+{
+ PROGRESS_SET,
+ PROGRESS_ACCUMULATE,
+ PROGRESS_HIGHEST
+};
+
+class TC_GAME_API CriteriaHandler
+{
+public:
+ CriteriaHandler();
+ virtual ~CriteriaHandler();
+
+ virtual void Reset();
+
+ void UpdateCriteria(CriteriaTypes type, uint64 miscValue1 = 0, uint64 miscValue2 = 0, uint64 miscValue3 = 0, Unit const* unit = nullptr, Player* referencePlayer = nullptr);
+
+ virtual void SendAllData(Player const* receiver) const = 0;
+
+ void UpdateTimedCriteria(uint32 timeDiff);
+ void StartCriteriaTimer(CriteriaTimedTypes type, uint32 entry, uint32 timeLost = 0);
+ void RemoveCriteriaTimer(CriteriaTimedTypes type, uint32 entry); // used for quest and scripted timed s
+
+protected:
+ virtual void SendCriteriaUpdate(Criteria const* criteria, CriteriaProgress const* progress, uint32 timeElapsed, bool timedCompleted) const = 0;
+
+ CriteriaProgress* GetCriteriaProgress(Criteria const* entry);
+ void SetCriteriaProgress(Criteria const* criteria, uint64 changeValue, Player* referencePlayer, ProgressType progressType = PROGRESS_SET);
+ void RemoveCriteriaProgress(Criteria const* criteria);
+ virtual void SendCriteriaProgressRemoved(uint32 criteriaId) = 0;
+
+ bool IsCompletedCriteriaTree(CriteriaTree const* tree);
+ virtual bool CanUpdateCriteriaTree(Criteria const* criteria, CriteriaTree const* tree, Player* referencePlayer) const = 0;
+ virtual bool CanCompleteCriteriaTree(CriteriaTree const* tree);
+ virtual void CompletedCriteriaTree(CriteriaTree const* tree, Player* referencePlayer) = 0;
+ virtual void AfterCriteriaTreeUpdate(CriteriaTree const* /*tree*/, Player* /*referencePlayer*/) { }
+
+ bool IsCompletedCriteria(Criteria const* criteria, uint64 requiredAmount);
+ bool CanUpdateCriteria(Criteria const* criteria, CriteriaTreeList const* trees, uint64 miscValue1, uint64 miscValue2, uint64 miscValue3, Unit const* unit, Player* referencePlayer);
+
+ virtual void SendPacket(WorldPacket const* data) const = 0;
+
+ bool ConditionsSatisfied(Criteria const* criteria, Player* referencePlayer) const;
+ bool RequirementsSatisfied(Criteria const* criteria, uint64 miscValue1, uint64 miscValue2, uint64 miscValue3, Unit const* unit, Player* referencePlayer) const;
+ virtual bool RequiredAchievementSatisfied(uint32 /*achievementId*/) const { return false; }
+ bool AdditionalRequirementsSatisfied(ModifierTreeNode const* parent, uint64 miscValue1, uint64 miscValue2, Unit const* unit, Player* referencePlayer) const;
+
+ virtual std::string GetOwnerInfo() const = 0;
+ virtual CriteriaList const& GetCriteriaByType(CriteriaTypes type) const = 0;
+
+ CriteriaProgressMap _criteriaProgress;
+ std::map<uint32, uint32 /*ms time left*/> _timeCriteriaTrees;
+};
+
+class TC_GAME_API CriteriaMgr
+{
+ CriteriaMgr() { }
+ ~CriteriaMgr();
+
+public:
+ static char const* GetCriteriaTypeString(CriteriaTypes type);
+ static char const* GetCriteriaTypeString(uint32 type);
+
+ static CriteriaMgr* Instance();
+
+ CriteriaList const& GetPlayerCriteriaByType(CriteriaTypes type) const
+ {
+ return _criteriasByType[type];
+ }
+
+ CriteriaList const& GetGuildCriteriaByType(CriteriaTypes type) const
+ {
+ return _guildCriteriasByType[type];
+ }
+
+ CriteriaList const& GetScenarioCriteriaByType(CriteriaTypes type) const
+ {
+ return _scenarioCriteriasByType[type];
+ }
+
+ CriteriaTreeList const* GetCriteriaTreesByCriteria(uint32 criteriaId) const
+ {
+ auto itr = _criteriaTreeByCriteria.find(criteriaId);
+ return itr != _criteriaTreeByCriteria.end() ? &itr->second : nullptr;
+ }
+
+ CriteriaList const& GetTimedCriteriaByType(CriteriaTimedTypes type) const
+ {
+ return _criteriasByTimedType[type];
+ }
+
+ CriteriaDataSet const* GetCriteriaDataSet(Criteria const* Criteria) const
+ {
+ CriteriaDataMap::const_iterator iter = _criteriaDataMap.find(Criteria->ID);
+ return iter != _criteriaDataMap.end() ? &iter->second : NULL;
+ }
+
+ static bool IsGroupCriteriaType(CriteriaTypes type)
+ {
+ switch (type)
+ {
+ case CRITERIA_TYPE_KILL_CREATURE:
+ case CRITERIA_TYPE_WIN_BG:
+ case CRITERIA_TYPE_BE_SPELL_TARGET: // NYI
+ case CRITERIA_TYPE_WIN_RATED_ARENA:
+ case CRITERIA_TYPE_BE_SPELL_TARGET2: // NYI
+ case CRITERIA_TYPE_WIN_RATED_BATTLEGROUND: // NYI
+ return true;
+ default:
+ break;
+ }
+
+ return false;
+ }
+
+ template<typename Func>
+ static void WalkCriteriaTree(CriteriaTree const* tree, Func const& func)
+ {
+ for (CriteriaTree const* node : tree->Children)
+ WalkCriteriaTree(node, func);
+
+ func(tree);
+ }
+
+ void LoadCriteriaModifiersTree();
+ void LoadCriteriaList();
+ void LoadCriteriaData();
+ CriteriaTree const* GetCriteriaTree(uint32 criteriaTreeId) const;
+ Criteria const* GetCriteria(uint32 criteriaId) const;
+
+private:
+ CriteriaDataMap _criteriaDataMap;
+
+ std::unordered_map<uint32, CriteriaTree*> _criteriaTrees;
+ std::unordered_map<uint32, Criteria*> _criteria;
+ std::unordered_map<uint32, ModifierTreeNode*> _criteriaModifiers;
+
+ std::unordered_map<uint32, CriteriaTreeList> _criteriaTreeByCriteria;
+
+ // store criterias by type to speed up lookup
+ CriteriaList _criteriasByType[CRITERIA_TYPE_TOTAL];
+ CriteriaList _guildCriteriasByType[CRITERIA_TYPE_TOTAL];
+ CriteriaList _scenarioCriteriasByType[CRITERIA_TYPE_TOTAL];
+
+ CriteriaList _criteriasByTimedType[CRITERIA_TIMED_TYPE_MAX];
+};
+
+#define sCriteriaMgr CriteriaMgr::Instance()
+
+#endif // CriteriaHandler_h__
diff --git a/src/server/game/AuctionHouse/AuctionHouseMgr.cpp b/src/server/game/AuctionHouse/AuctionHouseMgr.cpp
index 1ea1099cd96..b937f2194e2 100644
--- a/src/server/game/AuctionHouse/AuctionHouseMgr.cpp
+++ b/src/server/game/AuctionHouse/AuctionHouseMgr.cpp
@@ -157,7 +157,7 @@ void AuctionHouseMgr::SendAuctionWonMail(AuctionEntry* auction, SQLTransaction&
{
bidder->GetSession()->SendAuctionWonNotification(auction, item);
// FIXME: for offline player need also
- bidder->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WON_AUCTIONS, 1);
+ bidder->UpdateCriteria(CRITERIA_TYPE_WON_AUCTIONS, 1);
}
MailDraft(auction->BuildAuctionMailSubject(AUCTION_WON), AuctionEntry::BuildAuctionMailBody(auction->owner, auction->bid, auction->buyout, 0, 0))
@@ -198,8 +198,8 @@ void AuctionHouseMgr::SendAuctionSuccessfulMail(AuctionEntry* auction, SQLTransa
//FIXME: what do if owner offline
if (owner && item)
{
- owner->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GOLD_EARNED_BY_AUCTIONS, profit);
- owner->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_SOLD, auction->bid);
+ owner->UpdateCriteria(CRITERIA_TYPE_GOLD_EARNED_BY_AUCTIONS, profit);
+ owner->UpdateCriteria(CRITERIA_TYPE_HIGHEST_AUCTION_SOLD, auction->bid);
//send auction owner notification, bidder must be current!
owner->GetSession()->SendAuctionClosedNotification(auction, (float)sWorld->getIntConfig(CONFIG_MAIL_DELIVERY_DELAY), true, item);
}
diff --git a/src/server/game/BattlePets/BattlePetMgr.cpp b/src/server/game/BattlePets/BattlePetMgr.cpp
index 1ee8e8f9a3a..52adbd4d976 100644
--- a/src/server/game/BattlePets/BattlePetMgr.cpp
+++ b/src/server/game/BattlePets/BattlePetMgr.cpp
@@ -333,7 +333,7 @@ void BattlePetMgr::AddPet(uint32 species, uint32 creatureId, uint16 breed, uint8
updates.push_back(pet);
SendUpdates(updates, true);
- _owner->GetPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_OWN_BATTLE_PET, species);
+ _owner->GetPlayer()->UpdateCriteria(CRITERIA_TYPE_OWN_BATTLE_PET, species);
}
void BattlePetMgr::RemovePet(ObjectGuid guid)
diff --git a/src/server/game/Battlefield/Zones/BattlefieldWG.cpp b/src/server/game/Battlefield/Zones/BattlefieldWG.cpp
index 48db5704f8e..4cb37624cf6 100644
--- a/src/server/game/Battlefield/Zones/BattlefieldWG.cpp
+++ b/src/server/game/Battlefield/Zones/BattlefieldWG.cpp
@@ -414,7 +414,7 @@ void BattlefieldWG::OnBattleEnd(bool endByTimer)
// *******************************************************
void BattlefieldWG::DoCompleteOrIncrementAchievement(uint32 achievement, Player* player, uint8 /*incrementNumber*/)
{
- AchievementEntry const* achievementEntry = sAchievementMgr->GetAchievement(achievement);
+ AchievementEntry const* achievementEntry = sAchievementStore.LookupEntry(achievement);
if (!achievementEntry)
return;
@@ -423,7 +423,7 @@ void BattlefieldWG::DoCompleteOrIncrementAchievement(uint32 achievement, Player*
{
case ACHIEVEMENTS_WIN_WG_100:
{
- // player->UpdateAchievementCriteria();
+ // player->UpdateCriteria();
}
default:
{
diff --git a/src/server/game/Battlegrounds/Arena.cpp b/src/server/game/Battlegrounds/Arena.cpp
index 33b765b1930..8e101e71923 100644
--- a/src/server/game/Battlegrounds/Arena.cpp
+++ b/src/server/game/Battlegrounds/Arena.cpp
@@ -222,8 +222,8 @@ void Arena::EndBattleground(uint32 winner)
{
// update achievement BEFORE personal rating update
uint32 rating = player->GetArenaPersonalRating(winnerArenaTeam->GetSlot());
- player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA, rating ? rating : 1);
- player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WIN_ARENA, GetMapId());
+ player->UpdateCriteria(CRITERIA_TYPE_WIN_RATED_ARENA, rating ? rating : 1);
+ player->UpdateCriteria(CRITERIA_TYPE_WIN_ARENA, GetMapId());
player->ModifyCurrency(CURRENCY_TYPE_CONQUEST_META_ARENA, sWorld->getIntConfig(CONFIG_CURRENCY_CONQUEST_POINTS_ARENA_REWARD));
// Last standing - Rated 5v5 arena & be solely alive player
@@ -235,7 +235,7 @@ void Arena::EndBattleground(uint32 winner)
guildAwarded = true;
if (ObjectGuid::LowType guildId = GetBgMap()->GetOwnerGuildId(player->GetBGTeam()))
if (Guild* guild = sGuildMgr->GetGuildById(guildId))
- guild->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA, std::max<uint32>(winnerArenaTeam->GetRating(), 1), 0, 0, NULL, player);
+ guild->UpdateCriteria(CRITERIA_TYPE_WIN_RATED_ARENA, std::max<uint32>(winnerArenaTeam->GetRating(), 1), 0, 0, NULL, player);
}
winnerArenaTeam->MemberWon(player, loserMatchmakerRating, winnerMatchmakerChange);
@@ -245,7 +245,7 @@ void Arena::EndBattleground(uint32 winner)
loserArenaTeam->MemberLost(player, winnerMatchmakerRating, loserMatchmakerChange);
// Arena lost => reset the win_rated_arena having the "no_lose" condition
- player->ResetAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA, ACHIEVEMENT_CRITERIA_CONDITION_NO_LOSE);
+ player->ResetCriteria(CRITERIA_TYPE_WIN_RATED_ARENA, CRITERIA_CONDITION_NO_LOSE);
}
}
diff --git a/src/server/game/Battlegrounds/ArenaTeam.cpp b/src/server/game/Battlegrounds/ArenaTeam.cpp
index 8e7c4fd0258..23eb6843fb3 100644
--- a/src/server/game/Battlegrounds/ArenaTeam.cpp
+++ b/src/server/game/Battlegrounds/ArenaTeam.cpp
@@ -436,7 +436,7 @@ void ArenaTeamMember::ModifyPersonalRating(Player* player, int32 mod, uint32 typ
if (player)
{
player->SetArenaTeamInfoField(ArenaTeam::GetSlotByType(type), ARENA_TEAM_PERSONAL_RATING, PersonalRating);
- player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_PERSONAL_RATING, PersonalRating, type);
+ player->UpdateCriteria(CRITERIA_TYPE_HIGHEST_PERSONAL_RATING, PersonalRating, type);
}
}
@@ -597,7 +597,7 @@ void ArenaTeam::FinishGame(int32 mod)
// Check if rating related achivements are met
for (MemberList::iterator itr = Members.begin(); itr != Members.end(); ++itr)
if (Player* member = ObjectAccessor::FindConnectedPlayer(itr->Guid))
- member->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_TEAM_RATING, Stats.Rating, Type);
+ member->UpdateCriteria(CRITERIA_TYPE_HIGHEST_TEAM_RATING, Stats.Rating, Type);
}
// Update number of games played per season or week
diff --git a/src/server/game/Battlegrounds/Battleground.cpp b/src/server/game/Battlegrounds/Battleground.cpp
index 5347915fb39..0051f0698d9 100644
--- a/src/server/game/Battlegrounds/Battleground.cpp
+++ b/src/server/game/Battlegrounds/Battleground.cpp
@@ -869,14 +869,14 @@ void Battleground::EndBattleground(uint32 winner)
else // 50cp awarded for each non-rated battleground won
player->ModifyCurrency(CURRENCY_TYPE_CONQUEST_META_ARENA, sWorld->getIntConfig(CONFIG_BG_REWARD_WINNER_CONQUEST_LAST));
- player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WIN_BG, 1);
+ player->UpdateCriteria(CRITERIA_TYPE_WIN_BG, 1);
if (!guildAwarded)
{
guildAwarded = true;
if (ObjectGuid::LowType guildId = GetBgMap()->GetOwnerGuildId(player->GetBGTeam()))
{
if (Guild* guild = sGuildMgr->GetGuildById(guildId))
- guild->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WIN_BG, 1, 0, 0, NULL, player);
+ guild->UpdateCriteria(CRITERIA_TYPE_WIN_BG, 1, 0, 0, NULL, player);
}
}
}
@@ -897,7 +897,7 @@ void Battleground::EndBattleground(uint32 winner)
sBattlegroundMgr->BuildBattlegroundStatusActive(&battlefieldStatus, this, player, player->GetBattlegroundQueueIndex(bgQueueTypeId), player->GetBattlegroundQueueJoinTime(bgQueueTypeId), GetArenaType());
player->SendDirectMessage(battlefieldStatus.Write());
- player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND, 1);
+ player->UpdateCriteria(CRITERIA_TYPE_COMPLETE_BATTLEGROUND, 1);
}
if (winmsg_id)
@@ -1138,17 +1138,17 @@ void Battleground::AddPlayer(Player* player)
}
}
- player->ResetAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE, ACHIEVEMENT_CRITERIA_CONDITION_BG_MAP, GetMapId(), true);
- player->ResetAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WIN_BG, ACHIEVEMENT_CRITERIA_CONDITION_BG_MAP, GetMapId(), true);
- player->ResetAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DAMAGE_DONE, ACHIEVEMENT_CRITERIA_CONDITION_BG_MAP, GetMapId(), true);
- player->ResetAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, ACHIEVEMENT_CRITERIA_CONDITION_BG_MAP, GetMapId(), true);
- player->ResetAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL, ACHIEVEMENT_CRITERIA_CONDITION_BG_MAP, GetMapId(), true);
- player->ResetAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, ACHIEVEMENT_CRITERIA_CONDITION_BG_MAP, GetMapId(), true);
- player->ResetAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL_AT_AREA, ACHIEVEMENT_CRITERIA_CONDITION_BG_MAP, GetMapId(), true);
- player->ResetAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL, ACHIEVEMENT_CRITERIA_CONDITION_BG_MAP, GetMapId(), true);
- player->ResetAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE, ACHIEVEMENT_CRITERIA_CONDITION_BG_MAP, GetMapId(), true);
- player->ResetAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS, ACHIEVEMENT_CRITERIA_CONDITION_BG_MAP, GetMapId(), true);
- player->ResetAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL, ACHIEVEMENT_CRITERIA_CONDITION_BG_MAP, GetMapId(), true);
+ player->ResetCriteria(CRITERIA_TYPE_KILL_CREATURE, CRITERIA_CONDITION_BG_MAP, GetMapId(), true);
+ player->ResetCriteria(CRITERIA_TYPE_WIN_BG, CRITERIA_CONDITION_BG_MAP, GetMapId(), true);
+ player->ResetCriteria(CRITERIA_TYPE_DAMAGE_DONE, CRITERIA_CONDITION_BG_MAP, GetMapId(), true);
+ player->ResetCriteria(CRITERIA_TYPE_BE_SPELL_TARGET, CRITERIA_CONDITION_BG_MAP, GetMapId(), true);
+ player->ResetCriteria(CRITERIA_TYPE_CAST_SPELL, CRITERIA_CONDITION_BG_MAP, GetMapId(), true);
+ player->ResetCriteria(CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, CRITERIA_CONDITION_BG_MAP, GetMapId(), true);
+ player->ResetCriteria(CRITERIA_TYPE_HONORABLE_KILL_AT_AREA, CRITERIA_CONDITION_BG_MAP, GetMapId(), true);
+ player->ResetCriteria(CRITERIA_TYPE_HONORABLE_KILL, CRITERIA_CONDITION_BG_MAP, GetMapId(), true);
+ player->ResetCriteria(CRITERIA_TYPE_HEALING_DONE, CRITERIA_CONDITION_BG_MAP, GetMapId(), true);
+ player->ResetCriteria(CRITERIA_TYPE_GET_KILLING_BLOWS, CRITERIA_CONDITION_BG_MAP, GetMapId(), true);
+ player->ResetCriteria(CRITERIA_TYPE_SPECIAL_PVP_KILL, CRITERIA_CONDITION_BG_MAP, GetMapId(), true);
// setup BG group membership
PlayerAddedToBGCheckIfBGIsRunning(player);
@@ -1902,11 +1902,11 @@ WorldSafeLocsEntry const* Battleground::GetClosestGraveYard(Player* player)
return sObjectMgr->GetClosestGraveYard(player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), player->GetMapId(), player->GetTeam());
}
-void Battleground::StartTimedAchievement(AchievementCriteriaTimedTypes type, uint32 entry)
+void Battleground::StartCriteriaTimer(CriteriaTimedTypes type, uint32 entry)
{
for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
if (Player* player = ObjectAccessor::FindPlayer(itr->first))
- player->StartTimedAchievement(type, entry);
+ player->StartCriteriaTimer(type, entry);
}
void Battleground::SetBracket(PvPDifficultyEntry const* bracketEntry)
diff --git a/src/server/game/Battlegrounds/Battleground.h b/src/server/game/Battlegrounds/Battleground.h
index cb2fb68d9dd..2ef7eca4aa1 100644
--- a/src/server/game/Battlegrounds/Battleground.h
+++ b/src/server/game/Battlegrounds/Battleground.h
@@ -253,7 +253,7 @@ class TC_GAME_API Battleground
/* achievement req. */
virtual bool IsAllNodesControlledByTeam(uint32 /*team*/) const { return false; }
- void StartTimedAchievement(AchievementCriteriaTimedTypes type, uint32 entry);
+ void StartCriteriaTimer(CriteriaTimedTypes type, uint32 entry);
virtual bool CheckAchievementCriteriaMeet(uint32 /*criteriaId*/, Player const* /*player*/, Unit const* /*target*/ = NULL, uint32 /*miscvalue1*/ = 0);
/* Battleground */
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp
index d3083da8734..911fe259fc3 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp
@@ -216,7 +216,7 @@ void BattlegroundAB::StartingEventOpenDoors()
DoorOpen(BG_AB_OBJECT_GATE_H);
// Achievement: Let's Get This Done
- StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, AB_EVENT_START_BATTLE);
+ StartCriteriaTimer(CRITERIA_TIMED_TYPE_EVENT, AB_EVENT_START_BATTLE);
}
void BattlegroundAB::AddPlayer(Player* player)
@@ -698,10 +698,10 @@ bool BattlegroundAB::UpdatePlayerScore(Player* player, uint32 type, uint32 value
switch (type)
{
case SCORE_BASES_ASSAULTED:
- player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, AB_OBJECTIVE_ASSAULT_BASE);
+ player->UpdateCriteria(CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, AB_OBJECTIVE_ASSAULT_BASE);
break;
case SCORE_BASES_DEFENDED:
- player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, AB_OBJECTIVE_DEFEND_BASE);
+ player->UpdateCriteria(CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, AB_OBJECTIVE_DEFEND_BASE);
break;
default:
break;
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp
index 80dfd1e4aeb..59d01df8237 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp
@@ -429,7 +429,7 @@ void BattlegroundAV::StartingEventOpenDoors()
DoorOpen(BG_AV_OBJECT_DOOR_A);
// Achievement: The Alterac Blitz
- StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, BG_AV_EVENT_START_BATTLE);
+ StartCriteriaTimer(CRITERIA_TIMED_TYPE_EVENT, BG_AV_EVENT_START_BATTLE);
}
void BattlegroundAV::AddPlayer(Player* player)
@@ -533,16 +533,16 @@ bool BattlegroundAV::UpdatePlayerScore(Player* player, uint32 type, uint32 value
switch (type)
{
case SCORE_GRAVEYARDS_ASSAULTED:
- player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, AV_OBJECTIVE_ASSAULT_GRAVEYARD);
+ player->UpdateCriteria(CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, AV_OBJECTIVE_ASSAULT_GRAVEYARD);
break;
case SCORE_GRAVEYARDS_DEFENDED:
- player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, AV_OBJECTIVE_DEFEND_GRAVEYARD);
+ player->UpdateCriteria(CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, AV_OBJECTIVE_DEFEND_GRAVEYARD);
break;
case SCORE_TOWERS_ASSAULTED:
- player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, AV_OBJECTIVE_ASSAULT_TOWER);
+ player->UpdateCriteria(CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, AV_OBJECTIVE_ASSAULT_TOWER);
break;
case SCORE_TOWERS_DEFENDED:
- player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, AV_OBJECTIVE_DEFEND_TOWER);
+ player->UpdateCriteria(CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, AV_OBJECTIVE_DEFEND_TOWER);
break;
default:
break;
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp
index d2922ff0164..461420fe962 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp
@@ -153,7 +153,7 @@ void BattlegroundEY::StartingEventOpenDoors()
}
// Achievement: Flurry
- StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, BG_EY_EVENT_START_BATTLE);
+ StartCriteriaTimer(CRITERIA_TIMED_TYPE_EVENT, BG_EY_EVENT_START_BATTLE);
}
void BattlegroundEY::AddPoints(uint32 Team, uint32 Points)
@@ -849,7 +849,7 @@ bool BattlegroundEY::UpdatePlayerScore(Player* player, uint32 type, uint32 value
switch (type)
{
case SCORE_FLAG_CAPTURES:
- player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, EY_OBJECTIVE_CAPTURE_FLAG);
+ player->UpdateCriteria(CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, EY_OBJECTIVE_CAPTURE_FLAG);
break;
default:
break;
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp
index 149d914d128..032b283727c 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp
@@ -343,7 +343,7 @@ void BattlegroundSA::PostUpdateImpl(uint32 diff)
ToggleTimer();
DemolisherStartState(false);
Status = BG_SA_ROUND_ONE;
- StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, (Attackers == TEAM_ALLIANCE) ? 23748 : 21702);
+ StartCriteriaTimer(CRITERIA_TIMED_TYPE_EVENT, (Attackers == TEAM_ALLIANCE) ? 23748 : 21702);
}
if (TotalTime >= BG_SA_BOAT_START)
StartShips();
@@ -365,7 +365,7 @@ void BattlegroundSA::PostUpdateImpl(uint32 diff)
ToggleTimer();
DemolisherStartState(false);
Status = BG_SA_ROUND_TWO;
- StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, (Attackers == TEAM_ALLIANCE) ? 23748 : 21702);
+ StartCriteriaTimer(CRITERIA_TIMED_TYPE_EVENT, (Attackers == TEAM_ALLIANCE) ? 23748 : 21702);
// status was set to STATUS_WAIT_JOIN manually for Preparation, set it back now
SetStatus(STATUS_IN_PROGRESS);
for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
@@ -907,7 +907,7 @@ void BattlegroundSA::TitanRelicActivated(Player* clicker)
{
if (Player* player = ObjectAccessor::FindPlayer(itr->first))
if (player->GetTeamId() == Attackers)
- player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, 65246);
+ player->UpdateCriteria(CRITERIA_TYPE_BE_SPELL_TARGET, 65246);
}
Attackers = (Attackers == TEAM_ALLIANCE) ? TEAM_HORDE : TEAM_ALLIANCE;
@@ -937,7 +937,7 @@ void BattlegroundSA::TitanRelicActivated(Player* clicker)
{
if (Player* player = ObjectAccessor::FindPlayer(itr->first))
if (player->GetTeamId() == Attackers && RoundScores[1].winner == Attackers)
- player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, 65246);
+ player->UpdateCriteria(CRITERIA_TYPE_BE_SPELL_TARGET, 65246);
}
if (RoundScores[0].time == RoundScores[1].time)
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp
index 2c9c43826ce..0df4fd6f88e 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp
@@ -245,7 +245,7 @@ void BattlegroundWS::StartingEventOpenDoors()
SpawnBGObject(BG_WS_OBJECT_DOOR_H_4, RESPAWN_ONE_DAY);
// players joining later are not eligibles
- StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, WS_EVENT_START_BATTLE);
+ StartCriteriaTimer(CRITERIA_TIMED_TYPE_EVENT, WS_EVENT_START_BATTLE);
}
void BattlegroundWS::AddPlayer(Player* player)
@@ -504,7 +504,7 @@ void BattlegroundWS::EventPlayerClickedOnFlag(Player* player, GameObject* target
UpdateFlagState(HORDE, BG_WS_FLAG_STATE_ON_PLAYER);
UpdateWorldState(BG_WS_FLAG_UNK_ALLIANCE, 1);
player->CastSpell(player, BG_WS_SPELL_SILVERWING_FLAG, true);
- player->StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_SPELL_TARGET, BG_WS_SPELL_SILVERWING_FLAG_PICKED);
+ player->StartCriteriaTimer(CRITERIA_TIMED_TYPE_SPELL_TARGET, BG_WS_SPELL_SILVERWING_FLAG_PICKED);
if (_flagState[1] == BG_WS_FLAG_STATE_ON_PLAYER)
_bothFlagsKept = true;
}
@@ -523,7 +523,7 @@ void BattlegroundWS::EventPlayerClickedOnFlag(Player* player, GameObject* target
UpdateFlagState(ALLIANCE, BG_WS_FLAG_STATE_ON_PLAYER);
UpdateWorldState(BG_WS_FLAG_UNK_HORDE, 1);
player->CastSpell(player, BG_WS_SPELL_WARSONG_FLAG, true);
- player->StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_SPELL_TARGET, BG_WS_SPELL_WARSONG_FLAG_PICKED);
+ player->StartCriteriaTimer(CRITERIA_TIMED_TYPE_SPELL_TARGET, BG_WS_SPELL_WARSONG_FLAG_PICKED);
if (_flagState[0] == BG_WS_FLAG_STATE_ON_PLAYER)
_bothFlagsKept = true;
}
@@ -817,10 +817,10 @@ bool BattlegroundWS::UpdatePlayerScore(Player* player, uint32 type, uint32 value
switch (type)
{
case SCORE_FLAG_CAPTURES: // flags captured
- player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, WS_OBJECTIVE_CAPTURE_FLAG);
+ player->UpdateCriteria(CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, WS_OBJECTIVE_CAPTURE_FLAG);
break;
case SCORE_FLAG_RETURNS: // flags returned
- player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, WS_OBJECTIVE_RETURN_FLAG);
+ player->UpdateCriteria(CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, WS_OBJECTIVE_RETURN_FLAG);
break;
default:
break;
diff --git a/src/server/game/Chat/ChatLink.cpp b/src/server/game/Chat/ChatLink.cpp
index 4eeea1b20cb..3e523cad4fb 100644
--- a/src/server/game/Chat/ChatLink.cpp
+++ b/src/server/game/Chat/ChatLink.cpp
@@ -379,7 +379,7 @@ bool AchievementChatLink::Initialize(std::istringstream& iss)
return false;
}
// Validate achievement
- _achievement = sAchievementMgr->GetAchievement(achievementId);
+ _achievement = sAchievementStore.LookupEntry(achievementId);
if (!_achievement)
{
TC_LOG_TRACE("chat.system", "ChatHandler::isValidChatMessage('%s'): got invalid achivement id %u in |achievement command", iss.str().c_str(), achievementId);
diff --git a/src/server/game/Conditions/ConditionMgr.cpp b/src/server/game/Conditions/ConditionMgr.cpp
index 002f4040255..4a0fa1984aa 100644
--- a/src/server/game/Conditions/ConditionMgr.cpp
+++ b/src/server/game/Conditions/ConditionMgr.cpp
@@ -425,8 +425,8 @@ bool Condition::Meets(ConditionSourceInfo& sourceInfo) const
}
case CONDITION_REALM_ACHIEVEMENT:
{
- AchievementEntry const* achievement = sAchievementMgr->GetAchievement(ConditionValue1);
- if (achievement && sAchievementMgr->IsRealmCompleted(achievement, std::numeric_limits<uint32>::max()))
+ AchievementEntry const* achievement = sAchievementStore.LookupEntry(ConditionValue1);
+ if (achievement && sAchievementMgr->IsRealmCompleted(achievement))
condMeets = true;
break;
}
@@ -1908,7 +1908,7 @@ bool ConditionMgr::isConditionTypeValid(Condition* cond) const
}
case CONDITION_ACHIEVEMENT:
{
- AchievementEntry const* achievement = sAchievementMgr->GetAchievement(cond->ConditionValue1);
+ AchievementEntry const* achievement = sAchievementStore.LookupEntry(cond->ConditionValue1);
if (!achievement)
{
TC_LOG_ERROR("sql.sql", "%s has non existing achivement id (%u), skipped.", cond->ToString(true).c_str(), cond->ConditionValue1);
@@ -2211,7 +2211,7 @@ bool ConditionMgr::isConditionTypeValid(Condition* cond) const
break;
case CONDITION_REALM_ACHIEVEMENT:
{
- AchievementEntry const* achievement = sAchievementMgr->GetAchievement(cond->ConditionValue1);
+ AchievementEntry const* achievement = sAchievementStore.LookupEntry(cond->ConditionValue1);
if (!achievement)
{
TC_LOG_ERROR("sql.sql", "%s has non existing realm first achivement id (%u), skipped.", cond->ToString(true).c_str(), cond->ConditionValue1);
diff --git a/src/server/game/Conditions/DisableMgr.cpp b/src/server/game/Conditions/DisableMgr.cpp
index cf5b672384b..62d5ecfa88a 100644
--- a/src/server/game/Conditions/DisableMgr.cpp
+++ b/src/server/game/Conditions/DisableMgr.cpp
@@ -17,7 +17,7 @@
*/
#include "DisableMgr.h"
-#include "AchievementMgr.h"
+#include "CriteriaHandler.h"
#include "ObjectMgr.h"
#include "OutdoorPvP.h"
#include "SpellMgr.h"
@@ -183,14 +183,14 @@ void LoadDisables()
if (flags)
TC_LOG_ERROR("sql.sql", "Disable flags specified for outdoor PvP %u, useless data.", entry);
break;
- case DISABLE_TYPE_ACHIEVEMENT_CRITERIA:
- if (!sAchievementMgr->GetAchievementCriteria(entry))
+ case DISABLE_TYPE_CRITERIA:
+ if (!sCriteriaMgr->GetCriteria(entry))
{
- TC_LOG_ERROR("sql.sql", "Achievement Criteria entry %u from `disables` doesn't exist in dbc, skipped.", entry);
+ TC_LOG_ERROR("sql.sql", "Criteria entry %u from `disables` doesn't exist in dbc, skipped.", entry);
continue;
}
if (flags)
- TC_LOG_ERROR("sql.sql", "Disable flags specified for Achievement Criteria %u, useless data.", entry);
+ TC_LOG_ERROR("sql.sql", "Disable flags specified for Criteria %u, useless data.", entry);
break;
case DISABLE_TYPE_VMAP:
{
@@ -362,7 +362,7 @@ bool IsDisabledFor(DisableType type, uint32 entry, Unit const* unit, uint8 flags
return true;
case DISABLE_TYPE_BATTLEGROUND:
case DISABLE_TYPE_OUTDOORPVP:
- case DISABLE_TYPE_ACHIEVEMENT_CRITERIA:
+ case DISABLE_TYPE_CRITERIA:
case DISABLE_TYPE_MMAP:
return true;
case DISABLE_TYPE_VMAP:
diff --git a/src/server/game/Conditions/DisableMgr.h b/src/server/game/Conditions/DisableMgr.h
index cae1e0329e8..95e54932f15 100644
--- a/src/server/game/Conditions/DisableMgr.h
+++ b/src/server/game/Conditions/DisableMgr.h
@@ -30,7 +30,7 @@ enum DisableType
DISABLE_TYPE_QUEST = 1,
DISABLE_TYPE_MAP = 2,
DISABLE_TYPE_BATTLEGROUND = 3,
- DISABLE_TYPE_ACHIEVEMENT_CRITERIA = 4,
+ DISABLE_TYPE_CRITERIA = 4,
DISABLE_TYPE_OUTDOORPVP = 5,
DISABLE_TYPE_VMAP = 6,
DISABLE_TYPE_MMAP = 7
diff --git a/src/server/game/DataStores/DB2Structure.h b/src/server/game/DataStores/DB2Structure.h
index a6774b03684..daebcf7375f 100644
--- a/src/server/game/DataStores/DB2Structure.h
+++ b/src/server/game/DataStores/DB2Structure.h
@@ -188,120 +188,120 @@ struct CriteriaEntry
union
{
uint32 ID;
- // ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE = 0
- // ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE = 20
+ // CRITERIA_TYPE_KILL_CREATURE = 0
+ // CRITERIA_TYPE_KILLED_BY_CREATURE = 20
uint32 CreatureID;
- // ACHIEVEMENT_CRITERIA_TYPE_WIN_BG = 1
- // ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND = 15
- // ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP = 16
- // ACHIEVEMENT_CRITERIA_TYPE_WIN_ARENA = 32
- // ACHIEVEMENT_CRITERIA_TYPE_PLAY_ARENA = 33
+ // CRITERIA_TYPE_WIN_BG = 1
+ // CRITERIA_TYPE_COMPLETE_BATTLEGROUND = 15
+ // CRITERIA_TYPE_DEATH_AT_MAP = 16
+ // CRITERIA_TYPE_WIN_ARENA = 32
+ // CRITERIA_TYPE_PLAY_ARENA = 33
uint32 MapID;
- // ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL = 7
- // ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL = 40
- // ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS = 75
- // ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LINE = 112
+ // CRITERIA_TYPE_REACH_SKILL_LEVEL = 7
+ // CRITERIA_TYPE_LEARN_SKILL_LEVEL = 40
+ // CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS = 75
+ // CRITERIA_TYPE_LEARN_SKILL_LINE = 112
uint32 SkillID;
- // ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT = 8
+ // CRITERIA_TYPE_COMPLETE_ACHIEVEMENT = 8
uint32 AchievementID;
- // ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE = 11
+ // CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE = 11
uint32 ZoneID;
- // ACHIEVEMENT_CRITERIA_TYPE_CURRENCY = 12
+ // CRITERIA_TYPE_CURRENCY = 12
uint32 CurrencyID;
- // ACHIEVEMENT_CRITERIA_TYPE_DEATH_IN_DUNGEON = 18
- // ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_RAID = 19
+ // CRITERIA_TYPE_DEATH_IN_DUNGEON = 18
+ // CRITERIA_TYPE_COMPLETE_RAID = 19
uint32 GroupSize;
- // ACHIEVEMENT_CRITERIA_TYPE_DEATHS_FROM = 26
+ // CRITERIA_TYPE_DEATHS_FROM = 26
uint32 DamageType;
- // ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST = 27
+ // CRITERIA_TYPE_COMPLETE_QUEST = 27
uint32 QuestID;
- // ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET = 28
- // ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2 = 69
- // ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL = 29
- // ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2 = 110
- // ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL = 34
+ // CRITERIA_TYPE_BE_SPELL_TARGET = 28
+ // CRITERIA_TYPE_BE_SPELL_TARGET2 = 69
+ // CRITERIA_TYPE_CAST_SPELL = 29
+ // CRITERIA_TYPE_CAST_SPELL2 = 110
+ // CRITERIA_TYPE_LEARN_SPELL = 34
uint32 SpellID;
- // ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE
+ // CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE
uint32 ObjectiveId;
- // ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL_AT_AREA = 31
- // ACHIEVEMENT_CRITERIA_TYPE_ENTER_AREA = 163
- // ACHIEVEMENT_CRITERIA_TYPE_LEAVE_AREA = 164
+ // CRITERIA_TYPE_HONORABLE_KILL_AT_AREA = 31
+ // CRITERIA_TYPE_ENTER_AREA = 163
+ // CRITERIA_TYPE_LEAVE_AREA = 164
uint32 AreaID;
- // ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM = 36
- // ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM = 41
- // ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM = 42
- // ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM = 57
- // ACHIEVEMENT_CRITERIA_TYPE_OWN_TOY = 185
+ // CRITERIA_TYPE_OWN_ITEM = 36
+ // CRITERIA_TYPE_USE_ITEM = 41
+ // CRITERIA_TYPE_LOOT_ITEM = 42
+ // CRITERIA_TYPE_EQUIP_ITEM = 57
+ // CRITERIA_TYPE_OWN_TOY = 185
uint32 ItemID;
- // ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_TEAM_RATING = 38
- // ACHIEVEMENT_CRITERIA_TYPE_REACH_TEAM_RATING = 39
- // ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_PERSONAL_RATING = 39
+ // CRITERIA_TYPE_HIGHEST_TEAM_RATING = 38
+ // CRITERIA_TYPE_REACH_TEAM_RATING = 39
+ // CRITERIA_TYPE_HIGHEST_PERSONAL_RATING = 39
uint32 TeamType;
- // ACHIEVEMENT_CRITERIA_TYPE_EXPLORE_AREA = 43
+ // CRITERIA_TYPE_EXPLORE_AREA = 43
uint32 WorldMapOverlayID;
- // ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION = 46
+ // CRITERIA_TYPE_GAIN_REPUTATION = 46
uint32 FactionID;
- // ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM = 49
+ // CRITERIA_TYPE_EQUIP_EPIC_ITEM = 49
uint32 ItemSlot;
- // ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT = 50
- // ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT = 51
+ // CRITERIA_TYPE_ROLL_NEED_ON_LOOT = 50
+ // CRITERIA_TYPE_ROLL_GREED_ON_LOOT = 51
uint32 RollValue;
- // ACHIEVEMENT_CRITERIA_TYPE_HK_CLASS = 52
+ // CRITERIA_TYPE_HK_CLASS = 52
uint32 ClassID;
- // ACHIEVEMENT_CRITERIA_TYPE_HK_RACE = 53
+ // CRITERIA_TYPE_HK_RACE = 53
uint32 RaceID;
- // ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE = 54
+ // CRITERIA_TYPE_DO_EMOTE = 54
uint32 EmoteID;
- // ACHIEVEMENT_CRITERIA_TYPE_USE_GAMEOBJECT = 68
- // ACHIEVEMENT_CRITERIA_TYPE_FISH_IN_GAMEOBJECT = 72
+ // CRITERIA_TYPE_USE_GAMEOBJECT = 68
+ // CRITERIA_TYPE_FISH_IN_GAMEOBJECT = 72
uint32 GameObjectID;
- // ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_POWER = 96
+ // CRITERIA_TYPE_HIGHEST_POWER = 96
uint32 PowerType;
- // ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_STAT = 97
+ // CRITERIA_TYPE_HIGHEST_STAT = 97
uint32 StatType;
- // ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_SPELLPOWER = 98
+ // CRITERIA_TYPE_HIGHEST_SPELLPOWER = 98
uint32 SpellSchool;
- // ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE = 109
+ // CRITERIA_TYPE_LOOT_TYPE = 109
uint32 LootType;
- // ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DUNGEON_ENCOUNTER = 165
+ // CRITERIA_TYPE_COMPLETE_DUNGEON_ENCOUNTER = 165
uint32 DungeonEncounterID;
- // ACHIEVEMENT_CRITERIA_TYPE_CONSTRUCT_GARRISON_BUILDING = 169
+ // CRITERIA_TYPE_CONSTRUCT_GARRISON_BUILDING = 169
uint32 GarrBuildingID;
- // ACHIEVEMENT_CRITERIA_TYPE_UPGRADE_GARRISON = 170
+ // CRITERIA_TYPE_UPGRADE_GARRISON = 170
uint32 GarrisonLevel;
- // ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_GARRISON_MISSION = 174
+ // CRITERIA_TYPE_COMPLETE_GARRISON_MISSION = 174
uint32 GarrMissionID;
- // ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_GARRISON_SHIPMENT = 182
+ // CRITERIA_TYPE_COMPLETE_GARRISON_SHIPMENT = 182
uint32 CharShipmentContainerID;
} Asset; // 2
uint32 StartEvent; // 3
diff --git a/src/server/game/DataStores/DBCEnums.h b/src/server/game/DataStores/DBCEnums.h
index 822415d05ab..327c8cac081 100644
--- a/src/server/game/DataStores/DBCEnums.h
+++ b/src/server/game/DataStores/DBCEnums.h
@@ -91,278 +91,16 @@ enum AchievementFlags
ACHIEVEMENT_FLAG_REALM_FIRST_REACH = 0x00000100, //
ACHIEVEMENT_FLAG_REALM_FIRST_KILL = 0x00000200, //
ACHIEVEMENT_FLAG_UNK3 = 0x00000400, // ACHIEVEMENT_FLAG_HIDE_NAME_IN_TIE
- ACHIEVEMENT_FLAG_UNK4 = 0x00000800, // first guild on realm done something
+ ACHIEVEMENT_FLAG_HIDE_INCOMPLETE = 0x00000800, // hide from UI if not completed
ACHIEVEMENT_FLAG_SHOW_IN_GUILD_NEWS = 0x00001000, // Shows in guild news
ACHIEVEMENT_FLAG_SHOW_IN_GUILD_HEADER = 0x00002000, // Shows in guild news header
ACHIEVEMENT_FLAG_GUILD = 0x00004000, //
ACHIEVEMENT_FLAG_SHOW_GUILD_MEMBERS = 0x00008000, //
ACHIEVEMENT_FLAG_SHOW_CRITERIA_MEMBERS = 0x00010000, //
- ACHIEVEMENT_FLAG_ACCOUNT = 0x00020000
-};
-
-enum AchievementCriteriaCondition
-{
- ACHIEVEMENT_CRITERIA_CONDITION_NONE = 0,
- ACHIEVEMENT_CRITERIA_CONDITION_NO_DEATH = 1, // reset progress on death
- ACHIEVEMENT_CRITERIA_CONDITION_UNK2 = 2, // only used in "Complete a daily quest every day for five consecutive days"
- ACHIEVEMENT_CRITERIA_CONDITION_BG_MAP = 3, // requires you to be on specific map, reset at change
- ACHIEVEMENT_CRITERIA_CONDITION_NO_LOSE = 4, // only used in "Win 10 arenas without losing"
- ACHIEVEMENT_CRITERIA_CONDITION_UNK5 = 5, // Have spell?
- ACHIEVEMENT_CRITERIA_CONDITION_UNK8 = 8,
- ACHIEVEMENT_CRITERIA_CONDITION_NO_SPELL_HIT = 9, // requires the player not to be hit by specific spell
- ACHIEVEMENT_CRITERIA_CONDITION_NOT_IN_GROUP = 10, // requires the player not to be in group
- ACHIEVEMENT_CRITERIA_CONDITION_UNK13 = 13 // unk
-};
-
-enum AchievementCriteriaAdditionalCondition
-{
- ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_SOURCE_DRUNK_VALUE = 1, // NYI
- ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_UNK2 = 2,
- ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_ITEM_LEVEL = 3, // NYI
- ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_CREATURE_ENTRY = 4,
- ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_MUST_BE_PLAYER = 5,
- ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_MUST_BE_DEAD = 6,
- ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_MUST_BE_ENEMY = 7,
- ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_SOURCE_HAS_AURA = 8,
- ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_HAS_AURA = 10,
- ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_HAS_AURA_TYPE = 11,
- ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_ITEM_QUALITY_MIN = 14,
- ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_ITEM_QUALITY_EQUALS = 15,
- ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_UNK16 = 16,
- ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_SOURCE_AREA_OR_ZONE = 17,
- ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_AREA_OR_ZONE = 18,
- ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_MAP_DIFFICULTY = 20,
- ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_CREATURE_YIELDS_XP = 21, // NYI
- ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_ARENA_TYPE = 24,
- ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_SOURCE_RACE = 25,
- ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_SOURCE_CLASS = 26,
- ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_RACE = 27,
- ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_CLASS = 28,
- ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_MAX_GROUP_MEMBERS = 29,
- ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_CREATURE_TYPE = 30,
- ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_SOURCE_MAP = 32,
- ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_ITEM_CLASS = 33, // NYI
- ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_ITEM_SUBCLASS = 34, // NYI
- ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_COMPLETE_QUEST_NOT_IN_GROUP = 35, // NYI
- ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_MIN_PERSONAL_RATING = 37, // NYI (when implementing don't forget about ACHIEVEMENT_CRITERIA_CONDITION_NO_LOSE)
- ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TITLE_BIT_INDEX = 38,
- ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_SOURCE_LEVEL = 39,
- ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_LEVEL = 40,
- ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_ZONE = 41,
- ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_HEALTH_PERCENT_BELOW = 46,
- ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_UNK55 = 55,
- ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_MIN_ACHIEVEMENT_POINTS = 56, // NYI
- ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_REQUIRES_LFG_GROUP = 58, // NYI
- ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_UNK60 = 60,
- ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_REQUIRES_GUILD_GROUP = 61, // NYI
- ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_GUILD_REPUTATION = 62, // NYI
- ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_RATED_BATTLEGROUND = 63, // NYI
- ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_PROJECT_RARITY = 65,
- ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_PROJECT_RACE = 66,
- ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_BATTLE_PET_SPECIES = 91,
- ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_GARRISON_FOLLOWER_QUALITY = 145,
- ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_GARRISON_FOLLOWER_LEVEL = 146,
- ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_GARRISON_RARE_MISSION = 147, // NYI
- ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_GARRISON_BUILDING_LEVEL = 149, // NYI
- ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_GARRISON_MISSION_TYPE = 167, // NYI
- ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_GARRISON_FOLLOWER_ILVL = 184,
-};
-
-enum AchievementCriteriaFlags
-{
- ACHIEVEMENT_CRITERIA_FLAG_SHOW_PROGRESS_BAR = 0x00000001, // Show progress as bar
- ACHIEVEMENT_CRITERIA_FLAG_HIDDEN = 0x00000002, // Not show criteria in client
- ACHIEVEMENT_CRITERIA_FLAG_FAIL_ACHIEVEMENT = 0x00000004, // BG related??
- ACHIEVEMENT_CRITERIA_FLAG_RESET_ON_START = 0x00000008, //
- ACHIEVEMENT_CRITERIA_FLAG_IS_DATE = 0x00000010, // not used
- ACHIEVEMENT_CRITERIA_FLAG_MONEY_COUNTER = 0x00000020 // Displays counter as money
-};
-
-enum AchievementCriteriaTimedTypes
-{
- ACHIEVEMENT_TIMED_TYPE_EVENT = 1, // Timer is started by internal event with id in timerStartEvent
- ACHIEVEMENT_TIMED_TYPE_QUEST = 2, // Timer is started by accepting quest with entry in timerStartEvent
- ACHIEVEMENT_TIMED_TYPE_SPELL_CASTER = 5, // Timer is started by casting a spell with entry in timerStartEvent
- ACHIEVEMENT_TIMED_TYPE_SPELL_TARGET = 6, // Timer is started by being target of spell with entry in timerStartEvent
- ACHIEVEMENT_TIMED_TYPE_CREATURE = 7, // Timer is started by killing creature with entry in timerStartEvent
- ACHIEVEMENT_TIMED_TYPE_ITEM = 9, // Timer is started by using item with entry in timerStartEvent
- ACHIEVEMENT_TIMED_TYPE_UNK = 10, // Unknown
- ACHIEVEMENT_TIMED_TYPE_UNK_2 = 13, // Unknown
- ACHIEVEMENT_TIMED_TYPE_SCENARIO_STAGE = 14, // Timer is started by changing stages in a scenario
-
- ACHIEVEMENT_TIMED_TYPE_MAX
-};
-
-enum AchievementCriteriaTypes
-{
- ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE = 0,
- ACHIEVEMENT_CRITERIA_TYPE_WIN_BG = 1,
- ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ARCHAEOLOGY_PROJECTS = 3, // struct { uint32 itemCount; }
- ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL = 5,
- ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL = 7,
- ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT = 8,
- ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT = 9,
- ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST_DAILY = 10, // you have to complete a daily quest x times in a row
- ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE = 11,
- ACHIEVEMENT_CRITERIA_TYPE_CURRENCY = 12,
- ACHIEVEMENT_CRITERIA_TYPE_DAMAGE_DONE = 13,
- ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST = 14,
- ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND = 15,
- ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP = 16,
- ACHIEVEMENT_CRITERIA_TYPE_DEATH = 17,
- ACHIEVEMENT_CRITERIA_TYPE_DEATH_IN_DUNGEON = 18,
- ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_RAID = 19,
- ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE = 20,
- ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER = 23,
- ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING = 24,
- ACHIEVEMENT_CRITERIA_TYPE_DEATHS_FROM = 26,
- ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST = 27,
- ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET = 28,
- ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL = 29,
- ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE = 30,
- ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL_AT_AREA = 31,
- ACHIEVEMENT_CRITERIA_TYPE_WIN_ARENA = 32,
- ACHIEVEMENT_CRITERIA_TYPE_PLAY_ARENA = 33,
- ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL = 34,
- ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL = 35,
- ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM = 36,
- ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA = 37,
- ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_TEAM_RATING = 38,
- ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_PERSONAL_RATING = 39,
- ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL = 40,
- ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM = 41,
- ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM = 42,
- ACHIEVEMENT_CRITERIA_TYPE_EXPLORE_AREA = 43,
- ACHIEVEMENT_CRITERIA_TYPE_OWN_RANK = 44,
- ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT = 45,
- ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION = 46,
- ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION = 47,
- ACHIEVEMENT_CRITERIA_TYPE_VISIT_BARBER_SHOP = 48,
- ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM = 49,
- ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT = 50, /// @todo itemlevel is mentioned in text but not present in dbc
- ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT = 51,
- ACHIEVEMENT_CRITERIA_TYPE_HK_CLASS = 52,
- ACHIEVEMENT_CRITERIA_TYPE_HK_RACE = 53,
- ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE = 54,
- ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE = 55,
- ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS = 56, /// @todo in some cases map not present, and in some cases need do without die
- ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM = 57,
- ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_VENDORS = 59,
- ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TALENTS = 60,
- ACHIEVEMENT_CRITERIA_TYPE_NUMBER_OF_TALENT_RESETS = 61,
- ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD = 62,
- ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TRAVELLING = 63,
- ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_AT_BARBER = 65,
- ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_MAIL = 66,
- ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY = 67,
- ACHIEVEMENT_CRITERIA_TYPE_USE_GAMEOBJECT = 68,
- ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2 = 69,
- ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL = 70,
- ACHIEVEMENT_CRITERIA_TYPE_FISH_IN_GAMEOBJECT = 72,
- /// @todo 73: Achievements 1515, 1241, 1103 (Name: Mal'Ganis)
- ACHIEVEMENT_CRITERIA_TYPE_ON_LOGIN = 74,
- ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS = 75,
- ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL = 76,
- ACHIEVEMENT_CRITERIA_TYPE_LOSE_DUEL = 77,
- ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE = 78,
- ACHIEVEMENT_CRITERIA_TYPE_GOLD_EARNED_BY_AUCTIONS = 80,
- ACHIEVEMENT_CRITERIA_TYPE_CREATE_AUCTION = 82,
- ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_BID = 83,
- ACHIEVEMENT_CRITERIA_TYPE_WON_AUCTIONS = 84,
- ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_SOLD = 85,
- ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_GOLD_VALUE_OWNED = 86,
- ACHIEVEMENT_CRITERIA_TYPE_GAIN_REVERED_REPUTATION = 87,
- ACHIEVEMENT_CRITERIA_TYPE_GAIN_HONORED_REPUTATION = 88,
- ACHIEVEMENT_CRITERIA_TYPE_KNOWN_FACTIONS = 89,
- ACHIEVEMENT_CRITERIA_TYPE_LOOT_EPIC_ITEM = 90,
- ACHIEVEMENT_CRITERIA_TYPE_RECEIVE_EPIC_ITEM = 91,
- ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED = 93,
- ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED = 94,
- ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_DEALT = 101,
- ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_RECEIVED = 102,
- ACHIEVEMENT_CRITERIA_TYPE_TOTAL_DAMAGE_RECEIVED = 103,
- ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEAL_CAST = 104,
- ACHIEVEMENT_CRITERIA_TYPE_TOTAL_HEALING_RECEIVED = 105,
- ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEALING_RECEIVED = 106,
- ACHIEVEMENT_CRITERIA_TYPE_QUEST_ABANDONED = 107,
- ACHIEVEMENT_CRITERIA_TYPE_FLIGHT_PATHS_TAKEN = 108,
- ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE = 109,
- ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2 = 110, /// @todo target entry is missing
- ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LINE = 112,
- ACHIEVEMENT_CRITERIA_TYPE_EARN_HONORABLE_KILL = 113,
- ACHIEVEMENT_CRITERIA_TYPE_ACCEPTED_SUMMONINGS = 114,
- ACHIEVEMENT_CRITERIA_TYPE_EARN_ACHIEVEMENT_POINTS = 115,
- ACHIEVEMENT_CRITERIA_TYPE_USE_LFD_TO_GROUP_WITH_PLAYERS = 119,
- ACHIEVEMENT_CRITERIA_TYPE_SPENT_GOLD_GUILD_REPAIRS = 124,
- ACHIEVEMENT_CRITERIA_TYPE_REACH_GUILD_LEVEL = 125,
- ACHIEVEMENT_CRITERIA_TYPE_CRAFT_ITEMS_GUILD = 126,
- ACHIEVEMENT_CRITERIA_TYPE_CATCH_FROM_POOL = 127,
- ACHIEVEMENT_CRITERIA_TYPE_BUY_GUILD_BANK_SLOTS = 128,
- ACHIEVEMENT_CRITERIA_TYPE_EARN_GUILD_ACHIEVEMENT_POINTS = 129,
- ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_BATTLEGROUND = 130,
- ACHIEVEMENT_CRITERIA_TYPE_REACH_BG_RATING = 132,
- ACHIEVEMENT_CRITERIA_TYPE_BUY_GUILD_TABARD = 133,
- ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_GUILD = 134,
- ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILLS_GUILD = 135,
- ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE_GUILD = 136,
- ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_GUILD_CHALLENGE_TYPE = 138, //struct { Flag flag; uint32 count; } 1: Guild Dungeon, 2:Guild Challenge, 3:Guild battlefield
- ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_GUILD_CHALLENGE = 139, //struct { uint32 count; } Guild Challenge
- // 140 unk
- // 141 unk
- // 142 unk
- // 143 unk
- // 144 unk
- ACHIEVEMENT_CRITERIA_TYPE_LFR_DUNGEONS_COMPLETED = 145,
- ACHIEVEMENT_CRITERIA_TYPE_LFR_LEAVES = 146,
- ACHIEVEMENT_CRITERIA_TYPE_LFR_VOTE_KICKS_INITIATED_BY_PLAYER = 147,
- ACHIEVEMENT_CRITERIA_TYPE_LFR_VOTE_KICKS_NOT_INIT_BY_PLAYER = 148,
- ACHIEVEMENT_CRITERIA_TYPE_BE_KICKED_FROM_LFR = 149,
- ACHIEVEMENT_CRITERIA_TYPE_COUNT_OF_LFR_QUEUE_BOOSTS_BY_TANK = 150,
- ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_SCENARIO_COUNT = 151,
- ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_SCENARIO = 152,
- // ACHIEVEMENT_CRITERIA_TYPE_REACH_SOMETHING_LIKE_AREATRIGGER = 153,
- // 154
- ACHIEVEMENT_CRITERIA_TYPE_OWN_BATTLE_PET = 155,
- ACHIEVEMENT_CRITERIA_TYPE_OWN_BATTLE_PET_COUNT = 156,
- ACHIEVEMENT_CRITERIA_TYPE_CAPTURE_BATTLE_PET = 157,
- ACHIEVEMENT_CRITERIA_TYPE_WIN_PET_BATTLE = 158,
- // 159
- ACHIEVEMENT_CRITERIA_TYPE_LEVEL_BATTLE_PET = 160,
- ACHIEVEMENT_CRITERIA_TYPE_CAPTURE_BATTLE_PET_CREDIT = 161, // triggers a quest credit
- ACHIEVEMENT_CRITERIA_TYPE_LEVEL_BATTLE_PET_CREDIT = 162, // triggers a quest credit
- ACHIEVEMENT_CRITERIA_TYPE_ENTER_AREA = 163, // triggers a quest credit
- ACHIEVEMENT_CRITERIA_TYPE_LEAVE_AREA = 164, // triggers a quest credit
- ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DUNGEON_ENCOUNTER = 165,
- ACHIEVEMENT_CRITERIA_TYPE_PLACE_GARRISON_BUILDING = 167,
- ACHIEVEMENT_CRITERIA_TYPE_UPGRADE_GARRISON_BUILDING = 168,
- ACHIEVEMENT_CRITERIA_TYPE_CONSTRUCT_GARRISON_BUILDING = 169,
- ACHIEVEMENT_CRITERIA_TYPE_UPGRADE_GARRISON = 170,
- ACHIEVEMENT_CRITERIA_TYPE_START_GARRISON_MISSION = 171,
- // 172
- ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_GARRISON_MISSION_COUNT = 173,
- ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_GARRISON_MISSION = 174,
- ACHIEVEMENT_CRITERIA_TYPE_RECRUIT_GARRISON_FOLLOWER_COUNT = 175,
- // 176
- // 177
- ACHIEVEMENT_CRITERIA_TYPE_LEARN_GARRISON_BLUEPRINT_COUNT = 178,
- // 179
- // 180
- // 181
- ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_GARRISON_SHIPMENT = 182,
- ACHIEVEMENT_CRITERIA_TYPE_RAISE_GARRISON_FOLLOWER_ITEM_LEVEL = 183,
- ACHIEVEMENT_CRITERIA_TYPE_RAISE_GARRISON_FOLLOWER_LEVEL = 184,
- ACHIEVEMENT_CRITERIA_TYPE_OWN_TOY = 185,
- ACHIEVEMENT_CRITERIA_TYPE_OWN_TOY_COUNT = 186,
- ACHIEVEMENT_CRITERIA_TYPE_RECRUIT_GARRISON_FOLLOWER = 187,
- ACHIEVEMENT_CRITERIA_TYPE_OWN_HEIRLOOMS = 189
-};
-
-#define ACHIEVEMENT_CRITERIA_TYPE_TOTAL 190
-
-enum AchievementCriteriaTreeOperator
-{
- ACHIEVEMENT_CRITERIA_TREE_OPERATOR_ALL = 4,
- ACHIEVEMENT_CRITERIA_TREE_OPERATOR_ANY = 8
+ ACHIEVEMENT_FLAG_ACCOUNT = 0x00020000,
+ ACHIEVEMENT_FLAG_UNK5 = 0x00040000,
+ ACHIEVEMENT_FLAG_HIDE_ZERO_COUNTER = 0x00080000, // statistic is hidden from UI if no criteria value exists
+ ACHIEVEMENT_FLAG_TRACKING_FLAG = 0x00100000, // hidden tracking flag, sent to client in all cases except completion announcements
};
enum AreaFlags
@@ -399,6 +137,271 @@ enum AreaFlags
AREA_FLAG_UNK9 = 0x40000000
};
+enum CriteriaCondition
+{
+ CRITERIA_CONDITION_NONE = 0,
+ CRITERIA_CONDITION_NO_DEATH = 1, // reset progress on death
+ CRITERIA_CONDITION_UNK2 = 2, // only used in "Complete a daily quest every day for five consecutive days"
+ CRITERIA_CONDITION_BG_MAP = 3, // requires you to be on specific map, reset at change
+ CRITERIA_CONDITION_NO_LOSE = 4, // only used in "Win 10 arenas without losing"
+ CRITERIA_CONDITION_UNK5 = 5, // Have spell?
+ CRITERIA_CONDITION_UNK8 = 8,
+ CRITERIA_CONDITION_NO_SPELL_HIT = 9, // requires the player not to be hit by specific spell
+ CRITERIA_CONDITION_NOT_IN_GROUP = 10, // requires the player not to be in group
+ CRITERIA_CONDITION_UNK13 = 13 // unk
+};
+
+enum CriteriaAdditionalCondition
+{
+ CRITERIA_ADDITIONAL_CONDITION_SOURCE_DRUNK_VALUE = 1, // NYI
+ CRITERIA_ADDITIONAL_CONDITION_UNK2 = 2,
+ CRITERIA_ADDITIONAL_CONDITION_ITEM_LEVEL = 3, // NYI
+ CRITERIA_ADDITIONAL_CONDITION_TARGET_CREATURE_ENTRY = 4,
+ CRITERIA_ADDITIONAL_CONDITION_TARGET_MUST_BE_PLAYER = 5,
+ CRITERIA_ADDITIONAL_CONDITION_TARGET_MUST_BE_DEAD = 6,
+ CRITERIA_ADDITIONAL_CONDITION_TARGET_MUST_BE_ENEMY = 7,
+ CRITERIA_ADDITIONAL_CONDITION_SOURCE_HAS_AURA = 8,
+ CRITERIA_ADDITIONAL_CONDITION_TARGET_HAS_AURA = 10,
+ CRITERIA_ADDITIONAL_CONDITION_TARGET_HAS_AURA_TYPE = 11,
+ CRITERIA_ADDITIONAL_CONDITION_ITEM_QUALITY_MIN = 14,
+ CRITERIA_ADDITIONAL_CONDITION_ITEM_QUALITY_EQUALS = 15,
+ CRITERIA_ADDITIONAL_CONDITION_UNK16 = 16,
+ CRITERIA_ADDITIONAL_CONDITION_SOURCE_AREA_OR_ZONE = 17,
+ CRITERIA_ADDITIONAL_CONDITION_TARGET_AREA_OR_ZONE = 18,
+ CRITERIA_ADDITIONAL_CONDITION_MAP_DIFFICULTY = 20,
+ CRITERIA_ADDITIONAL_CONDITION_TARGET_CREATURE_YIELDS_XP = 21, // NYI
+ CRITERIA_ADDITIONAL_CONDITION_ARENA_TYPE = 24,
+ CRITERIA_ADDITIONAL_CONDITION_SOURCE_RACE = 25,
+ CRITERIA_ADDITIONAL_CONDITION_SOURCE_CLASS = 26,
+ CRITERIA_ADDITIONAL_CONDITION_TARGET_RACE = 27,
+ CRITERIA_ADDITIONAL_CONDITION_TARGET_CLASS = 28,
+ CRITERIA_ADDITIONAL_CONDITION_MAX_GROUP_MEMBERS = 29,
+ CRITERIA_ADDITIONAL_CONDITION_TARGET_CREATURE_TYPE = 30,
+ CRITERIA_ADDITIONAL_CONDITION_SOURCE_MAP = 32,
+ CRITERIA_ADDITIONAL_CONDITION_ITEM_CLASS = 33, // NYI
+ CRITERIA_ADDITIONAL_CONDITION_ITEM_SUBCLASS = 34, // NYI
+ CRITERIA_ADDITIONAL_CONDITION_COMPLETE_QUEST_NOT_IN_GROUP = 35, // NYI
+ CRITERIA_ADDITIONAL_CONDITION_MIN_PERSONAL_RATING = 37, // NYI (when implementing don't forget about CRITERIA_CONDITION_NO_LOSE)
+ CRITERIA_ADDITIONAL_CONDITION_TITLE_BIT_INDEX = 38,
+ CRITERIA_ADDITIONAL_CONDITION_SOURCE_LEVEL = 39,
+ CRITERIA_ADDITIONAL_CONDITION_TARGET_LEVEL = 40,
+ CRITERIA_ADDITIONAL_CONDITION_TARGET_ZONE = 41,
+ CRITERIA_ADDITIONAL_CONDITION_TARGET_HEALTH_PERCENT_BELOW = 46,
+ CRITERIA_ADDITIONAL_CONDITION_UNK55 = 55,
+ CRITERIA_ADDITIONAL_CONDITION_MIN_ACHIEVEMENT_POINTS = 56, // NYI
+ CRITERIA_ADDITIONAL_CONDITION_REQUIRES_LFG_GROUP = 58, // NYI
+ CRITERIA_ADDITIONAL_CONDITION_UNK60 = 60,
+ CRITERIA_ADDITIONAL_CONDITION_REQUIRES_GUILD_GROUP = 61, // NYI
+ CRITERIA_ADDITIONAL_CONDITION_GUILD_REPUTATION = 62, // NYI
+ CRITERIA_ADDITIONAL_CONDITION_RATED_BATTLEGROUND = 63, // NYI
+ CRITERIA_ADDITIONAL_CONDITION_PROJECT_RARITY = 65,
+ CRITERIA_ADDITIONAL_CONDITION_PROJECT_RACE = 66,
+ CRITERIA_ADDITIONAL_CONDITION_BATTLE_PET_SPECIES = 91,
+ CRITERIA_ADDITIONAL_CONDITION_GARRISON_FOLLOWER_QUALITY = 145,
+ CRITERIA_ADDITIONAL_CONDITION_GARRISON_FOLLOWER_LEVEL = 146,
+ CRITERIA_ADDITIONAL_CONDITION_GARRISON_RARE_MISSION = 147, // NYI
+ CRITERIA_ADDITIONAL_CONDITION_GARRISON_BUILDING_LEVEL = 149, // NYI
+ CRITERIA_ADDITIONAL_CONDITION_GARRISON_MISSION_TYPE = 167, // NYI
+ CRITERIA_ADDITIONAL_CONDITION_GARRISON_FOLLOWER_ILVL = 184,
+};
+
+enum CriteriaFlags
+{
+ CRITERIA_FLAG_SHOW_PROGRESS_BAR = 0x00000001, // Show progress as bar
+ CRITERIA_FLAG_HIDDEN = 0x00000002, // Not show criteria in client
+ CRITERIA_FLAG_FAIL_ACHIEVEMENT = 0x00000004, // BG related??
+ CRITERIA_FLAG_RESET_ON_START = 0x00000008, //
+ CRITERIA_FLAG_IS_DATE = 0x00000010, // not used
+ CRITERIA_FLAG_MONEY_COUNTER = 0x00000020 // Displays counter as money
+};
+
+enum CriteriaTimedTypes
+{
+ CRITERIA_TIMED_TYPE_EVENT = 1, // Timer is started by internal event with id in timerStartEvent
+ CRITERIA_TIMED_TYPE_QUEST = 2, // Timer is started by accepting quest with entry in timerStartEvent
+ CRITERIA_TIMED_TYPE_SPELL_CASTER = 5, // Timer is started by casting a spell with entry in timerStartEvent
+ CRITERIA_TIMED_TYPE_SPELL_TARGET = 6, // Timer is started by being target of spell with entry in timerStartEvent
+ CRITERIA_TIMED_TYPE_CREATURE = 7, // Timer is started by killing creature with entry in timerStartEvent
+ CRITERIA_TIMED_TYPE_ITEM = 9, // Timer is started by using item with entry in timerStartEvent
+ CRITERIA_TIMED_TYPE_UNK = 10, // Unknown
+ CRITERIA_TIMED_TYPE_UNK_2 = 13, // Unknown
+ CRITERIA_TIMED_TYPE_SCENARIO_STAGE = 14, // Timer is started by changing stages in a scenario
+
+ CRITERIA_TIMED_TYPE_MAX
+};
+
+enum CriteriaTypes
+{
+ CRITERIA_TYPE_KILL_CREATURE = 0,
+ CRITERIA_TYPE_WIN_BG = 1,
+ CRITERIA_TYPE_COMPLETE_ARCHAEOLOGY_PROJECTS = 3, // struct { uint32 itemCount; }
+ CRITERIA_TYPE_REACH_LEVEL = 5,
+ CRITERIA_TYPE_REACH_SKILL_LEVEL = 7,
+ CRITERIA_TYPE_COMPLETE_ACHIEVEMENT = 8,
+ CRITERIA_TYPE_COMPLETE_QUEST_COUNT = 9,
+ CRITERIA_TYPE_COMPLETE_DAILY_QUEST_DAILY = 10, // you have to complete a daily quest x times in a row
+ CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE = 11,
+ CRITERIA_TYPE_CURRENCY = 12,
+ CRITERIA_TYPE_DAMAGE_DONE = 13,
+ CRITERIA_TYPE_COMPLETE_DAILY_QUEST = 14,
+ CRITERIA_TYPE_COMPLETE_BATTLEGROUND = 15,
+ CRITERIA_TYPE_DEATH_AT_MAP = 16,
+ CRITERIA_TYPE_DEATH = 17,
+ CRITERIA_TYPE_DEATH_IN_DUNGEON = 18,
+ CRITERIA_TYPE_COMPLETE_RAID = 19,
+ CRITERIA_TYPE_KILLED_BY_CREATURE = 20,
+ CRITERIA_TYPE_KILLED_BY_PLAYER = 23,
+ CRITERIA_TYPE_FALL_WITHOUT_DYING = 24,
+ CRITERIA_TYPE_DEATHS_FROM = 26,
+ CRITERIA_TYPE_COMPLETE_QUEST = 27,
+ CRITERIA_TYPE_BE_SPELL_TARGET = 28,
+ CRITERIA_TYPE_CAST_SPELL = 29,
+ CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE = 30,
+ CRITERIA_TYPE_HONORABLE_KILL_AT_AREA = 31,
+ CRITERIA_TYPE_WIN_ARENA = 32,
+ CRITERIA_TYPE_PLAY_ARENA = 33,
+ CRITERIA_TYPE_LEARN_SPELL = 34,
+ CRITERIA_TYPE_HONORABLE_KILL = 35,
+ CRITERIA_TYPE_OWN_ITEM = 36,
+ CRITERIA_TYPE_WIN_RATED_ARENA = 37,
+ CRITERIA_TYPE_HIGHEST_TEAM_RATING = 38,
+ CRITERIA_TYPE_HIGHEST_PERSONAL_RATING = 39,
+ CRITERIA_TYPE_LEARN_SKILL_LEVEL = 40,
+ CRITERIA_TYPE_USE_ITEM = 41,
+ CRITERIA_TYPE_LOOT_ITEM = 42,
+ CRITERIA_TYPE_EXPLORE_AREA = 43,
+ CRITERIA_TYPE_OWN_RANK = 44,
+ CRITERIA_TYPE_BUY_BANK_SLOT = 45,
+ CRITERIA_TYPE_GAIN_REPUTATION = 46,
+ CRITERIA_TYPE_GAIN_EXALTED_REPUTATION = 47,
+ CRITERIA_TYPE_VISIT_BARBER_SHOP = 48,
+ CRITERIA_TYPE_EQUIP_EPIC_ITEM = 49,
+ CRITERIA_TYPE_ROLL_NEED_ON_LOOT = 50, /// @todo itemlevel is mentioned in text but not present in dbc
+ CRITERIA_TYPE_ROLL_GREED_ON_LOOT = 51,
+ CRITERIA_TYPE_HK_CLASS = 52,
+ CRITERIA_TYPE_HK_RACE = 53,
+ CRITERIA_TYPE_DO_EMOTE = 54,
+ CRITERIA_TYPE_HEALING_DONE = 55,
+ CRITERIA_TYPE_GET_KILLING_BLOWS = 56, /// @todo in some cases map not present, and in some cases need do without die
+ CRITERIA_TYPE_EQUIP_ITEM = 57,
+ CRITERIA_TYPE_MONEY_FROM_VENDORS = 59,
+ CRITERIA_TYPE_GOLD_SPENT_FOR_TALENTS = 60,
+ CRITERIA_TYPE_NUMBER_OF_TALENT_RESETS = 61,
+ CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD = 62,
+ CRITERIA_TYPE_GOLD_SPENT_FOR_TRAVELLING = 63,
+ CRITERIA_TYPE_GOLD_SPENT_AT_BARBER = 65,
+ CRITERIA_TYPE_GOLD_SPENT_FOR_MAIL = 66,
+ CRITERIA_TYPE_LOOT_MONEY = 67,
+ CRITERIA_TYPE_USE_GAMEOBJECT = 68,
+ CRITERIA_TYPE_BE_SPELL_TARGET2 = 69,
+ CRITERIA_TYPE_SPECIAL_PVP_KILL = 70,
+ CRITERIA_TYPE_FISH_IN_GAMEOBJECT = 72,
+ /// @todo 73: Achievements 1515, 1241, 1103 (Name: Mal'Ganis)
+ CRITERIA_TYPE_ON_LOGIN = 74,
+ CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS = 75,
+ CRITERIA_TYPE_WIN_DUEL = 76,
+ CRITERIA_TYPE_LOSE_DUEL = 77,
+ CRITERIA_TYPE_KILL_CREATURE_TYPE = 78,
+ CRITERIA_TYPE_GOLD_EARNED_BY_AUCTIONS = 80,
+ CRITERIA_TYPE_CREATE_AUCTION = 82,
+ CRITERIA_TYPE_HIGHEST_AUCTION_BID = 83,
+ CRITERIA_TYPE_WON_AUCTIONS = 84,
+ CRITERIA_TYPE_HIGHEST_AUCTION_SOLD = 85,
+ CRITERIA_TYPE_HIGHEST_GOLD_VALUE_OWNED = 86,
+ CRITERIA_TYPE_GAIN_REVERED_REPUTATION = 87,
+ CRITERIA_TYPE_GAIN_HONORED_REPUTATION = 88,
+ CRITERIA_TYPE_KNOWN_FACTIONS = 89,
+ CRITERIA_TYPE_LOOT_EPIC_ITEM = 90,
+ CRITERIA_TYPE_RECEIVE_EPIC_ITEM = 91,
+ CRITERIA_TYPE_ROLL_NEED = 93,
+ CRITERIA_TYPE_ROLL_GREED = 94,
+ CRITERIA_TYPE_HIGHEST_HIT_DEALT = 101,
+ CRITERIA_TYPE_HIGHEST_HIT_RECEIVED = 102,
+ CRITERIA_TYPE_TOTAL_DAMAGE_RECEIVED = 103,
+ CRITERIA_TYPE_HIGHEST_HEAL_CAST = 104,
+ CRITERIA_TYPE_TOTAL_HEALING_RECEIVED = 105,
+ CRITERIA_TYPE_HIGHEST_HEALING_RECEIVED = 106,
+ CRITERIA_TYPE_QUEST_ABANDONED = 107,
+ CRITERIA_TYPE_FLIGHT_PATHS_TAKEN = 108,
+ CRITERIA_TYPE_LOOT_TYPE = 109,
+ CRITERIA_TYPE_CAST_SPELL2 = 110, /// @todo target entry is missing
+ CRITERIA_TYPE_LEARN_SKILL_LINE = 112,
+ CRITERIA_TYPE_EARN_HONORABLE_KILL = 113,
+ CRITERIA_TYPE_ACCEPTED_SUMMONINGS = 114,
+ CRITERIA_TYPE_EARN_ACHIEVEMENT_POINTS = 115,
+ CRITERIA_TYPE_USE_LFD_TO_GROUP_WITH_PLAYERS = 119,
+ CRITERIA_TYPE_SPENT_GOLD_GUILD_REPAIRS = 124,
+ CRITERIA_TYPE_REACH_GUILD_LEVEL = 125,
+ CRITERIA_TYPE_CRAFT_ITEMS_GUILD = 126,
+ CRITERIA_TYPE_CATCH_FROM_POOL = 127,
+ CRITERIA_TYPE_BUY_GUILD_BANK_SLOTS = 128,
+ CRITERIA_TYPE_EARN_GUILD_ACHIEVEMENT_POINTS = 129,
+ CRITERIA_TYPE_WIN_RATED_BATTLEGROUND = 130,
+ CRITERIA_TYPE_REACH_BG_RATING = 132,
+ CRITERIA_TYPE_BUY_GUILD_TABARD = 133,
+ CRITERIA_TYPE_COMPLETE_QUESTS_GUILD = 134,
+ CRITERIA_TYPE_HONORABLE_KILLS_GUILD = 135,
+ CRITERIA_TYPE_KILL_CREATURE_TYPE_GUILD = 136,
+ CRITERIA_TYPE_COMPLETE_GUILD_CHALLENGE_TYPE = 138, //struct { Flag flag; uint32 count; } 1: Guild Dungeon, 2:Guild Challenge, 3:Guild battlefield
+ CRITERIA_TYPE_COMPLETE_GUILD_CHALLENGE = 139, //struct { uint32 count; } Guild Challenge
+ // 140 unk
+ // 141 unk
+ // 142 unk
+ // 143 unk
+ // 144 unk
+ CRITERIA_TYPE_LFR_DUNGEONS_COMPLETED = 145,
+ CRITERIA_TYPE_LFR_LEAVES = 146,
+ CRITERIA_TYPE_LFR_VOTE_KICKS_INITIATED_BY_PLAYER = 147,
+ CRITERIA_TYPE_LFR_VOTE_KICKS_NOT_INIT_BY_PLAYER = 148,
+ CRITERIA_TYPE_BE_KICKED_FROM_LFR = 149,
+ CRITERIA_TYPE_COUNT_OF_LFR_QUEUE_BOOSTS_BY_TANK = 150,
+ CRITERIA_TYPE_COMPLETE_SCENARIO_COUNT = 151,
+ CRITERIA_TYPE_COMPLETE_SCENARIO = 152,
+ // CRITERIA_TYPE_REACH_SOMETHING_LIKE_AREATRIGGER = 153,
+ // 154
+ CRITERIA_TYPE_OWN_BATTLE_PET = 155,
+ CRITERIA_TYPE_OWN_BATTLE_PET_COUNT = 156,
+ CRITERIA_TYPE_CAPTURE_BATTLE_PET = 157,
+ CRITERIA_TYPE_WIN_PET_BATTLE = 158,
+ // 159
+ CRITERIA_TYPE_LEVEL_BATTLE_PET = 160,
+ CRITERIA_TYPE_CAPTURE_BATTLE_PET_CREDIT = 161, // triggers a quest credit
+ CRITERIA_TYPE_LEVEL_BATTLE_PET_CREDIT = 162, // triggers a quest credit
+ CRITERIA_TYPE_ENTER_AREA = 163, // triggers a quest credit
+ CRITERIA_TYPE_LEAVE_AREA = 164, // triggers a quest credit
+ CRITERIA_TYPE_COMPLETE_DUNGEON_ENCOUNTER = 165,
+ CRITERIA_TYPE_PLACE_GARRISON_BUILDING = 167,
+ CRITERIA_TYPE_UPGRADE_GARRISON_BUILDING = 168,
+ CRITERIA_TYPE_CONSTRUCT_GARRISON_BUILDING = 169,
+ CRITERIA_TYPE_UPGRADE_GARRISON = 170,
+ CRITERIA_TYPE_START_GARRISON_MISSION = 171,
+ // 172
+ CRITERIA_TYPE_COMPLETE_GARRISON_MISSION_COUNT = 173,
+ CRITERIA_TYPE_COMPLETE_GARRISON_MISSION = 174,
+ CRITERIA_TYPE_RECRUIT_GARRISON_FOLLOWER_COUNT = 175,
+ // 176
+ // 177
+ CRITERIA_TYPE_LEARN_GARRISON_BLUEPRINT_COUNT = 178,
+ // 179
+ // 180
+ // 181
+ CRITERIA_TYPE_COMPLETE_GARRISON_SHIPMENT = 182,
+ CRITERIA_TYPE_RAISE_GARRISON_FOLLOWER_ITEM_LEVEL = 183,
+ CRITERIA_TYPE_RAISE_GARRISON_FOLLOWER_LEVEL = 184,
+ CRITERIA_TYPE_OWN_TOY = 185,
+ CRITERIA_TYPE_OWN_TOY_COUNT = 186,
+ CRITERIA_TYPE_RECRUIT_GARRISON_FOLLOWER = 187,
+ CRITERIA_TYPE_OWN_HEIRLOOMS = 189
+};
+
+#define CRITERIA_TYPE_TOTAL 190
+
+enum CriteriaTreeOperator
+{
+ CRITERIA_TREE_OPERATOR_ALL = 4,
+ CRITERIA_TREE_OPERATOR_ANY = 8
+};
+
enum Difficulty : uint8
{
DIFFICULTY_NONE = 0,
diff --git a/src/server/game/DungeonFinding/LFGMgr.cpp b/src/server/game/DungeonFinding/LFGMgr.cpp
index 25732e32f93..94885deeffe 100644
--- a/src/server/game/DungeonFinding/LFGMgr.cpp
+++ b/src/server/game/DungeonFinding/LFGMgr.cpp
@@ -1410,7 +1410,7 @@ void LFGMgr::FinishDungeon(ObjectGuid gguid, const uint32 dungeonId)
// Update achievements
if (dungeon->difficulty == DIFFICULTY_HEROIC)
- player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_USE_LFD_TO_GROUP_WITH_PLAYERS, 1);
+ player->UpdateCriteria(CRITERIA_TYPE_USE_LFD_TO_GROUP_WITH_PLAYERS, 1);
LfgReward const* reward = GetRandomDungeonReward(rDungeonId, player->getLevel());
if (!reward)
diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp
index 06851b938ff..42d7ff404db 100644
--- a/src/server/game/Entities/GameObject/GameObject.cpp
+++ b/src/server/game/Entities/GameObject/GameObject.cpp
@@ -1736,7 +1736,7 @@ void GameObject::Use(Unit* user)
Player* player = user->ToPlayer();
player->SendLoot(GetGUID(), LOOT_FISHINGHOLE);
- player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_FISH_IN_GAMEOBJECT, GetGOInfo()->entry);
+ player->UpdateCriteria(CRITERIA_TYPE_FISH_IN_GAMEOBJECT, GetGOInfo()->entry);
return;
}
diff --git a/src/server/game/Entities/Player/KillRewarder.cpp b/src/server/game/Entities/Player/KillRewarder.cpp
index d7ebf9cc220..3c022538fe2 100644
--- a/src/server/game/Entities/Player/KillRewarder.cpp
+++ b/src/server/game/Entities/Player/KillRewarder.cpp
@@ -177,7 +177,7 @@ inline void KillRewarder::_RewardKillCredit(Player* player)
if (Creature* target = _victim->ToCreature())
{
player->KilledMonster(target->GetCreatureTemplate(), target->GetGUID());
- player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE, target->GetCreatureType(), 1, 0, target);
+ player->UpdateCriteria(CRITERIA_TYPE_KILL_CREATURE_TYPE, target->GetCreatureType(), 1, 0, target);
}
}
@@ -240,7 +240,7 @@ void KillRewarder::_RewardGroup()
if (member->IsAtGroupRewardDistance(_victim))
{
_RewardPlayer(member, isDungeon);
- member->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL, 1, 0, 0, _victim);
+ member->UpdateCriteria(CRITERIA_TYPE_SPECIAL_PVP_KILL, 1, 0, 0, _victim);
}
}
}
@@ -277,7 +277,7 @@ void KillRewarder::Reward()
if (ObjectGuid::LowType guildId = victim->GetMap()->GetOwnerGuildId())
if (Guild* guild = sGuildMgr->GetGuildById(guildId))
- guild->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE, victim->GetEntry(), 1, 0, victim, _killer);
+ guild->UpdateCriteria(CRITERIA_TYPE_KILL_CREATURE, victim->GetEntry(), 1, 0, victim, _killer);
}
}
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index f722319e192..d32150b8038 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -332,7 +332,7 @@ Player::Player(WorldSession* session) : Unit(true)
memset(_voidStorageItems, 0, VOID_STORAGE_MAX_SLOT * sizeof(VoidStorageItem*));
- m_achievementMgr = new AchievementMgr<Player>(this);
+ m_achievementMgr = new PlayerAchievementMgr(this);
m_reputationMgr = new ReputationMgr(this);
for (uint8 i = 0; i < MAX_CUF_PROFILES; ++i)
@@ -770,7 +770,7 @@ uint32 Player::EnvironmentalDamage(EnviromentalDamage type, uint32 damage)
SendDurabilityLoss(this, 10);
}
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DEATHS_FROM, 1, type);
+ UpdateCriteria(CRITERIA_TYPE_DEATHS_FROM, 1, type);
}
return final_damage;
@@ -1088,7 +1088,7 @@ void Player::Update(uint32 p_time)
}
}
- m_achievementMgr->UpdateTimedAchievements(p_time);
+ m_achievementMgr->UpdateTimedCriteria(p_time);
if (HasUnitState(UNIT_STATE_MELEE_ATTACKING) && !HasUnitState(UNIT_STATE_CASTING))
{
@@ -1373,12 +1373,12 @@ void Player::setDeathState(DeathState s)
// passive spell
if (!ressSpellId)
ressSpellId = GetResurrectionSpellId();
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP, 1);
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DEATH, 1);
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DEATH_IN_DUNGEON, 1);
- ResetAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, ACHIEVEMENT_CRITERIA_CONDITION_NO_DEATH);
- ResetAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL, ACHIEVEMENT_CRITERIA_CONDITION_NO_DEATH);
- ResetAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS, ACHIEVEMENT_CRITERIA_CONDITION_NO_DEATH);
+ UpdateCriteria(CRITERIA_TYPE_DEATH_AT_MAP, 1);
+ UpdateCriteria(CRITERIA_TYPE_DEATH, 1);
+ UpdateCriteria(CRITERIA_TYPE_DEATH_IN_DUNGEON, 1);
+ ResetCriteria(CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE, CRITERIA_CONDITION_NO_DEATH);
+ ResetCriteria(CRITERIA_TYPE_HONORABLE_KILL, CRITERIA_CONDITION_NO_DEATH);
+ ResetCriteria(CRITERIA_TYPE_GET_KILLING_BLOWS, CRITERIA_CONDITION_NO_DEATH);
}
Unit::setDeathState(s);
@@ -2475,7 +2475,7 @@ void Player::GiveLevel(uint8 level)
CharacterDatabase.CommitTransaction(trans);
}
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL);
+ UpdateCriteria(CRITERIA_TYPE_REACH_LEVEL);
// Refer-A-Friend
if (GetSession()->GetRecruiterId())
@@ -3173,11 +3173,11 @@ bool Player::AddSpell(uint32 spellId, bool active, bool learning, bool dependent
// not ranked skills
for (SkillLineAbilityMap::const_iterator _spell_idx = skill_bounds.first; _spell_idx != skill_bounds.second; ++_spell_idx)
{
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LINE, _spell_idx->second->SkillLine);
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS, _spell_idx->second->SkillLine);
+ UpdateCriteria(CRITERIA_TYPE_LEARN_SKILL_LINE, _spell_idx->second->SkillLine);
+ UpdateCriteria(CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS, _spell_idx->second->SkillLine);
}
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL, spellId);
+ UpdateCriteria(CRITERIA_TYPE_LEARN_SPELL, spellId);
}
// return true (for send learn packet) only if spell active (in case ranked spells) and not replace old spell
@@ -3535,8 +3535,8 @@ bool Player::ResetTalents(bool noCost)
if (!noCost)
{
ModifyMoney(-(int64)cost);
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TALENTS, cost);
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_NUMBER_OF_TALENT_RESETS, 1);
+ UpdateCriteria(CRITERIA_TYPE_GOLD_SPENT_FOR_TALENTS, cost);
+ UpdateCriteria(CRITERIA_TYPE_NUMBER_OF_TALENT_RESETS, 1);
SetTalentResetCost(cost);
SetTalentResetTime(time(nullptr));
@@ -5137,7 +5137,7 @@ bool Player::UpdateSkill(uint32 skill_id, uint32 step)
itr->second.uState = SKILL_CHANGED;
UpdateSkillEnchantments(skill_id, value, new_value);
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL, skill_id);
+ UpdateCriteria(CRITERIA_TYPE_REACH_SKILL_LEVEL, skill_id);
return true;
}
@@ -5289,7 +5289,7 @@ bool Player::UpdateSkillPro(uint16 skillId, int32 chance, uint32 step)
}
UpdateSkillEnchantments(skillId, value, new_value);
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL, skillId);
+ UpdateCriteria(CRITERIA_TYPE_REACH_SKILL_LEVEL, skillId);
TC_LOG_DEBUG("entities.player.skills", "Player::UpdateSkillPro: Player '%s' (%s), SkillID: %u, Chance: %3.1f%% taken",
GetName().c_str(), GetGUID().ToString().c_str(), skillId, chance / 10.0f);
return true;
@@ -5417,8 +5417,8 @@ void Player::SetSkill(uint16 id, uint16 step, uint16 newVal, uint16 maxVal)
if (newVal > currVal)
UpdateSkillEnchantments(id, currVal, newVal);
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL, id);
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL, id);
+ UpdateCriteria(CRITERIA_TYPE_REACH_SKILL_LEVEL, id);
+ UpdateCriteria(CRITERIA_TYPE_LEARN_SKILL_LEVEL, id);
}
else //remove
{
@@ -5483,8 +5483,8 @@ void Player::SetSkill(uint16 id, uint16 step, uint16 newVal, uint16 maxVal)
SetUInt16Value(PLAYER_SKILL_LINEID + SKILL_MAX_RANK_OFFSET + field, offset, maxVal);
UpdateSkillEnchantments(id, currVal, newVal);
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL, id);
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL, id);
+ UpdateCriteria(CRITERIA_TYPE_REACH_SKILL_LEVEL, id);
+ UpdateCriteria(CRITERIA_TYPE_LEARN_SKILL_LEVEL, id);
// insert new entry or update if not deleted old entry yet
if (itr != mSkillStatus.end())
@@ -5896,7 +5896,7 @@ void Player::CheckAreaExploreAndOutdoor()
{
SetUInt32Value(PLAYER_EXPLORED_ZONES_1 + offset, (uint32)(currFields | val));
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EXPLORE_AREA);
+ UpdateCriteria(CRITERIA_TYPE_EXPLORE_AREA);
if (areaEntry->ExplorationLevel > 0)
{
@@ -6256,11 +6256,11 @@ bool Player::RewardHonor(Unit* victim, uint32 groupsize, int32 honor, bool pvpto
ApplyModUInt16Value(PLAYER_FIELD_KILLS, PLAYER_FIELD_KILLS_OFFSET_TODAY_KILLS, 1, true);
// and those in a lifetime
ApplyModUInt32Value(PLAYER_FIELD_LIFETIME_HONORABLE_KILLS, 1, true);
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EARN_HONORABLE_KILL);
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HK_CLASS, victim->getClass());
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HK_RACE, victim->getRace());
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL_AT_AREA, GetAreaId());
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL, 1, 0, 0, victim);
+ UpdateCriteria(CRITERIA_TYPE_EARN_HONORABLE_KILL);
+ UpdateCriteria(CRITERIA_TYPE_HK_CLASS, victim->getClass());
+ UpdateCriteria(CRITERIA_TYPE_HK_RACE, victim->getRace());
+ UpdateCriteria(CRITERIA_TYPE_HONORABLE_KILL_AT_AREA, GetAreaId());
+ UpdateCriteria(CRITERIA_TYPE_HONORABLE_KILL, 1, 0, 0, victim);
}
else
{
@@ -6568,7 +6568,7 @@ void Player::ModifyCurrency(uint32 id, int32 count, bool printLog/* = true*/, bo
itr->second.TrackedQuantity = newTrackedCount;
if (count > 0)
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CURRENCY, id, count);
+ UpdateCriteria(CRITERIA_TYPE_CURRENCY, id, count);
CurrencyChanged(id, count);
@@ -7040,8 +7040,8 @@ void Player::DuelComplete(DuelCompleteType type)
}
break;
case DUEL_WON:
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOSE_DUEL, 1);
- duel->opponent->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL, 1);
+ UpdateCriteria(CRITERIA_TYPE_LOSE_DUEL, 1);
+ duel->opponent->UpdateCriteria(CRITERIA_TYPE_WIN_DUEL, 1);
// Credit for quest Death's Challenge
if (getClass() == CLASS_DEATH_KNIGHT && duel->opponent->GetQuestStatus(12733) == QUEST_STATUS_INCOMPLETE)
@@ -11031,8 +11031,8 @@ Item* Player::StoreNewItem(ItemPosCountVec const& pos, uint32 itemId, bool updat
if (item)
{
ItemAddedQuestCheck(itemId, count);
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_RECEIVE_EPIC_ITEM, itemId, count);
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM, itemId, 1);
+ UpdateCriteria(CRITERIA_TYPE_RECEIVE_EPIC_ITEM, itemId, count);
+ UpdateCriteria(CRITERIA_TYPE_OWN_ITEM, itemId, 1);
if (sDB2Manager.GetHeirloomByItemId(itemId))
GetSession()->GetCollectionMgr()->AddHeirloom(itemId, 0);
@@ -11206,7 +11206,7 @@ Item* Player::EquipNewItem(uint16 pos, uint32 item, bool update)
if (Item* pItem = Item::CreateItem(item, 1, this))
{
ItemAddedQuestCheck(item, 1);
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_RECEIVE_EPIC_ITEM, item, 1);
+ UpdateCriteria(CRITERIA_TYPE_RECEIVE_EPIC_ITEM, item, 1);
return EquipItem(pos, pItem, update);
}
@@ -11315,8 +11315,8 @@ Item* Player::EquipItem(uint16 pos, Item* pItem, bool update)
}
// only for full equip instead adding to stack
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM, pItem->GetEntry());
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM, pItem->GetEntry(), slot);
+ UpdateCriteria(CRITERIA_TYPE_EQUIP_ITEM, pItem->GetEntry());
+ UpdateCriteria(CRITERIA_TYPE_EQUIP_EPIC_ITEM, pItem->GetEntry(), slot);
return pItem;
}
@@ -11337,8 +11337,8 @@ void Player::QuickEquipItem(uint16 pos, Item* pItem)
pItem->SendUpdateToPlayer(this);
}
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM, pItem->GetEntry());
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM, pItem->GetEntry(), slot);
+ UpdateCriteria(CRITERIA_TYPE_EQUIP_ITEM, pItem->GetEntry());
+ UpdateCriteria(CRITERIA_TYPE_EQUIP_EPIC_ITEM, pItem->GetEntry(), slot);
}
}
@@ -11490,7 +11490,7 @@ void Player::MoveItemToInventory(ItemPosCountVec const& dest, Item* pItem, bool
{
// update quest counters
ItemAddedQuestCheck(pItem->GetEntry(), pItem->GetCount());
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_RECEIVE_EPIC_ITEM, pItem->GetEntry(), pItem->GetCount());
+ UpdateCriteria(CRITERIA_TYPE_RECEIVE_EPIC_ITEM, pItem->GetEntry(), pItem->GetCount());
// store item
Item* pLastItem = StoreItem(dest, pItem, update);
@@ -14099,7 +14099,7 @@ void Player::AddQuest(Quest const* quest, Object* questGiver)
m_QuestStatusSave[quest_id] = QUEST_DEFAULT_SAVE_TYPE;
- StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_QUEST, quest_id);
+ StartCriteriaTimer(CRITERIA_TIMED_TYPE_QUEST, quest_id);
SendQuestUpdate(quest_id);
@@ -14307,7 +14307,7 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver,
ModifyMoney(moneyRew);
if (moneyRew > 0)
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD, uint32(moneyRew));
+ UpdateCriteria(CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD, uint32(moneyRew));
}
// honor reward
@@ -14335,8 +14335,8 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver,
SetDailyQuestStatus(quest_id);
if (quest->IsDaily())
{
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST, quest_id);
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST_DAILY, quest_id);
+ UpdateCriteria(CRITERIA_TYPE_COMPLETE_DAILY_QUEST, quest_id);
+ UpdateCriteria(CRITERIA_TYPE_COMPLETE_DAILY_QUEST_DAILY, quest_id);
}
}
else if (quest->IsWeekly())
@@ -14383,9 +14383,9 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver,
}
if (quest->GetZoneOrSort() > 0)
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE, quest->GetZoneOrSort());
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT);
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST, quest->GetQuestId());
+ UpdateCriteria(CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE, quest->GetZoneOrSort());
+ UpdateCriteria(CRITERIA_TYPE_COMPLETE_QUEST_COUNT);
+ UpdateCriteria(CRITERIA_TYPE_COMPLETE_QUEST, quest->GetQuestId());
if (uint32 questBit = sDB2Manager.GetQuestUniqueBitFlag(quest_id))
SetQuestCompletedBit(questBit, true);
@@ -15453,8 +15453,8 @@ void Player::KilledMonsterCredit(uint32 entry, ObjectGuid guid /*= ObjectGuid::E
real_entry = killed->GetEntry();
}
- StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_CREATURE, real_entry); // MUST BE CALLED FIRST
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE, real_entry, addKillCount, 0, killed);
+ StartCriteriaTimer(CRITERIA_TIMED_TYPE_CREATURE, real_entry); // MUST BE CALLED FIRST
+ UpdateCriteria(CRITERIA_TYPE_KILL_CREATURE, real_entry, addKillCount, 0, killed);
for (uint8 i = 0; i < MAX_QUEST_LOG_SIZE; ++i)
{
@@ -16321,7 +16321,7 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder)
SetObjectScale(1.0f);
SetFloatValue(UNIT_FIELD_HOVERHEIGHT, 1.0f);
- // load achievements before anything else to prevent multiple gains for the same achievement/criteria on every loading (as loading does call UpdateAchievementCriteria)
+ // load achievements before anything else to prevent multiple gains for the same achievement/criteria on every loading (as loading does call UpdateCriteria)
m_achievementMgr->LoadFromDB(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_ACHIEVEMENTS), holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_CRITERIA_PROGRESS));
uint64 money = fields[8].GetUInt64();
@@ -20794,7 +20794,7 @@ bool Player::ActivateTaxiPathTo(std::vector<uint32> const& nodes, Creature* npc
}
//Checks and preparations done, DO FLIGHT
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_FLIGHT_PATHS_TAKEN, 1);
+ UpdateCriteria(CRITERIA_TYPE_FLIGHT_PATHS_TAKEN, 1);
// prevent stealth flight
//RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TALK);
@@ -20805,14 +20805,14 @@ bool Player::ActivateTaxiPathTo(std::vector<uint32> const& nodes, Creature* npc
ASSERT(lastPathNode);
m_taxi.ClearTaxiDestinations();
ModifyMoney(-int64(totalcost));
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TRAVELLING, totalcost);
+ UpdateCriteria(CRITERIA_TYPE_GOLD_SPENT_FOR_TRAVELLING, totalcost);
TeleportTo(lastPathNode->MapID, lastPathNode->Pos.X, lastPathNode->Pos.Y, lastPathNode->Pos.Z, GetOrientation());
return false;
}
else
{
ModifyMoney(-int64(firstcost));
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TRAVELLING, firstcost);
+ UpdateCriteria(CRITERIA_TYPE_GOLD_SPENT_FOR_TRAVELLING, firstcost);
GetSession()->SendActivateTaxiReply(ERR_TAXIOK);
GetSession()->SendDoFlight(mount_display_id, sourcepath);
}
@@ -22153,7 +22153,7 @@ void Player::SetMoney(uint64 value)
{
SetUInt64Value(PLAYER_FIELD_COINAGE, value);
MoneyChanged(value);
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_GOLD_VALUE_OWNED);
+ UpdateCriteria(CRITERIA_TYPE_HIGHEST_GOLD_VALUE_OWNED);
}
bool Player::IsQuestRewarded(uint32 quest_id) const
@@ -22277,7 +22277,7 @@ void Player::SendInitialPacketsBeforeAddToMap()
/// SMSG_EQUIPMENT_SET_LIST
SendEquipmentSetList();
- m_achievementMgr->SendAllAchievementData(this);
+ m_achievementMgr->SendAllData(this);
/// SMSG_LOGIN_SETTIMESPEED
static float const TimeSpeed = 0.01666667f;
@@ -23165,7 +23165,7 @@ void Player::SummonIfPossible(bool agree)
m_summon_expire = 0;
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_ACCEPTED_SUMMONINGS, 1);
+ UpdateCriteria(CRITERIA_TYPE_ACCEPTED_SUMMONINGS, 1);
TeleportTo(m_summon_location);
}
@@ -24365,9 +24365,9 @@ void Player::StoreLootItem(uint8 lootSlot, Loot* loot)
guild->AddGuildNews(GUILD_NEWS_ITEM_LOOTED, GetGUID(), 0, item->itemid);
SendNewItem(newitem, uint32(item->count), false, false, true);
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM, item->itemid, item->count);
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE, item->itemid, item->count, loot->loot_type);
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_EPIC_ITEM, item->itemid, item->count);
+ UpdateCriteria(CRITERIA_TYPE_LOOT_ITEM, item->itemid, item->count);
+ UpdateCriteria(CRITERIA_TYPE_LOOT_TYPE, item->itemid, item->count, loot->loot_type);
+ UpdateCriteria(CRITERIA_TYPE_LOOT_EPIC_ITEM, item->itemid, item->count);
// LootItem is being removed (looted) from the container, delete it from the DB.
if (!loot->containerID.IsEmpty())
@@ -24623,7 +24623,7 @@ void Player::HandleFall(MovementInfo const& movementInfo)
// recheck alive, might have died of EnvironmentalDamage, avoid cases when player die in fact like Spirit of Redemption case
if (IsAlive() && final_damage < original_health)
- UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING, uint32(z_diff*100));
+ UpdateCriteria(CRITERIA_TYPE_FALL_WITHOUT_DYING, uint32(z_diff*100));
}
//Z given by moveinfo, LastZ, FallTime, WaterZ, MapZ, Damage, Safefall reduction
@@ -24653,34 +24653,34 @@ bool Player::HasAchieved(uint32 achievementId) const
return m_achievementMgr->HasAchieved(achievementId);
}
-void Player::StartTimedAchievement(AchievementCriteriaTimedTypes type, uint32 entry, uint32 timeLost/* = 0*/)
+void Player::StartCriteriaTimer(CriteriaTimedTypes type, uint32 entry, uint32 timeLost/* = 0*/)
{
- m_achievementMgr->StartTimedAchievement(type, entry, timeLost);
+ m_achievementMgr->StartCriteriaTimer(type, entry, timeLost);
}
-void Player::RemoveTimedAchievement(AchievementCriteriaTimedTypes type, uint32 entry)
+void Player::RemoveCriteriaTimer(CriteriaTimedTypes type, uint32 entry)
{
- m_achievementMgr->RemoveTimedAchievement(type, entry);
+ m_achievementMgr->RemoveCriteriaTimer(type, entry);
}
-void Player::ResetAchievementCriteria(AchievementCriteriaTypes type, uint64 miscValue1 /*= 0*/, uint64 miscValue2 /*= 0*/, bool evenIfCriteriaComplete /* = false*/)
+void Player::ResetCriteria(CriteriaTypes type, uint64 miscValue1 /*= 0*/, uint64 miscValue2 /*= 0*/, bool evenIfCriteriaComplete /* = false*/)
{
- m_achievementMgr->ResetAchievementCriteria(type, miscValue1, miscValue2, evenIfCriteriaComplete);
+ m_achievementMgr->ResetCriteria(type, miscValue1, miscValue2, evenIfCriteriaComplete);
}
-void Player::UpdateAchievementCriteria(AchievementCriteriaTypes type, uint64 miscValue1 /*= 0*/, uint64 miscValue2 /*= 0*/, uint64 miscValue3 /*= 0*/, Unit* unit /*= NULL*/)
+void Player::UpdateCriteria(CriteriaTypes type, uint64 miscValue1 /*= 0*/, uint64 miscValue2 /*= 0*/, uint64 miscValue3 /*= 0*/, Unit* unit /*= NULL*/)
{
- m_achievementMgr->UpdateAchievementCriteria(type, miscValue1, miscValue2, miscValue3, unit, this);
+ m_achievementMgr->UpdateCriteria(type, miscValue1, miscValue2, miscValue3, unit, this);
Guild* guild = sGuildMgr->GetGuildById(GetGuildId());
if (!guild)
return;
// Update only individual achievement criteria here, otherwise we may get multiple updates
// from a single boss kill
- if (sAchievementMgr->IsGroupCriteriaType(type))
+ if (CriteriaMgr::IsGroupCriteriaType(type))
return;
- guild->UpdateAchievementCriteria(type, miscValue1, miscValue2, miscValue3, unit, this);
+ guild->UpdateCriteria(type, miscValue1, miscValue2, miscValue3, unit, this);
}
void Player::CompletedAchievement(AchievementEntry const* entry)
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index 7128a6feaa8..a2a7c7794cd 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -40,7 +40,7 @@ struct ItemExtendedCostEntry;
struct TrainerSpell;
struct VendorItem;
-template<class T> class AchievementMgr;
+class PlayerAchievementMgr;
class ReputationMgr;
class Channel;
class Creature;
@@ -2429,10 +2429,10 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
uint32 GetAchievementPoints() const;
bool HasAchieved(uint32 achievementId) const;
void ResetAchievements();
- 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* unit = NULL);
- void StartTimedAchievement(AchievementCriteriaTimedTypes type, uint32 entry, uint32 timeLost = 0);
- void RemoveTimedAchievement(AchievementCriteriaTimedTypes type, uint32 entry);
+ void ResetCriteria(CriteriaTypes type, uint64 miscValue1 = 0, uint64 miscValue2 = 0, bool evenIfCriteriaComplete = false);
+ void UpdateCriteria(CriteriaTypes type, uint64 miscValue1 = 0, uint64 miscValue2 = 0, uint64 miscValue3 = 0, Unit* unit = NULL);
+ void StartCriteriaTimer(CriteriaTimedTypes type, uint32 entry, uint32 timeLost = 0);
+ void RemoveCriteriaTimer(CriteriaTimedTypes type, uint32 entry);
void CompletedAchievement(AchievementEntry const* entry);
bool HasTitle(uint32 bitIndex) const;
@@ -2813,7 +2813,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
uint32 m_temporaryUnsummonedPetNumber;
uint32 m_oldpetspell;
- AchievementMgr<Player>* m_achievementMgr;
+ PlayerAchievementMgr* m_achievementMgr;
ReputationMgr* m_reputationMgr;
uint32 m_ChampioningFaction;
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index 4f15ed1d078..589bde335f0 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -740,12 +740,12 @@ uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDam
if (Battleground* bg = killer->GetBattleground())
bg->UpdatePlayerScore(killer, SCORE_DAMAGE_DONE, damage);
- killer->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DAMAGE_DONE, damage, 0, 0, victim);
- killer->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_DEALT, damage);
+ killer->UpdateCriteria(CRITERIA_TYPE_DAMAGE_DONE, damage, 0, 0, victim);
+ killer->UpdateCriteria(CRITERIA_TYPE_HIGHEST_HIT_DEALT, damage);
}
if (victim->GetTypeId() == TYPEID_PLAYER)
- victim->ToPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_RECEIVED, damage);
+ victim->ToPlayer()->UpdateCriteria(CRITERIA_TYPE_HIGHEST_HIT_RECEIVED, damage);
else if (!victim->IsControlledByPlayer() || victim->IsVehicle())
{
if (!victim->ToCreature()->hasLootRecipient())
@@ -760,7 +760,7 @@ uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDam
TC_LOG_DEBUG("entities.unit", "DealDamage: victim just died");
if (victim->GetTypeId() == TYPEID_PLAYER && victim != this)
- victim->ToPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_TOTAL_DAMAGE_RECEIVED, health);
+ victim->ToPlayer()->UpdateCriteria(CRITERIA_TYPE_TOTAL_DAMAGE_RECEIVED, health);
Kill(victim, durabilityLoss);
}
@@ -769,7 +769,7 @@ uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDam
TC_LOG_DEBUG("entities.unit", "DealDamageAlive");
if (victim->GetTypeId() == TYPEID_PLAYER)
- victim->ToPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_TOTAL_DAMAGE_RECEIVED, damage);
+ victim->ToPlayer()->UpdateCriteria(CRITERIA_TYPE_TOTAL_DAMAGE_RECEIVED, damage);
victim->ModifyHealth(-(int32)damage);
@@ -7585,15 +7585,15 @@ int32 Unit::DealHeal(Unit* victim, uint32 addhealth)
// use the actual gain, as the overheal shall not be counted, skip gain 0 (it ignored anyway in to criteria)
if (gain)
- player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE, gain, 0, 0, victim);
+ player->UpdateCriteria(CRITERIA_TYPE_HEALING_DONE, gain, 0, 0, victim);
- player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEAL_CAST, addhealth);
+ player->UpdateCriteria(CRITERIA_TYPE_HIGHEST_HEAL_CAST, addhealth);
}
if (Player* player = victim->ToPlayer())
{
- player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_TOTAL_HEALING_RECEIVED, gain);
- player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEALING_RECEIVED, addhealth);
+ player->UpdateCriteria(CRITERIA_TYPE_TOTAL_HEALING_RECEIVED, gain);
+ player->UpdateCriteria(CRITERIA_TYPE_HIGHEST_HEALING_RECEIVED, addhealth);
}
return gain;
@@ -13165,7 +13165,7 @@ void Unit::Kill(Unit* victim, bool durabilityLoss)
// update get killing blow achievements, must be done before setDeathState to be able to require auras on target
// and before Spirit of Redemption as it also removes auras
if (Player* killerPlayer = GetCharmerOrOwnerPlayerOrPlayerItself())
- killerPlayer->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS, 1, 0, 0, victim);
+ killerPlayer->UpdateCriteria(CRITERIA_TYPE_GET_KILLING_BLOWS, 1, 0, 0, victim);
// if talent known but not triggered (check priest class for speedup check)
bool spiritOfRedemption = false;
@@ -13334,9 +13334,9 @@ void Unit::Kill(Unit* victim, bool durabilityLoss)
if (victim->GetTypeId() == TYPEID_PLAYER)
{
if (GetTypeId() == TYPEID_UNIT)
- victim->ToPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE, GetEntry());
+ victim->ToPlayer()->UpdateCriteria(CRITERIA_TYPE_KILLED_BY_CREATURE, GetEntry());
else if (GetTypeId() == TYPEID_PLAYER && victim != this)
- victim->ToPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER, 1, ToPlayer()->GetTeam());
+ victim->ToPlayer()->UpdateCriteria(CRITERIA_TYPE_KILLED_BY_PLAYER, 1, ToPlayer()->GetTeam());
}
// Hook for OnPVPKill Event
diff --git a/src/server/game/Garrison/Garrison.cpp b/src/server/game/Garrison/Garrison.cpp
index cc07187d7a9..56cbb9ad58e 100644
--- a/src/server/game/Garrison/Garrison.cpp
+++ b/src/server/game/Garrison/Garrison.cpp
@@ -407,7 +407,7 @@ void Garrison::PlaceBuilding(uint32 garrPlotInstanceId, uint32 garrBuildingId)
_owner->SendDirectMessage(buildingRemoved.Write());
}
- _owner->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_PLACE_GARRISON_BUILDING, garrBuildingId);
+ _owner->UpdateCriteria(CRITERIA_TYPE_PLACE_GARRISON_BUILDING, garrBuildingId);
}
_owner->SendDirectMessage(placeBuildingResult.Write());
@@ -511,7 +511,7 @@ void Garrison::AddFollower(uint32 garrFollowerId)
addFollowerResult.Follower = follower.PacketInfo;
_owner->SendDirectMessage(addFollowerResult.Write());
- _owner->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_RECRUIT_GARRISON_FOLLOWER, follower.PacketInfo.DbID);
+ _owner->UpdateCriteria(CRITERIA_TYPE_RECRUIT_GARRISON_FOLLOWER, follower.PacketInfo.DbID);
}
Garrison::Follower const* Garrison::GetFollower(uint64 dbId) const
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp
index 8b12f60cbb8..96936a82d08 100644
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -6289,7 +6289,7 @@ void ObjectMgr::LoadAccessRequirements()
if (ar->achievement)
{
- if (!sAchievementMgr->GetAchievement(ar->achievement))
+ if (!sAchievementStore.LookupEntry(ar->achievement))
{
TC_LOG_ERROR("sql.sql", "Required Achievement %u not exist for map %u difficulty %u, remove quest done requirement.", ar->achievement, mapid, difficulty);
ar->achievement = 0;
@@ -8588,12 +8588,12 @@ void ObjectMgr::LoadScriptNames()
_scriptNamesStore.emplace_back("");
QueryResult result = WorldDatabase.Query(
- "SELECT DISTINCT(ScriptName) FROM achievement_criteria_data WHERE ScriptName <> '' AND type = 11 "
- "UNION "
"SELECT DISTINCT(ScriptName) FROM battleground_template WHERE ScriptName <> '' "
"UNION "
"SELECT DISTINCT(ScriptName) FROM creature_template WHERE ScriptName <> '' "
"UNION "
+ "SELECT DISTINCT(ScriptName) FROM criteria_data WHERE ScriptName <> '' AND type = 11 "
+ "UNION "
"SELECT DISTINCT(ScriptName) FROM gameobject_template WHERE ScriptName <> '' "
"UNION "
"SELECT DISTINCT(ScriptName) FROM item_script_names WHERE ScriptName <> '' "
@@ -8775,9 +8775,9 @@ void ObjectMgr::LoadFactionChangeAchievements()
uint32 alliance = fields[0].GetUInt32();
uint32 horde = fields[1].GetUInt32();
- if (!sAchievementMgr->GetAchievement(alliance))
+ if (!sAchievementStore.LookupEntry(alliance))
TC_LOG_ERROR("sql.sql", "Achievement %u (alliance_id) referenced in `player_factionchange_achievement` does not exist, pair skipped!", alliance);
- else if (!sAchievementMgr->GetAchievement(horde))
+ else if (!sAchievementStore.LookupEntry(horde))
TC_LOG_ERROR("sql.sql", "Achievement %u (horde_id) referenced in `player_factionchange_achievement` does not exist, pair skipped!", horde);
else
FactionChangeAchievements[alliance] = horde;
diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp
index b95a235bcb6..43763631b0b 100644
--- a/src/server/game/Groups/Group.cpp
+++ b/src/server/game/Groups/Group.cpp
@@ -1417,7 +1417,7 @@ void Group::CountTheRoll(Rolls::iterator rollI)
if (player && player->GetSession())
{
- player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT, roll->itemid, maxresul);
+ player->UpdateCriteria(CRITERIA_TYPE_ROLL_NEED_ON_LOOT, roll->itemid, maxresul);
ItemPosCountVec dest;
LootItem* item = &(roll->itemSlot >= roll->getLoot()->items.size() ? roll->getLoot()->quest_items[roll->itemSlot - roll->getLoot()->items.size()] : roll->getLoot()->items[roll->itemSlot]);
@@ -1466,7 +1466,7 @@ void Group::CountTheRoll(Rolls::iterator rollI)
if (player && player->GetSession())
{
- player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT, roll->itemid, maxresul);
+ player->UpdateCriteria(CRITERIA_TYPE_ROLL_GREED_ON_LOOT, roll->itemid, maxresul);
LootItem* item = &(roll->itemSlot >= roll->getLoot()->items.size() ? roll->getLoot()->quest_items[roll->itemSlot - roll->getLoot()->items.size()] : roll->getLoot()->items[roll->itemSlot]);
@@ -1493,7 +1493,7 @@ void Group::CountTheRoll(Rolls::iterator rollI)
roll->getLoot()->NotifyItemRemoved(roll->itemSlot);
roll->getLoot()->unlootedCount--;
ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(roll->itemid);
- player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL, 13262); // Disenchant
+ player->UpdateCriteria(CRITERIA_TYPE_CAST_SPELL, 13262); // Disenchant
ItemPosCountVec dest;
InventoryResult msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, roll->itemid, item->count);
diff --git a/src/server/game/Guilds/Guild.cpp b/src/server/game/Guilds/Guild.cpp
index 586af65ae5a..86a59f04f23 100644
--- a/src/server/game/Guilds/Guild.cpp
+++ b/src/server/game/Guilds/Guild.cpp
@@ -1391,11 +1391,11 @@ void Guild::HandleSetAchievementTracking(WorldSession* session, std::set<uint32>
for (uint32 achievementId : achievementIds)
{
- if (AchievementEntry const* achievement = sAchievementMgr->GetAchievement(achievementId))
+ if (AchievementEntry const* achievement = sAchievementStore.LookupEntry(achievementId))
{
- if (AchievementCriteriaTree const* tree = sAchievementMgr->GetAchievementCriteriaTree(achievement->CriteriaTree))
+ if (CriteriaTree const* tree = sCriteriaMgr->GetCriteriaTree(achievement->CriteriaTree))
{
- sAchievementMgr->WalkCriteriaTree(tree, [&criteriaIds](AchievementCriteriaTree const* node)
+ CriteriaMgr::WalkCriteriaTree(tree, [&criteriaIds](CriteriaTree const* node)
{
if (node->Criteria)
criteriaIds.insert(node->Criteria->ID);
@@ -2162,7 +2162,7 @@ void Guild::SendLoginInfo(WorldSession* session)
if (entry->GuildLevel <= GetLevel())
player->LearnSpell(entry->SpellID, true);
- m_achievementMgr.SendAllAchievementData(player);
+ m_achievementMgr.SendAllData(player);
WorldPackets::Guild::GuildMemberDailyReset packet; // tells the client to request bank withdrawal limit
player->GetSession()->SendPacket(packet.Write());
@@ -3384,9 +3384,9 @@ bool Guild::HasAchieved(uint32 achievementId) const
return m_achievementMgr.HasAchieved(achievementId);
}
-void Guild::UpdateAchievementCriteria(AchievementCriteriaTypes type, uint64 miscValue1, uint64 miscValue2, uint64 miscValue3, Unit* unit, Player* player)
+void Guild::UpdateCriteria(CriteriaTypes type, uint64 miscValue1, uint64 miscValue2, uint64 miscValue3, Unit* unit, Player* player)
{
- m_achievementMgr.UpdateAchievementCriteria(type, miscValue1, miscValue2, miscValue3, unit, player);
+ m_achievementMgr.UpdateCriteria(type, miscValue1, miscValue2, miscValue3, unit, player);
}
void Guild::HandleNewsSetSticky(WorldSession* session, uint32 newsId, bool sticky)
diff --git a/src/server/game/Guilds/Guild.h b/src/server/game/Guilds/Guild.h
index d41a4f7c726..db20f48c3e7 100644
--- a/src/server/game/Guilds/Guild.h
+++ b/src/server/game/Guilds/Guild.h
@@ -865,8 +865,8 @@ public:
// Bank tabs
void SetBankTabText(uint8 tabId, std::string const& text);
- AchievementMgr<Guild>& GetAchievementMgr() { return m_achievementMgr; }
- AchievementMgr<Guild> const& GetAchievementMgr() const { return m_achievementMgr; }
+ GuildAchievementMgr& GetAchievementMgr() { return m_achievementMgr; }
+ GuildAchievementMgr const& GetAchievementMgr() const { return m_achievementMgr; }
// Guild leveling
uint8 GetLevel() const { return _level; }
@@ -877,7 +877,7 @@ public:
void ResetTimes(bool weekly);
bool HasAchieved(uint32 achievementId) const;
- void UpdateAchievementCriteria(AchievementCriteriaTypes type, uint64 miscValue1, uint64 miscValue2, uint64 miscValue3, Unit* unit, Player* player);
+ void UpdateCriteria(CriteriaTypes type, uint64 miscValue1, uint64 miscValue2, uint64 miscValue3, Unit* unit, Player* player);
protected:
ObjectGuid::LowType m_id;
@@ -899,7 +899,7 @@ protected:
LogHolder* m_eventLog;
LogHolder* m_bankEventLog[GUILD_BANK_MAX_TABS + 1];
LogHolder* m_newsLog;
- AchievementMgr<Guild> m_achievementMgr;
+ GuildAchievementMgr m_achievementMgr;
uint8 _level;
diff --git a/src/server/game/Guilds/GuildMgr.cpp b/src/server/game/Guilds/GuildMgr.cpp
index 8cafc8cdd2f..6af809dcedb 100644
--- a/src/server/game/Guilds/GuildMgr.cpp
+++ b/src/server/game/Guilds/GuildMgr.cpp
@@ -511,7 +511,7 @@ void GuildMgr::LoadGuildRewards()
uint32 requiredAchievementId = fields[0].GetUInt32();
- if (!sAchievementMgr->GetAchievement(requiredAchievementId))
+ if (!sAchievementStore.LookupEntry(requiredAchievementId))
{
TC_LOG_ERROR("server.loading", "Guild rewards constains not existing achievement entry %u", requiredAchievementId);
continue;
diff --git a/src/server/game/Handlers/AuctionHouseHandler.cpp b/src/server/game/Handlers/AuctionHouseHandler.cpp
index f0e2d8693b0..43a0baa75a7 100644
--- a/src/server/game/Handlers/AuctionHouseHandler.cpp
+++ b/src/server/game/Handlers/AuctionHouseHandler.cpp
@@ -279,7 +279,7 @@ void WorldSession::HandleAuctionSellItem(WorldPackets::AuctionHouse::AuctionSell
SendAuctionCommandResult(AH, AUCTION_SELL_ITEM, ERR_AUCTION_OK);
- GetPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CREATE_AUCTION, 1);
+ GetPlayer()->UpdateCriteria(CRITERIA_TYPE_CREATE_AUCTION, 1);
}
else // Required stack size of auction does not match to current item stack size, clone item and set correct stack size
{
@@ -354,7 +354,7 @@ void WorldSession::HandleAuctionSellItem(WorldPackets::AuctionHouse::AuctionSell
SendAuctionCommandResult(AH, AUCTION_SELL_ITEM, ERR_AUCTION_OK);
- GetPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CREATE_AUCTION, 1);
+ GetPlayer()->UpdateCriteria(CRITERIA_TYPE_CREATE_AUCTION, 1);
}
}
@@ -437,7 +437,7 @@ void WorldSession::HandleAuctionPlaceBid(WorldPackets::AuctionHouse::AuctionPlac
auction->bidder = player->GetGUID().GetCounter();
auction->bid = packet.BidAmount;
- GetPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_BID, packet.BidAmount);
+ GetPlayer()->UpdateCriteria(CRITERIA_TYPE_HIGHEST_AUCTION_BID, packet.BidAmount);
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_AUCTION_BID);
stmt->setUInt64(0, auction->bidder);
@@ -466,7 +466,7 @@ void WorldSession::HandleAuctionPlaceBid(WorldPackets::AuctionHouse::AuctionPlac
}
auction->bidder = player->GetGUID().GetCounter();
auction->bid = auction->buyout;
- GetPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_BID, auction->buyout);
+ GetPlayer()->UpdateCriteria(CRITERIA_TYPE_HIGHEST_AUCTION_BID, auction->buyout);
SendAuctionCommandResult(auction, AUCTION_PLACE_BID, ERR_AUCTION_OK);
diff --git a/src/server/game/Handlers/BankHandler.cpp b/src/server/game/Handlers/BankHandler.cpp
index 38f5862b3b6..65321cd6fa8 100644
--- a/src/server/game/Handlers/BankHandler.cpp
+++ b/src/server/game/Handlers/BankHandler.cpp
@@ -159,7 +159,7 @@ void WorldSession::HandleBuyBankSlotOpcode(WorldPackets::Bank::BuyBankSlot& pack
data << uint32(ERR_BANKSLOT_OK);
SendPacket(&data);
- _player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT);
+ _player->UpdateCriteria(CRITERIA_TYPE_BUY_BANK_SLOT);
}
void WorldSession::SendShowBank(ObjectGuid guid)
diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp
index dff529891b6..ee75a4ed58c 100644
--- a/src/server/game/Handlers/CharacterHandler.cpp
+++ b/src/server/game/Handlers/CharacterHandler.cpp
@@ -1133,7 +1133,7 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder)
m_playerLoading.Clear();
// Handle Login-Achievements (should be handled after loading)
- _player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_ON_LOGIN, 1);
+ _player->UpdateCriteria(CRITERIA_TYPE_ON_LOGIN, 1);
sScriptMgr->OnPlayerLogin(pCurrChar, firstLogin);
@@ -1460,7 +1460,7 @@ void WorldSession::HandleAlterAppearance(WorldPackets::Character::AlterApperance
SendBarberShopResult(BARBER_SHOP_RESULT_SUCCESS);
_player->ModifyMoney(-int64(cost)); // it isn't free
- _player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_AT_BARBER, cost);
+ _player->UpdateCriteria(CRITERIA_TYPE_GOLD_SPENT_AT_BARBER, cost);
_player->SetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_HAIR_STYLE_ID, uint8(bs_hair->Data));
_player->SetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_HAIR_COLOR_ID, uint8(packet.NewHairColor));
@@ -1470,7 +1470,7 @@ void WorldSession::HandleAlterAppearance(WorldPackets::Character::AlterApperance
if (bs_face)
_player->SetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_FACE_ID, uint8(bs_face->Data));
- _player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_VISIT_BARBER_SHOP, 1);
+ _player->UpdateCriteria(CRITERIA_TYPE_VISIT_BARBER_SHOP, 1);
_player->SetStandState(UNIT_STAND_STATE_STAND);
}
@@ -2051,8 +2051,8 @@ void WorldSession::HandleCharRaceOrFactionChangeCallback(PreparedQueryResult res
trans->Append(stmt);
stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_ACHIEVEMENT);
- stmt->setUInt16(0, uint16(newTeamId == TEAM_ALLIANCE ? achiev_alliance : achiev_horde));
- stmt->setUInt16(1, uint16(newTeamId == TEAM_ALLIANCE ? achiev_horde : achiev_alliance));
+ stmt->setUInt32(0, uint16(newTeamId == TEAM_ALLIANCE ? achiev_alliance : achiev_horde));
+ stmt->setUInt32(1, uint16(newTeamId == TEAM_ALLIANCE ? achiev_horde : achiev_alliance));
stmt->setUInt64(2, lowGuid);
trans->Append(stmt);
}
diff --git a/src/server/game/Handlers/ChatHandler.cpp b/src/server/game/Handlers/ChatHandler.cpp
index 2c77d8df04d..2d5099fa341 100644
--- a/src/server/game/Handlers/ChatHandler.cpp
+++ b/src/server/game/Handlers/ChatHandler.cpp
@@ -627,7 +627,7 @@ void WorldSession::HandleTextEmoteOpcode(WorldPackets::Chat::CTextEmote& packet)
Unit* unit = ObjectAccessor::GetUnit(*_player, packet.Target);
- _player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE, packet.SoundIndex, 0, 0, unit);
+ _player->UpdateCriteria(CRITERIA_TYPE_DO_EMOTE, packet.SoundIndex, 0, 0, unit);
// Send scripted event call
if (unit)
diff --git a/src/server/game/Handlers/GroupHandler.cpp b/src/server/game/Handlers/GroupHandler.cpp
index ec29083d2f8..097a1979400 100644
--- a/src/server/game/Handlers/GroupHandler.cpp
+++ b/src/server/game/Handlers/GroupHandler.cpp
@@ -376,10 +376,10 @@ void WorldSession::HandleLootRoll(WorldPackets::Loot::LootRoll& packet)
switch (packet.RollType)
{
case ROLL_NEED:
- GetPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED, 1);
+ GetPlayer()->UpdateCriteria(CRITERIA_TYPE_ROLL_NEED, 1);
break;
case ROLL_GREED:
- GetPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED, 1);
+ GetPlayer()->UpdateCriteria(CRITERIA_TYPE_ROLL_GREED, 1);
break;
}
}
diff --git a/src/server/game/Handlers/ItemHandler.cpp b/src/server/game/Handlers/ItemHandler.cpp
index f253b4733e7..8c7f8190e09 100644
--- a/src/server/game/Handlers/ItemHandler.cpp
+++ b/src/server/game/Handlers/ItemHandler.cpp
@@ -437,7 +437,7 @@ void WorldSession::HandleSellItemOpcode(WorldPackets::Item::SellItem& packet)
uint32 money = pProto->GetSellPrice() * packet.Amount;
_player->ModifyMoney(money);
- _player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_VENDORS, money);
+ _player->UpdateCriteria(CRITERIA_TYPE_MONEY_FROM_VENDORS, money);
}
else
_player->SendSellError(SELL_ERR_CANT_SELL_ITEM, creature, packet.ItemGUID);
@@ -481,7 +481,7 @@ void WorldSession::HandleBuybackItem(WorldPackets::Item::BuyBackItem& packet)
_player->ModifyMoney(-(int32)price);
_player->RemoveItemFromBuyBackSlot(packet.Slot, false);
_player->ItemAddedQuestCheck(pItem->GetEntry(), pItem->GetCount());
- _player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_RECEIVE_EPIC_ITEM, pItem->GetEntry(), pItem->GetCount());
+ _player->UpdateCriteria(CRITERIA_TYPE_RECEIVE_EPIC_ITEM, pItem->GetEntry(), pItem->GetCount());
_player->StoreItem(dest, pItem, true);
}
else
diff --git a/src/server/game/Handlers/LootHandler.cpp b/src/server/game/Handlers/LootHandler.cpp
index 0d497089f75..f4772b1b347 100644
--- a/src/server/game/Handlers/LootHandler.cpp
+++ b/src/server/game/Handlers/LootHandler.cpp
@@ -185,7 +185,7 @@ void WorldSession::HandleLootMoneyOpcode(WorldPackets::Loot::LootMoney& /*packet
for (std::vector<Player*>::const_iterator i = playersNear.begin(); i != playersNear.end(); ++i)
{
(*i)->ModifyMoney(goldPerPlayer);
- (*i)->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY, goldPerPlayer);
+ (*i)->UpdateCriteria(CRITERIA_TYPE_LOOT_MONEY, goldPerPlayer);
if (Guild* guild = sGuildMgr->GetGuildById((*i)->GetGuildId()))
if (uint32 guildGold = CalculatePct(goldPerPlayer, (*i)->GetTotalAuraModifier(SPELL_AURA_DEPOSIT_BONUS_MONEY_IN_GUILD_BANK_ON_LOOT)))
@@ -200,7 +200,7 @@ void WorldSession::HandleLootMoneyOpcode(WorldPackets::Loot::LootMoney& /*packet
else
{
player->ModifyMoney(loot->gold);
- player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY, loot->gold);
+ player->UpdateCriteria(CRITERIA_TYPE_LOOT_MONEY, loot->gold);
if (Guild* guild = sGuildMgr->GetGuildById(player->GetGuildId()))
if (uint32 guildGold = CalculatePct(loot->gold, player->GetTotalAuraModifier(SPELL_AURA_DEPOSIT_BONUS_MONEY_IN_GUILD_BANK_ON_LOOT)))
@@ -471,9 +471,9 @@ void WorldSession::HandleLootMasterGiveOpcode(WorldPacket& recvData)
// now move item from loot to target inventory
Item* newitem = target->StoreNewItem(dest, item.itemid, true, item.randomPropertyId, item.GetAllowedLooters(), item.BonusListIDs);
target->SendNewItem(newitem, uint32(item.count), false, false, true);
- target->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM, item.itemid, item.count);
- target->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE, item.itemid, item.count, loot->loot_type);
- target->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_EPIC_ITEM, item.itemid, item.count);
+ target->UpdateCriteria(CRITERIA_TYPE_LOOT_ITEM, item.itemid, item.count);
+ target->UpdateCriteria(CRITERIA_TYPE_LOOT_TYPE, item.itemid, item.count, loot->loot_type);
+ target->UpdateCriteria(CRITERIA_TYPE_LOOT_EPIC_ITEM, item.itemid, item.count);
// mark as looted
item.count = 0;
diff --git a/src/server/game/Handlers/MailHandler.cpp b/src/server/game/Handlers/MailHandler.cpp
index 40cc854d740..81221599b2c 100644
--- a/src/server/game/Handlers/MailHandler.cpp
+++ b/src/server/game/Handlers/MailHandler.cpp
@@ -274,7 +274,7 @@ void WorldSession::HandleSendMail(WorldPackets::Mail::SendMail& packet)
player->SendMailResult(0, MAIL_SEND, MAIL_OK);
player->ModifyMoney(-reqmoney);
- player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_MAIL, cost);
+ player->UpdateCriteria(CRITERIA_TYPE_GOLD_SPENT_FOR_MAIL, cost);
bool needItemDelay = false;
diff --git a/src/server/game/Handlers/QuestHandler.cpp b/src/server/game/Handlers/QuestHandler.cpp
index cb56a81e5d9..bfa0bc3db16 100644
--- a/src/server/game/Handlers/QuestHandler.cpp
+++ b/src/server/game/Handlers/QuestHandler.cpp
@@ -436,7 +436,7 @@ void WorldSession::HandleQuestLogRemoveQuest(WorldPackets::Quest::QuestLogRemove
_player->TakeQuestSourceItem(questId, true); // remove quest src item from player
_player->RemoveActiveQuest(questId);
- _player->RemoveTimedAchievement(ACHIEVEMENT_TIMED_TYPE_QUEST, questId);
+ _player->RemoveCriteriaTimer(CRITERIA_TIMED_TYPE_QUEST, questId);
TC_LOG_INFO("network", "%s abandoned quest %u", _player->GetGUID().ToString().c_str(), questId);
@@ -454,7 +454,7 @@ void WorldSession::HandleQuestLogRemoveQuest(WorldPackets::Quest::QuestLogRemove
_player->SetQuestSlot(packet.Entry, 0);
- _player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_QUEST_ABANDONED, 1);
+ _player->UpdateCriteria(CRITERIA_TYPE_QUEST_ABANDONED, 1);
}
}
diff --git a/src/server/game/Handlers/SpellHandler.cpp b/src/server/game/Handlers/SpellHandler.cpp
index 4a28c076ce6..7d639d57f80 100644
--- a/src/server/game/Handlers/SpellHandler.cpp
+++ b/src/server/game/Handlers/SpellHandler.cpp
@@ -238,7 +238,7 @@ void WorldSession::HandleGameobjectReportUse(WorldPackets::GameObject::GameObjRe
if (go->AI()->GossipHello(_player))
return;
- _player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_USE_GAMEOBJECT, go->GetEntry());
+ _player->UpdateCriteria(CRITERIA_TYPE_USE_GAMEOBJECT, go->GetEntry());
}
}
diff --git a/src/server/game/Instances/InstanceScript.cpp b/src/server/game/Instances/InstanceScript.cpp
index 2969d5666ac..dc008aa881e 100644
--- a/src/server/game/Instances/InstanceScript.cpp
+++ b/src/server/game/Instances/InstanceScript.cpp
@@ -538,36 +538,36 @@ void InstanceScript::DoSendNotifyToInstance(char const* format, ...)
}
// Update Achievement Criteria for all players in instance
-void InstanceScript::DoUpdateAchievementCriteria(AchievementCriteriaTypes type, uint32 miscValue1 /*= 0*/, uint32 miscValue2 /*= 0*/, Unit* unit /*= NULL*/)
+void InstanceScript::DoUpdateCriteria(CriteriaTypes type, uint32 miscValue1 /*= 0*/, uint32 miscValue2 /*= 0*/, Unit* unit /*= NULL*/)
{
Map::PlayerList const &PlayerList = instance->GetPlayers();
if (!PlayerList.isEmpty())
for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
if (Player* player = i->GetSource())
- player->UpdateAchievementCriteria(type, miscValue1, miscValue2, 0, unit);
+ player->UpdateCriteria(type, miscValue1, miscValue2, 0, unit);
}
// Start timed achievement for all players in instance
-void InstanceScript::DoStartTimedAchievement(AchievementCriteriaTimedTypes type, uint32 entry)
+void InstanceScript::DoStartCriteriaTimer(CriteriaTimedTypes type, uint32 entry)
{
Map::PlayerList const &PlayerList = instance->GetPlayers();
if (!PlayerList.isEmpty())
for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
if (Player* player = i->GetSource())
- player->StartTimedAchievement(type, entry);
+ player->StartCriteriaTimer(type, entry);
}
// Stop timed achievement for all players in instance
-void InstanceScript::DoStopTimedAchievement(AchievementCriteriaTimedTypes type, uint32 entry)
+void InstanceScript::DoStopCriteriaTimer(CriteriaTimedTypes type, uint32 entry)
{
Map::PlayerList const &PlayerList = instance->GetPlayers();
if (!PlayerList.isEmpty())
for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
if (Player* player = i->GetSource())
- player->RemoveTimedAchievement(type, entry);
+ player->RemoveCriteriaTimer(type, entry);
}
// Remove Auras due to Spell on all players in instance
diff --git a/src/server/game/Instances/InstanceScript.h b/src/server/game/Instances/InstanceScript.h
index 7a2daaaecf8..92c7be92752 100644
--- a/src/server/game/Instances/InstanceScript.h
+++ b/src/server/game/Instances/InstanceScript.h
@@ -210,11 +210,11 @@ class TC_GAME_API InstanceScript : public ZoneScript
void DoSendNotifyToInstance(char const* format, ...);
// Update Achievement Criteria for all players in instance
- void DoUpdateAchievementCriteria(AchievementCriteriaTypes type, uint32 miscValue1 = 0, uint32 miscValue2 = 0, Unit* unit = NULL);
+ void DoUpdateCriteria(CriteriaTypes type, uint32 miscValue1 = 0, uint32 miscValue2 = 0, Unit* unit = NULL);
// Start/Stop Timed Achievement Criteria for all players in instance
- void DoStartTimedAchievement(AchievementCriteriaTimedTypes type, uint32 entry);
- void DoStopTimedAchievement(AchievementCriteriaTimedTypes type, uint32 entry);
+ void DoStartCriteriaTimer(CriteriaTimedTypes type, uint32 entry);
+ void DoStopCriteriaTimer(CriteriaTimedTypes type, uint32 entry);
// Remove Auras due to Spell on all players in instance
void DoRemoveAurasDueToSpellOnPlayers(uint32 spell);
diff --git a/src/server/game/Maps/MapManager.cpp b/src/server/game/Maps/MapManager.cpp
index 985ce1af681..3acd04543ad 100644
--- a/src/server/game/Maps/MapManager.cpp
+++ b/src/server/game/Maps/MapManager.cpp
@@ -34,7 +34,6 @@
#include "Player.h"
#include "WorldSession.h"
#include "Opcodes.h"
-#include "AchievementMgr.h"
#include "MiscPackets.h"
MapManager::MapManager()
@@ -370,5 +369,4 @@ void MapManager::FreeInstanceId(uint32 instanceId)
SetNextInstanceId(instanceId);
_instanceIds[instanceId] = false;
- sAchievementMgr->OnInstanceDestroyed(instanceId);
}
diff --git a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp
index d6d54f052e9..4d6383e5931 100755
--- a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp
@@ -370,7 +370,7 @@ bool FlightPathMovementGenerator::DoUpdate(Player* player, uint32 /*diff*/)
player->m_taxi.NextTaxiDestination();
if (!_pointsForPathSwitch.empty())
{
- player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TRAVELLING, _pointsForPathSwitch.front().Cost);
+ player->UpdateCriteria(CRITERIA_TYPE_GOLD_SPENT_FOR_TRAVELLING, _pointsForPathSwitch.front().Cost);
player->ModifyMoney(-_pointsForPathSwitch.front().Cost);
}
}
diff --git a/src/server/game/Reputation/ReputationMgr.cpp b/src/server/game/Reputation/ReputationMgr.cpp
index be0714b2747..ceecf1a9b85 100644
--- a/src/server/game/Reputation/ReputationMgr.cpp
+++ b/src/server/game/Reputation/ReputationMgr.cpp
@@ -367,11 +367,11 @@ bool ReputationMgr::SetOneFactionReputation(FactionEntry const* factionEntry, in
UpdateRankCounters(old_rank, new_rank);
_player->ReputationChanged(factionEntry);
- _player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KNOWN_FACTIONS, factionEntry->ID);
- _player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION, factionEntry->ID);
- _player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION, factionEntry->ID);
- _player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_REVERED_REPUTATION, factionEntry->ID);
- _player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GAIN_HONORED_REPUTATION, factionEntry->ID);
+ _player->UpdateCriteria(CRITERIA_TYPE_KNOWN_FACTIONS, factionEntry->ID);
+ _player->UpdateCriteria(CRITERIA_TYPE_GAIN_REPUTATION, factionEntry->ID);
+ _player->UpdateCriteria(CRITERIA_TYPE_GAIN_EXALTED_REPUTATION, factionEntry->ID);
+ _player->UpdateCriteria(CRITERIA_TYPE_GAIN_REVERED_REPUTATION, factionEntry->ID);
+ _player->UpdateCriteria(CRITERIA_TYPE_GAIN_HONORED_REPUTATION, factionEntry->ID);
return true;
}
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index c89ff4b2c7a..594221099d6 100644
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -2527,15 +2527,15 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleA
if (Player* player = unit->ToPlayer())
{
- player->StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_SPELL_TARGET, m_spellInfo->Id);
- player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, m_spellInfo->Id, 0, 0, m_caster);
- player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2, m_spellInfo->Id);
+ player->StartCriteriaTimer(CRITERIA_TIMED_TYPE_SPELL_TARGET, m_spellInfo->Id);
+ player->UpdateCriteria(CRITERIA_TYPE_BE_SPELL_TARGET, m_spellInfo->Id, 0, 0, m_caster);
+ player->UpdateCriteria(CRITERIA_TYPE_BE_SPELL_TARGET2, m_spellInfo->Id);
}
if (Player* player = m_caster->ToPlayer())
{
- player->StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_SPELL_CASTER, m_spellInfo->Id);
- player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2, m_spellInfo->Id, 0, 0, unit);
+ player->StartCriteriaTimer(CRITERIA_TIMED_TYPE_SPELL_CASTER, m_spellInfo->Id);
+ player->UpdateCriteria(CRITERIA_TYPE_CAST_SPELL2, m_spellInfo->Id, 0, 0, unit);
}
if (m_caster != unit)
@@ -3270,11 +3270,11 @@ void Spell::cast(bool skipCheck)
{
if (!(_triggeredCastFlags & TRIGGERED_IGNORE_CAST_ITEM) && m_CastItem)
{
- player->StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_ITEM, m_CastItem->GetEntry());
- player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM, m_CastItem->GetEntry());
+ player->StartCriteriaTimer(CRITERIA_TIMED_TYPE_ITEM, m_CastItem->GetEntry());
+ player->UpdateCriteria(CRITERIA_TYPE_USE_ITEM, m_CastItem->GetEntry());
}
- player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL, m_spellInfo->Id);
+ player->UpdateCriteria(CRITERIA_TYPE_CAST_SPELL, m_spellInfo->Id);
}
if (!(_triggeredCastFlags & TRIGGERED_IGNORE_POWER_AND_REAGENT_COST))
diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp
index 2b316f15572..b274750c5ab 100644
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -2211,7 +2211,7 @@ void Spell::EffectLearnSpell(SpellEffIndex effIndex)
if (entry->SummonSpellID == spellToLearn)
{
battlePetMgr->AddPet(entry->ID, entry->CreatureID, BattlePetMgr::RollPetBreed(entry->ID), BattlePetMgr::GetDefaultPetQuality(entry->ID));
- player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_OWN_BATTLE_PET_COUNT);
+ player->UpdateCriteria(CRITERIA_TYPE_OWN_BATTLE_PET_COUNT);
break;
}
}
diff --git a/src/server/game/Tools/CharacterDatabaseCleaner.cpp b/src/server/game/Tools/CharacterDatabaseCleaner.cpp
index 7fa56b77900..255900b5414 100644
--- a/src/server/game/Tools/CharacterDatabaseCleaner.cpp
+++ b/src/server/game/Tools/CharacterDatabaseCleaner.cpp
@@ -17,7 +17,7 @@
*/
#include "Common.h"
-#include "AchievementMgr.h"
+#include "CriteriaHandler.h"
#include "CharacterDatabaseCleaner.h"
#include "World.h"
#include "Database/DatabaseEnv.h"
@@ -109,7 +109,7 @@ void CharacterDatabaseCleaner::CheckUnique(const char* column, const char* table
bool CharacterDatabaseCleaner::AchievementProgressCheck(uint32 criteria)
{
- return sAchievementMgr->GetAchievementCriteria(criteria) != nullptr;
+ return sCriteriaMgr->GetCriteria(criteria) != nullptr;
}
void CharacterDatabaseCleaner::CleanCharacterAchievementProgress()
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index 3fc233b5c3c..61e1755b4e4 100644
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -1816,14 +1816,14 @@ void World::SetInitialWorldSettings()
TC_LOG_INFO("server.loading", "Loading skill tier info...");
sObjectMgr->LoadSkillTiers();
+ TC_LOG_INFO("server.loading", "Loading Criteria Modifier trees...");
+ sCriteriaMgr->LoadCriteriaModifiersTree();
+ TC_LOG_INFO("server.loading", "Loading Criteria Lists...");
+ sCriteriaMgr->LoadCriteriaList();
+ TC_LOG_INFO("server.loading", "Loading Criteria Data...");
+ sCriteriaMgr->LoadCriteriaData();
TC_LOG_INFO("server.loading", "Loading Achievements...");
sAchievementMgr->LoadAchievementReferenceList();
- TC_LOG_INFO("server.loading", "Loading Achievement Criteria Modifier trees...");
- sAchievementMgr->LoadAchievementCriteriaModifiersTree();
- TC_LOG_INFO("server.loading", "Loading Achievement Criteria Lists...");
- sAchievementMgr->LoadAchievementCriteriaList();
- TC_LOG_INFO("server.loading", "Loading Achievement Criteria Data...");
- sAchievementMgr->LoadAchievementCriteriaData();
TC_LOG_INFO("server.loading", "Loading Achievement Rewards...");
sAchievementMgr->LoadRewards();
TC_LOG_INFO("server.loading", "Loading Achievement Reward Locales...");
diff --git a/src/server/scripts/Commands/cs_achievement.cpp b/src/server/scripts/Commands/cs_achievement.cpp
index ef14ca66519..2238c76b5f5 100644
--- a/src/server/scripts/Commands/cs_achievement.cpp
+++ b/src/server/scripts/Commands/cs_achievement.cpp
@@ -68,7 +68,7 @@ public:
return false;
}
- if (AchievementEntry const* achievementEntry = sAchievementMgr->GetAchievement(achievementId))
+ if (AchievementEntry const* achievementEntry = sAchievementStore.LookupEntry(achievementId))
target->CompletedAchievement(achievementEntry);
return true;
diff --git a/src/server/scripts/Commands/cs_disable.cpp b/src/server/scripts/Commands/cs_disable.cpp
index 54932228372..75b35324c91 100644
--- a/src/server/scripts/Commands/cs_disable.cpp
+++ b/src/server/scripts/Commands/cs_disable.cpp
@@ -23,7 +23,7 @@ Category: commandscripts
EndScriptData */
#include "DisableMgr.h"
-#include "AchievementMgr.h"
+#include "CriteriaHandler.h"
#include "Chat.h"
#include "Language.h"
#include "ObjectMgr.h"
@@ -41,25 +41,25 @@ public:
{
static std::vector<ChatCommand> removeDisableCommandTable =
{
- { "spell", rbac::RBAC_PERM_COMMAND_DISABLE_REMOVE_SPELL, true, &HandleRemoveDisableSpellCommand, "" },
- { "quest", rbac::RBAC_PERM_COMMAND_DISABLE_REMOVE_QUEST, true, &HandleRemoveDisableQuestCommand, "" },
- { "map", rbac::RBAC_PERM_COMMAND_DISABLE_REMOVE_MAP, true, &HandleRemoveDisableMapCommand, "" },
- { "battleground", rbac::RBAC_PERM_COMMAND_DISABLE_REMOVE_BATTLEGROUND, true, &HandleRemoveDisableBattlegroundCommand, "" },
- { "achievement_criteria", rbac::RBAC_PERM_COMMAND_DISABLE_REMOVE_ACHIEVEMENT_CRITERIA, true, &HandleRemoveDisableAchievementCriteriaCommand, "" },
- { "outdoorpvp", rbac::RBAC_PERM_COMMAND_DISABLE_REMOVE_OUTDOORPVP, true, &HandleRemoveDisableOutdoorPvPCommand, "" },
- { "vmap", rbac::RBAC_PERM_COMMAND_DISABLE_REMOVE_VMAP, true, &HandleRemoveDisableVmapCommand, "" },
- { "mmap", rbac::RBAC_PERM_COMMAND_DISABLE_REMOVE_MMAP, true, &HandleRemoveDisableMMapCommand, "" },
+ { "spell", rbac::RBAC_PERM_COMMAND_DISABLE_REMOVE_SPELL, true, &HandleRemoveDisableSpellCommand, "" },
+ { "quest", rbac::RBAC_PERM_COMMAND_DISABLE_REMOVE_QUEST, true, &HandleRemoveDisableQuestCommand, "" },
+ { "map", rbac::RBAC_PERM_COMMAND_DISABLE_REMOVE_MAP, true, &HandleRemoveDisableMapCommand, "" },
+ { "battleground", rbac::RBAC_PERM_COMMAND_DISABLE_REMOVE_BATTLEGROUND, true, &HandleRemoveDisableBattlegroundCommand, "" },
+ { "criteria", rbac::RBAC_PERM_COMMAND_DISABLE_REMOVE_CRITERIA, true, &HandleRemoveDisableCriteriaCommand, "" },
+ { "outdoorpvp", rbac::RBAC_PERM_COMMAND_DISABLE_REMOVE_OUTDOORPVP, true, &HandleRemoveDisableOutdoorPvPCommand, "" },
+ { "vmap", rbac::RBAC_PERM_COMMAND_DISABLE_REMOVE_VMAP, true, &HandleRemoveDisableVmapCommand, "" },
+ { "mmap", rbac::RBAC_PERM_COMMAND_DISABLE_REMOVE_MMAP, true, &HandleRemoveDisableMMapCommand, "" },
};
static std::vector<ChatCommand> addDisableCommandTable =
{
- { "spell", rbac::RBAC_PERM_COMMAND_DISABLE_ADD_SPELL, true, &HandleAddDisableSpellCommand, "" },
- { "quest", rbac::RBAC_PERM_COMMAND_DISABLE_ADD_QUEST, true, &HandleAddDisableQuestCommand, "" },
- { "map", rbac::RBAC_PERM_COMMAND_DISABLE_ADD_MAP, true, &HandleAddDisableMapCommand, "" },
- { "battleground", rbac::RBAC_PERM_COMMAND_DISABLE_ADD_BATTLEGROUND, true, &HandleAddDisableBattlegroundCommand, "" },
- { "achievement_criteria", rbac::RBAC_PERM_COMMAND_DISABLE_ADD_ACHIEVEMENT_CRITERIA, true, &HandleAddDisableAchievementCriteriaCommand, "" },
- { "outdoorpvp", rbac::RBAC_PERM_COMMAND_DISABLE_ADD_OUTDOORPVP, true, &HandleAddDisableOutdoorPvPCommand, "" },
- { "vmap", rbac::RBAC_PERM_COMMAND_DISABLE_ADD_VMAP, true, &HandleAddDisableVmapCommand, "" },
- { "mmap", rbac::RBAC_PERM_COMMAND_DISABLE_ADD_MMAP, true, &HandleAddDisableMMapCommand, "" },
+ { "spell", rbac::RBAC_PERM_COMMAND_DISABLE_ADD_SPELL, true, &HandleAddDisableSpellCommand, "" },
+ { "quest", rbac::RBAC_PERM_COMMAND_DISABLE_ADD_QUEST, true, &HandleAddDisableQuestCommand, "" },
+ { "map", rbac::RBAC_PERM_COMMAND_DISABLE_ADD_MAP, true, &HandleAddDisableMapCommand, "" },
+ { "battleground", rbac::RBAC_PERM_COMMAND_DISABLE_ADD_BATTLEGROUND, true, &HandleAddDisableBattlegroundCommand, "" },
+ { "criteria", rbac::RBAC_PERM_COMMAND_DISABLE_ADD_CRITERIA, true, &HandleAddDisableCriteriaCommand, "" },
+ { "outdoorpvp", rbac::RBAC_PERM_COMMAND_DISABLE_ADD_OUTDOORPVP, true, &HandleAddDisableOutdoorPvPCommand, "" },
+ { "vmap", rbac::RBAC_PERM_COMMAND_DISABLE_ADD_VMAP, true, &HandleAddDisableVmapCommand, "" },
+ { "mmap", rbac::RBAC_PERM_COMMAND_DISABLE_ADD_MMAP, true, &HandleAddDisableMMapCommand, "" },
};
static std::vector<ChatCommand> disableCommandTable =
{
@@ -89,7 +89,7 @@ public:
std::string disableComment = commentStr;
uint32 entry = uint32(atoi(entryStr));
- std::string disableTypeStr = "";
+ char const* disableTypeStr = "";
switch (disableType)
{
@@ -137,15 +137,15 @@ public:
disableTypeStr = "battleground";
break;
}
- case DISABLE_TYPE_ACHIEVEMENT_CRITERIA:
+ case DISABLE_TYPE_CRITERIA:
{
- if (!sAchievementMgr->GetAchievementCriteria(entry))
+ if (!sCriteriaMgr->GetCriteria(entry))
{
handler->PSendSysMessage(LANG_COMMAND_NO_ACHIEVEMENT_CRITERIA_FOUND);
handler->SetSentErrorMessage(true);
return false;
}
- disableTypeStr = "achievement criteria";
+ disableTypeStr = "criteria";
break;
}
case DISABLE_TYPE_OUTDOORPVP:
@@ -192,7 +192,7 @@ public:
PreparedQueryResult result = WorldDatabase.Query(stmt);
if (result)
{
- handler->PSendSysMessage("This %s (Id: %u) is already disabled.", disableTypeStr.c_str(), entry);
+ handler->PSendSysMessage("This %s (Id: %u) is already disabled.", disableTypeStr, entry);
handler->SetSentErrorMessage(true);
return false;
}
@@ -204,7 +204,7 @@ public:
stmt->setString(3, disableComment);
WorldDatabase.Execute(stmt);
- handler->PSendSysMessage("Add Disabled %s (Id: %u) for reason %s", disableTypeStr.c_str(), entry, disableComment.c_str());
+ handler->PSendSysMessage("Add Disabled %s (Id: %u) for reason %s", disableTypeStr, entry, disableComment.c_str());
return true;
}
@@ -240,12 +240,12 @@ public:
return HandleAddDisables(handler, args, DISABLE_TYPE_BATTLEGROUND);
}
- static bool HandleAddDisableAchievementCriteriaCommand(ChatHandler* handler, char const* args)
+ static bool HandleAddDisableCriteriaCommand(ChatHandler* handler, char const* args)
{
if (!*args)
return false;
- return HandleAddDisables(handler, args, DISABLE_TYPE_ACHIEVEMENT_CRITERIA);
+ return HandleAddDisables(handler, args, DISABLE_TYPE_CRITERIA);
}
static bool HandleAddDisableOutdoorPvPCommand(ChatHandler* handler, char const* args)
@@ -281,7 +281,7 @@ public:
uint32 entry = uint32(atoi(entryStr));
- std::string disableTypeStr = "";
+ char const* disableTypeStr = "";
switch (disableType)
{
@@ -297,8 +297,8 @@ public:
case DISABLE_TYPE_BATTLEGROUND:
disableTypeStr = "battleground";
break;
- case DISABLE_TYPE_ACHIEVEMENT_CRITERIA:
- disableTypeStr = "achievement criteria";
+ case DISABLE_TYPE_CRITERIA:
+ disableTypeStr = "criteria";
break;
case DISABLE_TYPE_OUTDOORPVP:
disableTypeStr = "outdoorpvp";
@@ -318,7 +318,7 @@ public:
PreparedQueryResult result = WorldDatabase.Query(stmt);
if (!result)
{
- handler->PSendSysMessage("This %s (Id: %u) is not disabled.", disableTypeStr.c_str(), entry);
+ handler->PSendSysMessage("This %s (Id: %u) is not disabled.", disableTypeStr, entry);
handler->SetSentErrorMessage(true);
return false;
}
@@ -328,7 +328,7 @@ public:
stmt->setUInt8(1, disableType);
WorldDatabase.Execute(stmt);
- handler->PSendSysMessage("Remove Disabled %s (Id: %u)", disableTypeStr.c_str(), entry);
+ handler->PSendSysMessage("Remove Disabled %s (Id: %u)", disableTypeStr, entry);
return true;
}
@@ -364,12 +364,12 @@ public:
return HandleRemoveDisables(handler, args, DISABLE_TYPE_BATTLEGROUND);
}
- static bool HandleRemoveDisableAchievementCriteriaCommand(ChatHandler* handler, char const* args)
+ static bool HandleRemoveDisableCriteriaCommand(ChatHandler* handler, char const* args)
{
if (!*args)
return false;
- return HandleRemoveDisables(handler, args, DISABLE_TYPE_ACHIEVEMENT_CRITERIA);
+ return HandleRemoveDisables(handler, args, DISABLE_TYPE_CRITERIA);
}
static bool HandleRemoveDisableOutdoorPvPCommand(ChatHandler* handler, char const* args)
diff --git a/src/server/scripts/Commands/cs_reload.cpp b/src/server/scripts/Commands/cs_reload.cpp
index 4ef4f5807b2..4b185e7d6c5 100644
--- a/src/server/scripts/Commands/cs_reload.cpp
+++ b/src/server/scripts/Commands/cs_reload.cpp
@@ -67,7 +67,6 @@ public:
{
{ "auctions", rbac::RBAC_PERM_COMMAND_RELOAD_AUCTIONS, true, &HandleReloadAuctionsCommand, "" },
{ "access_requirement", rbac::RBAC_PERM_COMMAND_RELOAD_ACCESS_REQUIREMENT, true, &HandleReloadAccessRequirementCommand, "" },
- { "achievement_criteria_data", rbac::RBAC_PERM_COMMAND_RELOAD_ACHIEVEMENT_CRITERIA_DATA, true, &HandleReloadAchievementCriteriaDataCommand, "" },
{ "achievement_reward", rbac::RBAC_PERM_COMMAND_RELOAD_ACHIEVEMENT_REWARD, true, &HandleReloadAchievementRewardCommand, "" },
{ "all", rbac::RBAC_PERM_COMMAND_RELOAD_ALL, true, NULL, "", reloadAllCommandTable },
{ "areatrigger_involvedrelation", rbac::RBAC_PERM_COMMAND_RELOAD_AREATRIGGER_INVOLVEDRELATION, true, &HandleReloadQuestAreaTriggersCommand, "" },
@@ -87,6 +86,7 @@ public:
{ "creature_queststarter", rbac::RBAC_PERM_COMMAND_RELOAD_CREATURE_QUESTSTARTER, true, &HandleReloadCreatureQuestStarterCommand, "" },
{ "creature_summon_groups", rbac::RBAC_PERM_COMMAND_RELOAD_CREATURE_SUMMON_GROUPS, true, &HandleReloadCreatureSummonGroupsCommand, "" },
{ "creature_template", rbac::RBAC_PERM_COMMAND_RELOAD_CREATURE_TEMPLATE, true, &HandleReloadCreatureTemplateCommand, "" },
+ { "criteria_data", rbac::RBAC_PERM_COMMAND_RELOAD_CRITERIA_DATA, true, &HandleReloadCriteriaDataCommand, "" },
{ "disables", rbac::RBAC_PERM_COMMAND_RELOAD_DISABLES, true, &HandleReloadDisablesCommand, "" },
{ "disenchant_loot_template", rbac::RBAC_PERM_COMMAND_RELOAD_DISENCHANT_LOOT_TEMPLATE, true, &HandleReloadLootTemplatesDisenchantCommand, "" },
{ "event_scripts", rbac::RBAC_PERM_COMMAND_RELOAD_EVENT_SCRIPTS, true, &HandleReloadEventScriptsCommand, "" },
@@ -205,7 +205,7 @@ public:
static bool HandleReloadAllAchievementCommand(ChatHandler* handler, const char* /*args*/)
{
- HandleReloadAchievementCriteriaDataCommand(handler, "");
+ HandleReloadCriteriaDataCommand(handler, "");
HandleReloadAchievementRewardCommand(handler, "");
return true;
}
@@ -333,11 +333,11 @@ public:
return true;
}
- static bool HandleReloadAchievementCriteriaDataCommand(ChatHandler* handler, const char* /*args*/)
+ static bool HandleReloadCriteriaDataCommand(ChatHandler* handler, const char* /*args*/)
{
- TC_LOG_INFO("misc", "Re-Loading Additional Achievement Criteria Data...");
- sAchievementMgr->LoadAchievementCriteriaData();
- handler->SendGlobalGMSysMessage("DB table `achievement_criteria_data` reloaded.");
+ TC_LOG_INFO("misc", "Re-Loading Additional Criteria Data...");
+ sCriteriaMgr->LoadCriteriaData();
+ handler->SendGlobalGMSysMessage("DB table `criteria_data` reloaded.");
return true;
}
diff --git a/src/server/scripts/Commands/cs_reset.cpp b/src/server/scripts/Commands/cs_reset.cpp
index a1699a183da..e77893e9de6 100644
--- a/src/server/scripts/Commands/cs_reset.cpp
+++ b/src/server/scripts/Commands/cs_reset.cpp
@@ -64,7 +64,7 @@ public:
if (target)
target->ResetAchievements();
else
- AchievementMgr<Player>::DeleteFromDB(targetGuid);
+ PlayerAchievementMgr::DeleteFromDB(targetGuid);
return true;
}
@@ -77,7 +77,7 @@ public:
target->SetUInt32Value(PLAYER_FIELD_KILLS, 0);
target->SetUInt32Value(PLAYER_FIELD_LIFETIME_HONORABLE_KILLS, 0);
- target->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EARN_HONORABLE_KILL);
+ target->UpdateCriteria(CRITERIA_TYPE_EARN_HONORABLE_KILL);
return true;
}
diff --git a/src/server/scripts/Kalimdor/HallsOfOrigination/boss_anraphet.cpp b/src/server/scripts/Kalimdor/HallsOfOrigination/boss_anraphet.cpp
index 925eb8308aa..a75e23104d7 100644
--- a/src/server/scripts/Kalimdor/HallsOfOrigination/boss_anraphet.cpp
+++ b/src/server/scripts/Kalimdor/HallsOfOrigination/boss_anraphet.cpp
@@ -384,7 +384,7 @@ class npc_brann_bronzebeard_anraphet : public CreatureScript
case EVENT_BRANN_UNLOCK_DOOR:
Talk(BRANN_SAY_UNLOCK_DOOR);
_instance->SetBossState(DATA_VAULT_OF_LIGHTS, DONE);
- _instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_VAULT_OF_LIGHTS_EVENT);
+ _instance->DoStartCriteriaTimer(CRITERIA_TIMED_TYPE_EVENT, ACHIEV_VAULT_OF_LIGHTS_EVENT);
events.ScheduleEvent(EVENT_BRANN_MOVE_INTRO, 3500);
break;
case EVENT_BRANN_THINK:
diff --git a/src/server/scripts/Kalimdor/OnyxiasLair/boss_onyxia.cpp b/src/server/scripts/Kalimdor/OnyxiasLair/boss_onyxia.cpp
index 71ebe870e3d..56157afc9bd 100644
--- a/src/server/scripts/Kalimdor/OnyxiasLair/boss_onyxia.cpp
+++ b/src/server/scripts/Kalimdor/OnyxiasLair/boss_onyxia.cpp
@@ -155,7 +155,7 @@ public:
_Reset();
me->SetReactState(REACT_AGGRESSIVE);
instance->SetData(DATA_ONYXIA_PHASE, Phase);
- instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT);
+ instance->DoStopCriteriaTimer(CRITERIA_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT);
}
void EnterCombat(Unit* /*who*/) override
@@ -166,7 +166,7 @@ public:
events.ScheduleEvent(EVENT_TAIL_SWEEP, urand(15000, 20000));
events.ScheduleEvent(EVENT_CLEAVE, urand(2000, 5000));
events.ScheduleEvent(EVENT_WING_BUFFET, urand(10000, 20000));
- instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT);
+ instance->DoStartCriteriaTimer(CRITERIA_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT);
}
void JustSummoned(Creature* summoned) override
diff --git a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_herald_volazj.cpp b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_herald_volazj.cpp
index f077c433a93..53a061f49cf 100644
--- a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_herald_volazj.cpp
+++ b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_herald_volazj.cpp
@@ -165,7 +165,7 @@ public:
Initialize();
instance->SetBossState(DATA_HERALD_VOLAZJ, NOT_STARTED);
- instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_QUICK_DEMISE_START_EVENT);
+ instance->DoStopCriteriaTimer(CRITERIA_TIMED_TYPE_EVENT, ACHIEV_QUICK_DEMISE_START_EVENT);
// Visible for all players in insanity
me->SetInPhase(169, true, true);
@@ -185,7 +185,7 @@ public:
Talk(SAY_AGGRO);
instance->SetBossState(DATA_HERALD_VOLAZJ, IN_PROGRESS);
- instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_QUICK_DEMISE_START_EVENT);
+ instance->DoStartCriteriaTimer(CRITERIA_TIMED_TYPE_EVENT, ACHIEV_QUICK_DEMISE_START_EVENT);
}
void JustSummoned(Creature* summon) override
diff --git a/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_anubarak.cpp b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_anubarak.cpp
index 16cfb30e2dc..3f4c8fc9d3d 100644
--- a/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_anubarak.cpp
+++ b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_anubarak.cpp
@@ -144,7 +144,7 @@ public:
Summons.DespawnAll();
instance->SetBossState(DATA_ANUBARAK, NOT_STARTED);
- instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT);
+ instance->DoStopCriteriaTimer(CRITERIA_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT);
}
Creature* DoSummonImpaleTarget(Unit* target)
@@ -167,7 +167,7 @@ public:
{
Talk(SAY_AGGRO);
DelayTimer = 0;
- instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT);
+ instance->DoStartCriteriaTimer(CRITERIA_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT);
}
void DelayEventStart()
diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp
index 83bd1c8fbcb..8fbe5e7803d 100644
--- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp
+++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp
@@ -371,7 +371,7 @@ class boss_fjola : public CreatureScript
TouchSpellId = SPELL_LIGHT_TOUCH;
SpikeSpellId = SPELL_LIGHT_TWIN_SPIKE;
- instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, EVENT_START_TWINS_FIGHT);
+ instance->DoStopCriteriaTimer(CRITERIA_TIMED_TYPE_EVENT, EVENT_START_TWINS_FIGHT);
boss_twin_baseAI::Reset();
}
@@ -410,7 +410,7 @@ class boss_fjola : public CreatureScript
void EnterCombat(Unit* who) override
{
- instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, EVENT_START_TWINS_FIGHT);
+ instance->DoStartCriteriaTimer(CRITERIA_TIMED_TYPE_EVENT, EVENT_START_TWINS_FIGHT);
events.ScheduleEvent(EVENT_SPECIAL_ABILITY, 45 * IN_MILLISECONDS);
me->SummonCreature(NPC_BULLET_CONTROLLER, ToCCommonLoc[1].GetPositionX(), ToCCommonLoc[1].GetPositionY(), ToCCommonLoc[1].GetPositionZ(), 0.0f, TEMPSUMMON_MANUAL_DESPAWN);
boss_twin_baseAI::EnterCombat(who);
diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/instance_trial_of_the_crusader.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/instance_trial_of_the_crusader.cpp
index b053d95e1bd..904e07cbc33 100644
--- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/instance_trial_of_the_crusader.cpp
+++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/instance_trial_of_the_crusader.cpp
@@ -238,9 +238,9 @@ class instance_trial_of_the_crusader : public InstanceMapScript
state = IN_PROGRESS;
break;
case DONE:
- DoUpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, SPELL_DEFEAT_FACTION_CHAMPIONS);
+ DoUpdateCriteria(CRITERIA_TYPE_BE_SPELL_TARGET, SPELL_DEFEAT_FACTION_CHAMPIONS);
if (ResilienceWillFixItTimer > 0)
- DoUpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, SPELL_CHAMPIONS_KILLED_IN_MINUTE);
+ DoUpdateCriteria(CRITERIA_TYPE_BE_SPELL_TARGET, SPELL_CHAMPIONS_KILLED_IN_MINUTE);
DoRespawnGameObject(CrusadersCacheGUID, 7*DAY);
if (GameObject* cache = instance->GetGameObject(CrusadersCacheGUID))
cache->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
@@ -408,7 +408,7 @@ class instance_trial_of_the_crusader : public InstanceMapScript
break;
case SNAKES_DONE:
if (NotOneButTwoJormungarsTimer > 0)
- DoUpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, SPELL_WORMS_KILLED_IN_10_SECONDS);
+ DoUpdateCriteria(CRITERIA_TYPE_BE_SPELL_TARGET, SPELL_WORMS_KILLED_IN_10_SECONDS);
EventStage = 300;
SetData(TYPE_NORTHREND_BEASTS, IN_PROGRESS);
break;
diff --git a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp
index 41c79f17dbf..106c567b24e 100644
--- a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp
+++ b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp
@@ -815,7 +815,7 @@ class npc_jaina_or_sylvanas_escape_hor : public CreatureScript
_events.Reset();
_icewall = 0;
_events.ScheduleEvent(EVENT_ESCAPE, 1000);
- _instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_NOT_RETREATING_EVENT);
+ _instance->DoStopCriteriaTimer(CRITERIA_TIMED_TYPE_EVENT, ACHIEV_NOT_RETREATING_EVENT);
}
void JustDied(Unit* /*killer*/) override
@@ -1053,7 +1053,7 @@ class npc_jaina_or_sylvanas_escape_hor : public CreatureScript
}
}
_invincibility = false;
- _instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_NOT_RETREATING_EVENT);
+ _instance->DoStartCriteriaTimer(CRITERIA_TIMED_TYPE_EVENT, ACHIEV_NOT_RETREATING_EVENT);
_events.ScheduleEvent(EVENT_ESCAPE_7, 1000);
break;
case EVENT_ESCAPE_7:
diff --git a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/instance_halls_of_reflection.cpp b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/instance_halls_of_reflection.cpp
index c6570da1132..d78a3ac7ffe 100644
--- a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/instance_halls_of_reflection.cpp
+++ b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/instance_halls_of_reflection.cpp
@@ -349,7 +349,7 @@ class instance_halls_of_reflection : public InstanceMapScript
}
break;
case FAIL:
- DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_NOT_RETREATING_EVENT);
+ DoStopCriteriaTimer(CRITERIA_TIMED_TYPE_EVENT, ACHIEV_NOT_RETREATING_EVENT);
if (Creature* jainaOrSylvanas = instance->GetCreature(JainaOrSylvanasEscapeGUID))
jainaOrSylvanas->DespawnOrUnsummon(10000);
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp
index 745a90fef5e..8764f7ed86c 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp
@@ -322,7 +322,7 @@ class boss_lady_deathwhisper : public CreatureScript
livingAddEntries.insert(unit->GetEntry());
if (livingAddEntries.size() >= 5)
- instance->DoUpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, SPELL_FULL_HOUSE, 0, me);
+ instance->DoUpdateCriteria(CRITERIA_TYPE_BE_SPELL_TARGET, SPELL_FULL_HOUSE, 0, me);
if (Creature* darnavan = ObjectAccessor::GetCreature(*me, _darnavanGUID))
{
diff --git a/src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.cpp b/src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.cpp
index 1b485f588ec..10a1d0b4650 100644
--- a/src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.cpp
+++ b/src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.cpp
@@ -151,7 +151,7 @@ public:
_JustDied();
// start achievement timer (kill Maexna within 20 min)
- instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT);
+ instance->DoStartCriteriaTimer(CRITERIA_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT);
}
void EnterCombat(Unit* /*who*/) override
diff --git a/src/server/scripts/Northrend/Naxxramas/boss_four_horsemen.cpp b/src/server/scripts/Northrend/Naxxramas/boss_four_horsemen.cpp
index 5acd958217c..d655ee17316 100644
--- a/src/server/scripts/Northrend/Naxxramas/boss_four_horsemen.cpp
+++ b/src/server/scripts/Northrend/Naxxramas/boss_four_horsemen.cpp
@@ -286,7 +286,7 @@ struct boss_four_horsemen_baseAI : public BossAI
if (instance->GetBossState(BOSS_HORSEMEN) == DONE)
return;
instance->SetBossState(BOSS_HORSEMEN, DONE);
- //instance->DoUpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, SPELL_ENCOUNTER_CREDIT);
+ //instance->DoUpdateCriteria(CRITERIA_TYPE_BE_SPELL_TARGET, SPELL_ENCOUNTER_CREDIT);
DoCastAOE(SPELL_ENCOUNTER_CREDIT, true);
}
diff --git a/src/server/scripts/Northrend/Naxxramas/boss_patchwerk.cpp b/src/server/scripts/Northrend/Naxxramas/boss_patchwerk.cpp
index adbe5fdbcdc..c360947be3a 100644
--- a/src/server/scripts/Northrend/Naxxramas/boss_patchwerk.cpp
+++ b/src/server/scripts/Northrend/Naxxramas/boss_patchwerk.cpp
@@ -77,7 +77,7 @@ public:
{
_Reset();
- instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_MAKE_QUICK_WERK_OF_HIM_STARTING_EVENT);
+ instance->DoStopCriteriaTimer(CRITERIA_TIMED_TYPE_EVENT, ACHIEV_MAKE_QUICK_WERK_OF_HIM_STARTING_EVENT);
}
void KilledUnit(Unit* /*Victim*/) override
@@ -100,7 +100,7 @@ public:
events.ScheduleEvent(EVENT_HATEFUL, Seconds(1));
events.ScheduleEvent(EVENT_BERSERK, Minutes(6));
- instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_MAKE_QUICK_WERK_OF_HIM_STARTING_EVENT);
+ instance->DoStartCriteriaTimer(CRITERIA_TIMED_TYPE_EVENT, ACHIEV_MAKE_QUICK_WERK_OF_HIM_STARTING_EVENT);
}
void UpdateAI(uint32 diff) override
diff --git a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp
index 1e17aec42f7..6df0380000a 100644
--- a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp
+++ b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp
@@ -383,7 +383,7 @@ public:
SetPhase(PHASE_NOT_STARTED, true);
me->SetReactState(REACT_PASSIVE);
- instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT);
+ instance->DoStopCriteriaTimer(CRITERIA_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT);
}
uint32 GetData(uint32 data) const override
@@ -582,7 +582,7 @@ public:
Talk(SAY_START_P_ONE);
DoCast(SPELL_BERSERK); // periodic aura, first tick in 10 minutes
- instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT);
+ instance->DoStartCriteriaTimer(CRITERIA_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT);
}
void EnterEvadeMode(EvadeReason /*why*/) override
diff --git a/src/server/scripts/Northrend/Nexus/Oculus/boss_drakos.cpp b/src/server/scripts/Northrend/Nexus/Oculus/boss_drakos.cpp
index adc9ff2fbb0..0ee7b2e7649 100644
--- a/src/server/scripts/Northrend/Nexus/Oculus/boss_drakos.cpp
+++ b/src/server/scripts/Northrend/Nexus/Oculus/boss_drakos.cpp
@@ -133,7 +133,7 @@ class boss_drakos : public CreatureScript
Talk(SAY_DEATH);
// start achievement timer (kill Eregos within 20 min)
- instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT);
+ instance->DoStartCriteriaTimer(CRITERIA_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT);
}
void KilledUnit(Unit* /*victim*/) override
diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_loken.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_loken.cpp
index d6c87a4edf8..6e525fb4bb3 100644
--- a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_loken.cpp
+++ b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_loken.cpp
@@ -97,7 +97,7 @@ public:
{
Initialize();
_Reset();
- instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMELY_DEATH_START_EVENT);
+ instance->DoStopCriteriaTimer(CRITERIA_TIMED_TYPE_EVENT, ACHIEV_TIMELY_DEATH_START_EVENT);
}
void EnterCombat(Unit* /*who*/) override
@@ -108,7 +108,7 @@ public:
events.ScheduleEvent(EVENT_ARC_LIGHTNING, 15000);
events.ScheduleEvent(EVENT_LIGHTNING_NOVA, 20000);
events.ScheduleEvent(EVENT_RESUME_PULSING_SHOCKWAVE, 1000);
- instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMELY_DEATH_START_EVENT);
+ instance->DoStartCriteriaTimer(CRITERIA_TIMED_TYPE_EVENT, ACHIEV_TIMELY_DEATH_START_EVENT);
}
void JustDied(Unit* /*killer*/) override
diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_maiden_of_grief.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_maiden_of_grief.cpp
index 2ffe06f0d75..2bf229f2b9d 100644
--- a/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_maiden_of_grief.cpp
+++ b/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_maiden_of_grief.cpp
@@ -67,7 +67,7 @@ class boss_maiden_of_grief : public CreatureScript
events.ScheduleEvent(EVENT_SHOCK_OF_SORROW, urand(20000, 25000));
events.ScheduleEvent(EVENT_PILLAR_OF_WOE, urand(5000, 15000));
- instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_GOOD_GRIEF_START_EVENT);
+ instance->DoStopCriteriaTimer(CRITERIA_TIMED_TYPE_EVENT, ACHIEV_GOOD_GRIEF_START_EVENT);
}
void EnterCombat(Unit* /*who*/) override
@@ -75,7 +75,7 @@ class boss_maiden_of_grief : public CreatureScript
_EnterCombat();
Talk(SAY_AGGRO);
- instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_GOOD_GRIEF_START_EVENT);
+ instance->DoStartCriteriaTimer(CRITERIA_TIMED_TYPE_EVENT, ACHIEV_GOOD_GRIEF_START_EVENT);
}
void KilledUnit(Unit* who) override
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp
index 8f30bfb20ab..0d8f9a6bce1 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp
@@ -773,7 +773,7 @@ class npc_living_constellation : public CreatureScript
me->DespawnOrUnsummon(1);
if (InstanceScript* instance = me->GetInstanceScript())
- instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, EVENT_ID_SUPERMASSIVE_START);
+ instance->DoStartCriteriaTimer(CRITERIA_TIMED_TYPE_EVENT, EVENT_ID_SUPERMASSIVE_START);
caster->CastSpell((Unit*)NULL, SPELL_BLACK_HOLE_CREDIT, TRIGGERED_FULL_MASK);
caster->ToCreature()->DespawnOrUnsummon(1);
}
@@ -1348,7 +1348,7 @@ class spell_algalon_supermassive_fail : public SpellScriptLoader
if (!GetHitPlayer())
return;
- GetHitPlayer()->ResetAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, ACHIEVEMENT_CRITERIA_CONDITION_NO_SPELL_HIT, GetSpellInfo()->Id, true);
+ GetHitPlayer()->ResetCriteria(CRITERIA_TYPE_BE_SPELL_TARGET, CRITERIA_CONDITION_NO_SPELL_HIT, GetSpellInfo()->Id, true);
}
void Register() override
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_ignis.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_ignis.cpp
index cd214a0114f..c55b58367de 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_ignis.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_ignis.cpp
@@ -135,7 +135,7 @@ class boss_ignis : public CreatureScript
if (Vehicle* _vehicle = me->GetVehicleKit())
_vehicle->RemoveAllPassengers();
- instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEVEMENT_IGNIS_START_EVENT);
+ instance->DoStopCriteriaTimer(CRITERIA_TIMED_TYPE_EVENT, ACHIEVEMENT_IGNIS_START_EVENT);
}
void EnterCombat(Unit* /*who*/) override
@@ -149,7 +149,7 @@ class boss_ignis : public CreatureScript
events.ScheduleEvent(EVENT_END_POT, 40000);
events.ScheduleEvent(EVENT_BERSERK, 480000);
Initialize();
- instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEVEMENT_IGNIS_START_EVENT);
+ instance->DoStartCriteriaTimer(CRITERIA_TIMED_TYPE_EVENT, ACHIEVEMENT_IGNIS_START_EVENT);
}
void JustDied(Unit* /*killer*/) override
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_kologarn.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_kologarn.cpp
index 5acfdd8e832..b879498de74 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_kologarn.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_kologarn.cpp
@@ -196,7 +196,7 @@ class boss_kologarn : public CreatureScript
if (!right && !left)
events.ScheduleEvent(EVENT_STONE_SHOUT, 5000);
- instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, CRITERIA_DISARMED);
+ instance->DoStartCriteriaTimer(CRITERIA_TIMED_TYPE_EVENT, CRITERIA_DISARMED);
}
else
{
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_xt002.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_xt002.cpp
index a00e0d885cd..27d05999317 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_xt002.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_xt002.cpp
@@ -220,7 +220,7 @@ class boss_xt002 : public CreatureScript
Initialize();
- instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_MUST_DECONSTRUCT_FASTER);
+ instance->DoStopCriteriaTimer(CRITERIA_TIMED_TYPE_EVENT, ACHIEV_MUST_DECONSTRUCT_FASTER);
}
void EnterCombat(Unit* /*who*/) override
@@ -234,7 +234,7 @@ class boss_xt002 : public CreatureScript
//Tantrum is cast a bit slower the first time.
events.ScheduleEvent(EVENT_TYMPANIC_TANTRUM, urand(TIMER_TYMPANIC_TANTRUM_MIN, TIMER_TYMPANIC_TANTRUM_MAX) * 2);
- instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_MUST_DECONSTRUCT_FASTER);
+ instance->DoStartCriteriaTimer(CRITERIA_TIMED_TYPE_EVENT, ACHIEV_MUST_DECONSTRUCT_FASTER);
}
void DoAction(int32 action) override
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp
index 44dc40a5c1b..086e4fba780 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp
@@ -485,7 +485,7 @@ class boss_voice_of_yogg_saron : public CreatureScript
events.SetPhase(PHASE_ONE);
instance->SetData(DATA_DRIVE_ME_CRAZY, uint32(true));
- instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT);
+ instance->DoStopCriteriaTimer(CRITERIA_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT);
Initialize();
@@ -509,7 +509,7 @@ class boss_voice_of_yogg_saron : public CreatureScript
if (Creature* keeper = ObjectAccessor::GetCreature(*me, instance->GetGuidData(i)))
keeper->SetInCombatWith(me);
- instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT);
+ instance->DoStartCriteriaTimer(CRITERIA_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT);
me->CastCustomSpell(SPELL_SUMMON_GUARDIAN_2, SPELLVALUE_MAX_TARGETS, 1);
DoCast(me, SPELL_SANITY_PERIODIC);
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp
index 7271bd5af52..0897c7e35e8 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp
@@ -660,7 +660,7 @@ class instance_ulduar : public InstanceMapScript
case NPC_GUARDIAN_OF_LIFE:
if (!conSpeedAtory)
{
- DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, CRITERIA_CON_SPEED_ATORY);
+ DoStartCriteriaTimer(CRITERIA_TIMED_TYPE_EVENT, CRITERIA_CON_SPEED_ATORY);
conSpeedAtory = true;
}
break;
@@ -669,7 +669,7 @@ class instance_ulduar : public InstanceMapScript
case NPC_BRIGHTLEAF:
if (!lumberjacked)
{
- DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, CRITERIA_LUMBERJACKED);
+ DoStartCriteriaTimer(CRITERIA_TIMED_TYPE_EVENT, CRITERIA_LUMBERJACKED);
lumberjacked = true;
}
break;
diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp
index 7615217a794..358a287d485 100644
--- a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp
+++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp
@@ -213,7 +213,7 @@ public:
if ((ObjectAccessor::GetCreature(*me, m_uiGraufGUID) == NULL) && !me->IsMounted())
me->SummonCreature(NPC_GRAUF, Location[0].GetPositionX(), Location[0].GetPositionY(), Location[0].GetPositionZ(), 3.0f);
instance->SetBossState(DATA_SKADI_THE_RUTHLESS, NOT_STARTED);
- instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT);
+ instance->DoStopCriteriaTimer(CRITERIA_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT);
}
void JustReachedHome() override
@@ -237,7 +237,7 @@ public:
m_uiSummonTimer = 10000;
me->SetInCombatWithZone();
instance->SetBossState(DATA_SKADI_THE_RUTHLESS, IN_PROGRESS);
- instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT);
+ instance->DoStartCriteriaTimer(CRITERIA_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT);
me->GetMotionMaster()->MoveJump(Location[0], 5.0f, 10.0f);
me->SetWalk(false);
m_uiMountTimer = 1000;
diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist
index 2d253fe974d..f76f5ed9f78 100644
--- a/src/server/worldserver/worldserver.conf.dist
+++ b/src/server/worldserver/worldserver.conf.dist
@@ -3650,7 +3650,6 @@ Logger.sql.sql=5,Console DBErrors
Logger.sql.updates=3,Console Server
Logger.mmaps=3,Server
-#Logger.achievement=3,Console Server
#Logger.addon=3,Console Server
#Logger.ahbot=3,Console Server
#Logger.auctionHouse=3,Console Server
@@ -3663,6 +3662,8 @@ Logger.mmaps=3,Server
#Logger.cheat=3,Console Server
#Logger.commands.ra=3,Console Server
#Logger.condition=3,Console Server
+#Logger.criteria=3,Console Server
+#Logger.criteria.achievement=3,Console Server
#Logger.entities.pet=3,Console Server
#Logger.entities.player.character=3,Console Server
#Logger.entities.player.dump=3,Console Server