aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2016-05-07 01:16:29 +0200
committerShauren <shauren.trinity@gmail.com>2016-05-07 01:16:29 +0200
commitc75fcbe20b07fd7518be58bf02ba30d903133449 (patch)
tree747a9ecc6a91ffc04d394090c0a3d2e588f630b4
parent44962fe3a9551f183ee9003c8947d5f433cfee16 (diff)
Core/Achievements: AchievementMgr refactoring
* Extracted base CriteriaHandler class that deals with criteria only and will be reused for future scenario implementation * Fixed players earning guild achievements
-rw-r--r--sql/base/auth_database.sql4
-rw-r--r--sql/base/characters_database.sql6
-rw-r--r--sql/updates/auth/6.x/2016_05_07_00_auth.sql3
-rw-r--r--sql/updates/characters/6.x/2016_05_07_00_characters.sql2
-rw-r--r--sql/updates/world/6.x/2016_05_07_00_world.sql4
-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
87 files changed, 4024 insertions, 3895 deletions
diff --git a/sql/base/auth_database.sql b/sql/base/auth_database.sql
index 46da3ba1ba6..a7e4b08ff6f 100644
--- a/sql/base/auth_database.sql
+++ b/sql/base/auth_database.sql
@@ -595,7 +595,7 @@ CREATE TABLE `rbac_permissions` (
LOCK TABLES `rbac_permissions` WRITE;
/*!40000 ALTER TABLE `rbac_permissions` DISABLE KEYS */;
-INSERT INTO `rbac_permissions` VALUES (1,'Instant logout'),(2,'Skip Queue'),(3,'Join Normal Battleground'),(4,'Join Random Battleground'),(5,'Join Arenas'),(6,'Join Dungeon Finder'),(10,'Use character templates'),(11,'Log GM trades'),(13,'Skip Instance required bosses check'),(14,'Skip character creation team mask check'),(15,'Skip character creation class mask check'),(16,'Skip character creation race mask check'),(17,'Skip character creation reserved name check'),(18,'Skip character creation heroic min level check'),(19,'Skip needed requirements to use channel check'),(20,'Skip disable map check'),(21,'Skip reset talents when used more than allowed check'),(22,'Skip spam chat check'),(23,'Skip over-speed ping check'),(24,'Two side faction characters on the same account'),(25,'Allow say chat between factions'),(26,'Allow channel chat between factions'),(27,'Two side mail interaction'),(28,'See two side who list'),(29,'Add friends of other faction'),(30,'Save character without delay with .save command'),(31,'Use params with .unstuck command'),(32,'Can be assigned tickets with .assign ticket command'),(33,'Notify if a command was not found'),(34,'Check if should appear in list using .gm ingame command'),(35,'See all security levels with who command'),(36,'Filter whispers'),(37,'Use staff badge in chat'),(38,'Resurrect with full Health Points'),(39,'Restore saved gm setting states'),(40,'Allows to add a gm to friend list'),(41,'Use Config option START_GM_LEVEL to assign new character level'),(42,'Allows to use CMSG_WORLD_TELEPORT opcode'),(43,'Allows to use CMSG_WHOIS opcode'),(44,'Receive global GM messages/texts'),(45,'Join channels without announce'),(46,'Change channel settings without being channel moderator'),(47,'Enables lower security than target check'),(48,'Enable IP, Last Login and EMail output in pinfo'),(49,'Forces to enter the email for confirmation on password change'),(50,'Allow user to check his own email with .account'),(51,'Allow trading between factions'),(192,'Role: Sec Level Administrator'),(193,'Role: Sec Level Gamemaster'),(194,'Role: Sec Level Moderator'),(195,'Role: Sec Level Player'),(196,'Role: Administrator Commands'),(197,'Role: Gamemaster Commands'),(198,'Role: Moderator Commands'),(199,'Role: Player Commands'),(200,'Command: rbac'),(201,'Command: rbac account'),(202,'Command: rbac account list'),(203,'Command: rbac account grant'),(204,'Command: rbac account deny'),(205,'Command: rbac account revoke'),(206,'Command: rbac list'),(207,'Command: battlenetaccount'),(208,'Command: battlenetaccount create'),(209,'Command: battlenetaccount lock country'),(210,'Command: battlenetaccount lock ip'),(211,'Command: battlenetaccount password'),(212,'Command: battlenetaccount set'),(213,'Command: battlenetaccount set password'),(214,'Command: bnetaccount link'),(215,'Command: bnetaccount unlink'),(216,'Command: bnetaccount gameaccountcreate'),(217,'Command: account'),(218,'Command: account addon'),(219,'Command: account create'),(220,'Command: account delete'),(221,'Command: account lock'),(222,'Command: account lock country'),(223,'Command: account lock ip'),(224,'Command: account onlinelist'),(225,'Command: account password'),(226,'Command: account set'),(227,'Command: account set addon'),(228,'Command: account set gmlevel'),(229,'Command: account set password'),(230,'Command: achievement'),(231,'Command: achievement add'),(232,'Command: arena'),(233,'Command: arena captain'),(234,'Command: arena create'),(235,'Command: arena disband'),(236,'Command: arena info'),(237,'Command: arena lookup'),(238,'Command: arena rename'),(239,'Command: ban'),(240,'Command: ban account'),(241,'Command: ban character'),(242,'Command: ban ip'),(243,'Command: ban playeraccount'),(244,'Command: baninfo'),(245,'Command: baninfo account'),(246,'Command: baninfo character'),(247,'Command: baninfo ip'),(248,'Command: banlist'),(249,'Command: banlist account'),(250,'Command: banlist character'),(251,'Command: banlist ip'),(252,'Command: unban'),(253,'Command: unban account'),(254,'Command: unban character'),(255,'Command: unban ip'),(256,'Command: unban playeraccount'),(257,'Command: bf'),(258,'Command: bf start'),(259,'Command: bf stop'),(260,'Command: bf switch'),(261,'Command: bf timer'),(262,'Command: bf enable'),(263,'Command: account email'),(264,'Command: account set sec'),(265,'Command: account set sec email'),(266,'Command: account set sec regmail'),(267,'Command: cast'),(268,'Command: cast back'),(269,'Command: cast dist'),(270,'Command: cast self'),(271,'Command: cast target'),(272,'Command: cast dest'),(273,'Command: character'),(274,'Command: character customize'),(275,'Command: character changefaction'),(276,'Command: character changerace'),(277,'Command: character deleted'),(279,'Command: character deleted list'),(280,'Command: character deleted restore'),(283,'Command: character level'),(284,'Command: character rename'),(285,'Command: character reputation'),(286,'Command: character titles'),(287,'Command: levelup'),(288,'Command: pdump'),(289,'Command: pdump load'),(290,'Command: pdump write'),(291,'Command: cheat'),(292,'Command: cheat casttime'),(293,'Command: cheat cooldown'),(294,'Command: cheat explore'),(295,'Command: cheat god'),(296,'Command: cheat power'),(297,'Command: cheat status'),(298,'Command: cheat taxi'),(299,'Command: cheat waterwalk'),(300,'Command: debug'),(301,'Command: debug anim'),(302,'Command: debug areatriggers'),(303,'Command: debug arena'),(304,'Command: debug bg'),(305,'Command: debug entervehicle'),(306,'Command: debug getitemstate'),(307,'Command: debug getitemvalue'),(308,'Command: debug getvalue'),(309,'Command: debug hostil'),(310,'Command: debug itemexpire'),(311,'Command: debug lootrecipient'),(312,'Command: debug los'),(313,'Command: debug mod32value'),(314,'Command: debug moveflags'),(315,'Command: debug play'),(316,'Command: debug play cinematics'),(317,'Command: debug play movie'),(318,'Command: debug play sound'),(319,'Command: debug send'),(320,'Command: debug send buyerror'),(321,'Command: debug send channelnotify'),(322,'Command: debug send chatmessage'),(323,'Command: debug send equiperror'),(324,'Command: debug send largepacket'),(325,'Command: debug send opcode'),(326,'Command: debug send qinvalidmsg'),(327,'Command: debug send qpartymsg'),(328,'Command: debug send sellerror'),(329,'Command: debug send setphaseshift'),(330,'Command: debug send spellfail'),(331,'Command: debug setaurastate'),(332,'Command: debug setbit'),(333,'Command: debug setitemvalue'),(334,'Command: debug setvalue'),(335,'Command: debug setvid'),(336,'Command: debug spawnvehicle'),(337,'Command: debug threat'),(338,'Command: debug update'),(339,'Command: debug uws'),(340,'Command: wpgps'),(341,'Command: deserter'),(342,'Command: deserter bg'),(343,'Command: deserter bg add'),(344,'Command: deserter bg remove'),(345,'Command: deserter instance'),(346,'Command: deserter instance add'),(347,'Command: deserter instance remove'),(348,'Command: disable'),(349,'Command: disable add'),(350,'Command: disable add achievement_criteria'),(351,'Command: disable add battleground'),(352,'Command: disable add map'),(353,'Command: disable add mmap'),(354,'Command: disable add outdoorpvp'),(355,'Command: disable add quest'),(356,'Command: disable add spell'),(357,'Command: disable add vmap'),(358,'Command: disable remove'),(359,'Command: disable remove achievement_criteria'),(360,'Command: disable remove battleground'),(361,'Command: disable remove map'),(362,'Command: disable remove mmap'),(363,'Command: disable remove outdoorpvp'),(364,'Command: disable remove quest'),(365,'Command: disable remove spell'),(366,'Command: disable remove vmap'),(367,'Command: event'),(368,'Command: event activelist'),(369,'Command: event start'),(370,'Command: event stop'),(371,'Command: gm'),(372,'Command: gm chat'),(373,'Command: gm fly'),(374,'Command: gm ingame'),(375,'Command: gm list'),(376,'Command: gm visible'),(377,'Command: go'),(378,'Command: go creature'),(379,'Command: go graveyard'),(380,'Command: go grid'),(381,'Command: go object'),(382,'Command: go taxinode'),(384,'Command: go trigger'),(385,'Command: go xyz'),(386,'Command: go zonexy'),(387,'Command: gobject'),(388,'Command: gobject activate'),(389,'Command: gobject add'),(390,'Command: gobject add temp'),(391,'Command: gobject delete'),(392,'Command: gobject info'),(393,'Command: gobject move'),(394,'Command: gobject near'),(395,'Command: gobject set'),(396,'Command: gobject set phase'),(397,'Command: gobject set state'),(398,'Command: gobject target'),(399,'Command: gobject turn'),(400,'debug transport'),(401,'Command: guild'),(402,'Command: guild create'),(403,'Command: guild delete'),(404,'Command: guild invite'),(405,'Command: guild uninvite'),(406,'Command: guild rank'),(407,'Command: guild rename'),(408,'Command: honor'),(409,'Command: honor add'),(410,'Command: honor add kill'),(411,'Command: honor update'),(412,'Command: instance'),(413,'Command: instance listbinds'),(414,'Command: instance unbind'),(415,'Command: instance stats'),(416,'Command: instance savedata'),(417,'Command: learn'),(418,'Command: learn all'),(419,'Command: learn all my'),(420,'Command: learn all my class'),(421,'Command: learn all my pettalents'),(422,'Command: learn all my spells'),(423,'Command: learn all my talents'),(424,'Command: learn all gm'),(425,'Command: learn all crafts'),(426,'Command: learn all default'),(427,'Command: learn all lang'),(428,'Command: learn all recipes'),(429,'Command: unlearn'),(430,'Command: lfg'),(431,'Command: lfg player'),(432,'Command: lfg group'),(433,'Command: lfg queue'),(434,'Command: lfg clean'),(435,'Command: lfg options'),(436,'Command: list'),(437,'Command: list creature'),(438,'Command: list item'),(439,'Command: list object'),(440,'Command: list auras'),(441,'Command: list mail'),(442,'Command: lookup'),(443,'Command: lookup area'),(444,'Command: lookup creature'),(445,'Command: lookup event'),(446,'Command: lookup faction'),(447,'Command: lookup item'),(448,'Command: lookup itemset'),(449,'Command: lookup object'),(450,'Command: lookup quest'),(451,'Command: lookup player'),(452,'Command: lookup player ip'),(453,'Command: lookup player account'),(454,'Command: lookup player email'),(455,'Command: lookup skill'),(456,'Command: lookup spell'),(457,'Command: lookup spell id'),(458,'Command: lookup taxinode'),(459,'Command: lookup tele'),(460,'Command: lookup title'),(461,'Command: lookup map'),(462,'Command: announce'),(463,'Command: channel'),(464,'Command: channel set'),(465,'Command: channel set ownership'),(466,'Command: gmannounce'),(467,'Command: gmnameannounce'),(468,'Command: gmnotify'),(469,'Command: nameannounce'),(470,'Command: notify'),(471,'Command: whispers'),(472,'Command: group'),(473,'Command: group leader'),(474,'Command: group disband'),(475,'Command: group remove'),(476,'Command: group join'),(477,'Command: group list'),(478,'Command: group summon'),(479,'Command: pet'),(480,'Command: pet create'),(481,'Command: pet learn'),(482,'Command: pet unlearn'),(483,'Command: send'),(484,'Command: send items'),(485,'Command: send mail'),(486,'Command: send message'),(487,'Command: send money'),(488,'Command: additem'),(489,'Command: additemset'),(490,'Command: appear'),(491,'Command: aura'),(492,'Command: bank'),(493,'Command: bindsight'),(494,'Command: combatstop'),(495,'Command: cometome'),(496,'Command: commands'),(497,'Command: cooldown'),(498,'Command: damage'),(499,'Command: dev'),(500,'Command: die'),(501,'Command: dismount'),(502,'Command: distance'),(503,'Command: flusharenapoints'),(504,'Command: freeze'),(505,'Command: gps'),(506,'Command: guid'),(507,'Command: help'),(508,'Command: hidearea'),(509,'Command: itemmove'),(510,'Command: kick'),(511,'Command: linkgrave'),(512,'Command: listfreeze'),(513,'Command: maxskill'),(514,'Command: movegens'),(515,'Command: mute'),(516,'Command: neargrave'),(517,'Command: pinfo'),(518,'Command: playall'),(519,'Command: possess'),(520,'Command: recall'),(521,'Command: repairitems'),(522,'Command: respawn'),(523,'Command: revive'),(524,'Command: saveall'),(525,'Command: save'),(526,'Command: setskill'),(527,'Command: showarea'),(528,'Command: summon'),(529,'Command: unaura'),(530,'Command: unbindsight'),(531,'Command: unfreeze'),(532,'Command: unmute'),(533,'Command: unpossess'),(534,'Command: unstuck'),(535,'Command: wchange'),(536,'Command: mmap'),(537,'Command: mmap loadedtiles'),(538,'Command: mmap loc'),(539,'Command: mmap path'),(540,'Command: mmap stats'),(541,'Command: mmap testarea'),(542,'Command: morph'),(543,'Command: demorph'),(544,'Command: modify'),(545,'Command: modify arenapoints'),(546,'Command: modify bit'),(547,'Command: modify drunk'),(548,'Command: modify energy'),(549,'Command: modify faction'),(550,'Command: modify gender'),(551,'Command: modify honor'),(552,'Command: modify hp'),(553,'Command: modify mana'),(554,'Command: modify money'),(555,'Command: modify mount'),(556,'Command: modify phase'),(557,'Command: modify rage'),(558,'Command: modify reputation'),(559,'Command: modify runicpower'),(560,'Command: modify scale'),(561,'Command: modify speed'),(562,'Command: modify speed all'),(563,'Command: modify speed backwalk'),(564,'Command: modify speed fly'),(565,'Command: modify speed walk'),(566,'Command: modify speed swim'),(567,'Command: modify spell'),(568,'Command: modify standstate'),(569,'Command: modify talentpoints'),(570,'Command: npc'),(571,'Command: npc add'),(572,'Command: npc add formation'),(573,'Command: npc add item'),(574,'Command: npc add move'),(575,'Command: npc add temp'),(576,'Command: npc add delete'),(577,'Command: npc add delete item'),(578,'Command: npc add follow'),(579,'Command: npc add follow stop'),(580,'Command: npc set'),(581,'Command: npc set allowmove'),(582,'Command: npc set entry'),(583,'Command: npc set factionid'),(584,'Command: npc set flag'),(585,'Command: npc set level'),(586,'Command: npc set link'),(587,'Command: npc set model'),(588,'Command: npc set movetype'),(589,'Command: npc set phase'),(590,'Command: npc set spawndist'),(591,'Command: npc set spawntime'),(592,'Command: npc set data'),(593,'Command: npc info'),(594,'Command: npc near'),(595,'Command: npc move'),(596,'Command: npc playemote'),(597,'Command: npc say'),(598,'Command: npc textemote'),(599,'Command: npc whisper'),(600,'Command: npc yell'),(601,'Command: npc tame'),(602,'Command: quest'),(603,'Command: quest add'),(604,'Command: quest complete'),(605,'Command: quest remove'),(606,'Command: quest reward'),(607,'Command: reload'),(608,'Command: reload access_requirement'),(609,'Command: reload achievement_criteria_data'),(610,'Command: reload achievement_reward'),(611,'Command: reload all'),(612,'Command: reload all achievement'),(613,'Command: reload all area'),(615,'Command: reload all gossips'),(616,'Command: reload all item'),(617,'Command: reload all locales'),(618,'Command: reload all loot'),(619,'Command: reload all npc'),(620,'Command: reload all quest'),(621,'Command: reload all scripts'),(623,'Command: reload areatrigger_involvedrelation'),(624,'Command: reload areatrigger_tavern'),(625,'Command: reload areatrigger_teleport'),(626,'Command: reload auctions'),(627,'Command: reload autobroadcast'),(628,'Command: reload command'),(629,'Command: reload conditions'),(630,'Command: reload config'),(631,'Command: reload battleground_template'),(632,'Command: .mutehistory'),(633,'Command: reload creature_linked_respawn'),(634,'Command: reload creature_loot_template'),(635,'Command: reload creature_onkill_reputation'),(636,'Command: reload creature_questender'),(637,'Command: reload creature_queststarter'),(638,'Command: reload creature_summon_groups'),(639,'Command: reload creature_template'),(640,'Command: reload creature_text'),(641,'Command: reload disables'),(642,'Command: reload disenchant_loot_template'),(643,'Command: reload event_scripts'),(644,'Command: reload fishing_loot_template'),(645,'Command: reload game_graveyard_zone'),(646,'Command: reload game_tele'),(647,'Command: reload gameobject_questender'),(648,'Command: reload gameobject_loot_template'),(649,'Command: reload gameobject_queststarter'),(650,'Command: reload support'),(651,'Command: reload gossip_menu'),(652,'Command: reload gossip_menu_option'),(653,'Command: reload item_enchantment_template'),(654,'Command: reload item_loot_template'),(655,'Command: reload item_set_names'),(656,'Command: reload lfg_dungeon_rewards'),(657,'Command: reload locales_achievement_reward'),(658,'Command: reload locales_creature'),(659,'Command: reload locales_creature_text'),(660,'Command: reload locales_gameobject'),(661,'Command: reload locales_gossip_menu_option'),(662,'Command: reload character_template'),(663,'Command: reload locales_item_set_name'),(664,'Command: reload quest_greeting'),(665,'Command: reload locales_page_text'),(666,'Command: reload locales_points_of_interest'),(667,'Command: reload quest_locale'),(668,'Command: reload mail_level_reward'),(669,'Command: reload mail_loot_template'),(670,'Command: reload milling_loot_template'),(671,'Command: reload npc_spellclick_spells'),(672,'Command: reload npc_trainer'),(673,'Command: reload npc_vendor'),(674,'Command: reload page_text'),(675,'Command: reload pickpocketing_loot_template'),(676,'Command: reload points_of_interest'),(677,'Command: reload prospecting_loot_template'),(678,'Command: reload quest_poi'),(679,'Command: reload quest_template'),(680,'Command: reload rbac'),(681,'Command: reload reference_loot_template'),(682,'Command: reload reserved_name'),(683,'Command: reload reputation_reward_rate'),(684,'Command: reload reputation_spillover_template'),(685,'Command: reload skill_discovery_template'),(686,'Command: reload skill_extra_item_template'),(687,'Command: reload skill_fishing_base_level'),(688,'Command: reload skinning_loot_template'),(689,'Command: reload smart_scripts'),(690,'Command: reload spell_required'),(691,'Command: reload spell_area'),(692,'Command: debug send playscene'),(693,'Command: reload spell_group'),(694,'Command: reload spell_learn_spell'),(695,'Command: reload spell_loot_template'),(696,'Command: reload spell_linked_spell'),(697,'Command: reload spell_pet_auras'),(698,'Command: reload spell_proc_event'),(699,'Command: reload spell_proc'),(700,'Command: reload spell_scripts'),(701,'Command: reload spell_target_position'),(702,'Command: reload spell_threats'),(703,'Command: reload spell_group_stack_rules'),(704,'Command: reload trinity_string'),(705,'Command: reload warden_action'),(706,'Command: reload waypoint_scripts'),(707,'Command: reload waypoint_data'),(708,'Command: reload vehicle_accessory'),(709,'Command: reload vehicle_template_accessory'),(710,'Command: reset'),(711,'Command: reset achievements'),(712,'Command: reset honor'),(713,'Command: reset level'),(714,'Command: reset spells'),(715,'Command: reset stats'),(716,'Command: reset talents'),(717,'Command: reset all'),(718,'Command: server'),(719,'Command: server corpses'),(720,'Command: server exit'),(721,'Command: server idlerestart'),(722,'Command: server idlerestart cancel'),(723,'Command: server idleshutdown'),(724,'Command: server idleshutdown cancel'),(725,'Command: server info'),(726,'Command: server plimit'),(727,'Command: server restart'),(728,'Command: server restart cancel'),(729,'Command: server set'),(730,'Command: server set closed'),(731,'Command: server set difftime'),(732,'Command: server set loglevel'),(733,'Command: server set motd'),(734,'Command: server shutdown'),(735,'Command: server shutdown cancel'),(736,'Command: server motd'),(737,'Command: tele'),(738,'Command: tele add'),(739,'Command: tele del'),(740,'Command: tele name'),(741,'Command: tele group'),(742,'Command: ticket'),(753,'Command: ticket reset'),(757,'Command: ticket togglesystem'),(761,'Command: titles'),(762,'Command: titles add'),(763,'Command: titles current'),(764,'Command: titles remove'),(765,'Command: titles set'),(766,'Command: titles set mask'),(767,'Command: wp'),(768,'Command: wp add'),(769,'Command: wp event'),(770,'Command: wp load'),(771,'Command: wp modify'),(772,'Command: wp unload'),(773,'Command: wp reload'),(774,'Command: wp show'),(776,'Command: debug phase'),(777,'Command: mailbox'),(778,'Command: ahbot'),(779,'Command: ahbot items'),(780,'Command: ahbot items gray'),(781,'Command: ahbot items white'),(782,'Command: ahbot items green'),(783,'Command: ahbot items blue'),(784,'Command: ahbot items purple'),(785,'Command: ahbot items orange'),(786,'Command: ahbot items yellow'),(787,'Command: ahbot ratio'),(788,'Command: ahbot ratio alliance'),(789,'Command: ahbot ratio horde'),(790,'Command: ahbot ratio neutral'),(791,'Command: ahbot rebuild'),(792,'Command: ahbot reload'),(793,'Command: ahbot status'),(794,'Command: .guild info'),(797,'Command: pvpstats'),(798,'Command: .mod xp'),(799,'Command: .go bugticket'),(800,'Command: .go complaintticket'),(801,'Command: .go suggestionticket'),(802,'Command: .ticket bug'),(803,'Command: .ticket complaint'),(804,'Command: .ticket suggestion'),(805,'Command: .ticket bug assign'),(806,'Command: .ticket bug close'),(807,'Command: .ticket bug closedlist'),(808,'Command: .ticket bug comment'),(809,'Command: .ticket bug delete'),(810,'Command: .ticket bug list'),(811,'Command: .ticket bug unassign'),(812,'Command: .ticket bug view'),(813,'Command: .ticket complaint assign'),(814,'Command: .ticket complaint close'),(815,'Command: .ticket complaint closedlist'),(816,'Command: .ticket complaint comment'),(817,'Command: .ticket complaint delete'),(818,'Command: .ticket complaint list'),(819,'Command: .ticket complaint unassign'),(820,'Command: .ticket complaint view'),(821,'Command: .ticket suggestion assign'),(822,'Command: .ticket suggestion close'),(823,'Command: .ticket suggestion closedlist'),(824,'Command: .ticket suggestion comment'),(825,'Command: .ticket suggestion delete'),(826,'Command: .ticket suggestion list'),(827,'Command: .ticket suggestion unassign'),(828,'Command: .ticket suggestion view'),(829,'Command: .ticket reset all'),(831,'Command: .ticket reset bug'),(832,'Command: .ticket reset complaint'),(833,'Command: .ticket reset suggestion'),(834,'Command: go quest'),(835,'Command: debug loadcells'),(836,'Command: .debug boundary');
+INSERT INTO `rbac_permissions` VALUES (1,'Instant logout'),(2,'Skip Queue'),(3,'Join Normal Battleground'),(4,'Join Random Battleground'),(5,'Join Arenas'),(6,'Join Dungeon Finder'),(10,'Use character templates'),(11,'Log GM trades'),(13,'Skip Instance required bosses check'),(14,'Skip character creation team mask check'),(15,'Skip character creation class mask check'),(16,'Skip character creation race mask check'),(17,'Skip character creation reserved name check'),(18,'Skip character creation heroic min level check'),(19,'Skip needed requirements to use channel check'),(20,'Skip disable map check'),(21,'Skip reset talents when used more than allowed check'),(22,'Skip spam chat check'),(23,'Skip over-speed ping check'),(24,'Two side faction characters on the same account'),(25,'Allow say chat between factions'),(26,'Allow channel chat between factions'),(27,'Two side mail interaction'),(28,'See two side who list'),(29,'Add friends of other faction'),(30,'Save character without delay with .save command'),(31,'Use params with .unstuck command'),(32,'Can be assigned tickets with .assign ticket command'),(33,'Notify if a command was not found'),(34,'Check if should appear in list using .gm ingame command'),(35,'See all security levels with who command'),(36,'Filter whispers'),(37,'Use staff badge in chat'),(38,'Resurrect with full Health Points'),(39,'Restore saved gm setting states'),(40,'Allows to add a gm to friend list'),(41,'Use Config option START_GM_LEVEL to assign new character level'),(42,'Allows to use CMSG_WORLD_TELEPORT opcode'),(43,'Allows to use CMSG_WHOIS opcode'),(44,'Receive global GM messages/texts'),(45,'Join channels without announce'),(46,'Change channel settings without being channel moderator'),(47,'Enables lower security than target check'),(48,'Enable IP, Last Login and EMail output in pinfo'),(49,'Forces to enter the email for confirmation on password change'),(50,'Allow user to check his own email with .account'),(51,'Allow trading between factions'),(192,'Role: Sec Level Administrator'),(193,'Role: Sec Level Gamemaster'),(194,'Role: Sec Level Moderator'),(195,'Role: Sec Level Player'),(196,'Role: Administrator Commands'),(197,'Role: Gamemaster Commands'),(198,'Role: Moderator Commands'),(199,'Role: Player Commands'),(200,'Command: rbac'),(201,'Command: rbac account'),(202,'Command: rbac account list'),(203,'Command: rbac account grant'),(204,'Command: rbac account deny'),(205,'Command: rbac account revoke'),(206,'Command: rbac list'),(207,'Command: battlenetaccount'),(208,'Command: battlenetaccount create'),(209,'Command: battlenetaccount lock country'),(210,'Command: battlenetaccount lock ip'),(211,'Command: battlenetaccount password'),(212,'Command: battlenetaccount set'),(213,'Command: battlenetaccount set password'),(214,'Command: bnetaccount link'),(215,'Command: bnetaccount unlink'),(216,'Command: bnetaccount gameaccountcreate'),(217,'Command: account'),(218,'Command: account addon'),(219,'Command: account create'),(220,'Command: account delete'),(221,'Command: account lock'),(222,'Command: account lock country'),(223,'Command: account lock ip'),(224,'Command: account onlinelist'),(225,'Command: account password'),(226,'Command: account set'),(227,'Command: account set addon'),(228,'Command: account set gmlevel'),(229,'Command: account set password'),(230,'Command: achievement'),(231,'Command: achievement add'),(232,'Command: arena'),(233,'Command: arena captain'),(234,'Command: arena create'),(235,'Command: arena disband'),(236,'Command: arena info'),(237,'Command: arena lookup'),(238,'Command: arena rename'),(239,'Command: ban'),(240,'Command: ban account'),(241,'Command: ban character'),(242,'Command: ban ip'),(243,'Command: ban playeraccount'),(244,'Command: baninfo'),(245,'Command: baninfo account'),(246,'Command: baninfo character'),(247,'Command: baninfo ip'),(248,'Command: banlist'),(249,'Command: banlist account'),(250,'Command: banlist character'),(251,'Command: banlist ip'),(252,'Command: unban'),(253,'Command: unban account'),(254,'Command: unban character'),(255,'Command: unban ip'),(256,'Command: unban playeraccount'),(257,'Command: bf'),(258,'Command: bf start'),(259,'Command: bf stop'),(260,'Command: bf switch'),(261,'Command: bf timer'),(262,'Command: bf enable'),(263,'Command: account email'),(264,'Command: account set sec'),(265,'Command: account set sec email'),(266,'Command: account set sec regmail'),(267,'Command: cast'),(268,'Command: cast back'),(269,'Command: cast dist'),(270,'Command: cast self'),(271,'Command: cast target'),(272,'Command: cast dest'),(273,'Command: character'),(274,'Command: character customize'),(275,'Command: character changefaction'),(276,'Command: character changerace'),(277,'Command: character deleted'),(279,'Command: character deleted list'),(280,'Command: character deleted restore'),(283,'Command: character level'),(284,'Command: character rename'),(285,'Command: character reputation'),(286,'Command: character titles'),(287,'Command: levelup'),(288,'Command: pdump'),(289,'Command: pdump load'),(290,'Command: pdump write'),(291,'Command: cheat'),(292,'Command: cheat casttime'),(293,'Command: cheat cooldown'),(294,'Command: cheat explore'),(295,'Command: cheat god'),(296,'Command: cheat power'),(297,'Command: cheat status'),(298,'Command: cheat taxi'),(299,'Command: cheat waterwalk'),(300,'Command: debug'),(301,'Command: debug anim'),(302,'Command: debug areatriggers'),(303,'Command: debug arena'),(304,'Command: debug bg'),(305,'Command: debug entervehicle'),(306,'Command: debug getitemstate'),(307,'Command: debug getitemvalue'),(308,'Command: debug getvalue'),(309,'Command: debug hostil'),(310,'Command: debug itemexpire'),(311,'Command: debug lootrecipient'),(312,'Command: debug los'),(313,'Command: debug mod32value'),(314,'Command: debug moveflags'),(315,'Command: debug play'),(316,'Command: debug play cinematics'),(317,'Command: debug play movie'),(318,'Command: debug play sound'),(319,'Command: debug send'),(320,'Command: debug send buyerror'),(321,'Command: debug send channelnotify'),(322,'Command: debug send chatmessage'),(323,'Command: debug send equiperror'),(324,'Command: debug send largepacket'),(325,'Command: debug send opcode'),(326,'Command: debug send qinvalidmsg'),(327,'Command: debug send qpartymsg'),(328,'Command: debug send sellerror'),(329,'Command: debug send setphaseshift'),(330,'Command: debug send spellfail'),(331,'Command: debug setaurastate'),(332,'Command: debug setbit'),(333,'Command: debug setitemvalue'),(334,'Command: debug setvalue'),(335,'Command: debug setvid'),(336,'Command: debug spawnvehicle'),(337,'Command: debug threat'),(338,'Command: debug update'),(339,'Command: debug uws'),(340,'Command: wpgps'),(341,'Command: deserter'),(342,'Command: deserter bg'),(343,'Command: deserter bg add'),(344,'Command: deserter bg remove'),(345,'Command: deserter instance'),(346,'Command: deserter instance add'),(347,'Command: deserter instance remove'),(348,'Command: disable'),(349,'Command: disable add'),(350,'Command: disable add criteria'),(351,'Command: disable add battleground'),(352,'Command: disable add map'),(353,'Command: disable add mmap'),(354,'Command: disable add outdoorpvp'),(355,'Command: disable add quest'),(356,'Command: disable add spell'),(357,'Command: disable add vmap'),(358,'Command: disable remove'),(359,'Command: disable remove criteria'),(360,'Command: disable remove battleground'),(361,'Command: disable remove map'),(362,'Command: disable remove mmap'),(363,'Command: disable remove outdoorpvp'),(364,'Command: disable remove quest'),(365,'Command: disable remove spell'),(366,'Command: disable remove vmap'),(367,'Command: event'),(368,'Command: event activelist'),(369,'Command: event start'),(370,'Command: event stop'),(371,'Command: gm'),(372,'Command: gm chat'),(373,'Command: gm fly'),(374,'Command: gm ingame'),(375,'Command: gm list'),(376,'Command: gm visible'),(377,'Command: go'),(378,'Command: go creature'),(379,'Command: go graveyard'),(380,'Command: go grid'),(381,'Command: go object'),(382,'Command: go taxinode'),(384,'Command: go trigger'),(385,'Command: go xyz'),(386,'Command: go zonexy'),(387,'Command: gobject'),(388,'Command: gobject activate'),(389,'Command: gobject add'),(390,'Command: gobject add temp'),(391,'Command: gobject delete'),(392,'Command: gobject info'),(393,'Command: gobject move'),(394,'Command: gobject near'),(395,'Command: gobject set'),(396,'Command: gobject set phase'),(397,'Command: gobject set state'),(398,'Command: gobject target'),(399,'Command: gobject turn'),(400,'debug transport'),(401,'Command: guild'),(402,'Command: guild create'),(403,'Command: guild delete'),(404,'Command: guild invite'),(405,'Command: guild uninvite'),(406,'Command: guild rank'),(407,'Command: guild rename'),(408,'Command: honor'),(409,'Command: honor add'),(410,'Command: honor add kill'),(411,'Command: honor update'),(412,'Command: instance'),(413,'Command: instance listbinds'),(414,'Command: instance unbind'),(415,'Command: instance stats'),(416,'Command: instance savedata'),(417,'Command: learn'),(418,'Command: learn all'),(419,'Command: learn all my'),(420,'Command: learn all my class'),(421,'Command: learn all my pettalents'),(422,'Command: learn all my spells'),(423,'Command: learn all my talents'),(424,'Command: learn all gm'),(425,'Command: learn all crafts'),(426,'Command: learn all default'),(427,'Command: learn all lang'),(428,'Command: learn all recipes'),(429,'Command: unlearn'),(430,'Command: lfg'),(431,'Command: lfg player'),(432,'Command: lfg group'),(433,'Command: lfg queue'),(434,'Command: lfg clean'),(435,'Command: lfg options'),(436,'Command: list'),(437,'Command: list creature'),(438,'Command: list item'),(439,'Command: list object'),(440,'Command: list auras'),(441,'Command: list mail'),(442,'Command: lookup'),(443,'Command: lookup area'),(444,'Command: lookup creature'),(445,'Command: lookup event'),(446,'Command: lookup faction'),(447,'Command: lookup item'),(448,'Command: lookup itemset'),(449,'Command: lookup object'),(450,'Command: lookup quest'),(451,'Command: lookup player'),(452,'Command: lookup player ip'),(453,'Command: lookup player account'),(454,'Command: lookup player email'),(455,'Command: lookup skill'),(456,'Command: lookup spell'),(457,'Command: lookup spell id'),(458,'Command: lookup taxinode'),(459,'Command: lookup tele'),(460,'Command: lookup title'),(461,'Command: lookup map'),(462,'Command: announce'),(463,'Command: channel'),(464,'Command: channel set'),(465,'Command: channel set ownership'),(466,'Command: gmannounce'),(467,'Command: gmnameannounce'),(468,'Command: gmnotify'),(469,'Command: nameannounce'),(470,'Command: notify'),(471,'Command: whispers'),(472,'Command: group'),(473,'Command: group leader'),(474,'Command: group disband'),(475,'Command: group remove'),(476,'Command: group join'),(477,'Command: group list'),(478,'Command: group summon'),(479,'Command: pet'),(480,'Command: pet create'),(481,'Command: pet learn'),(482,'Command: pet unlearn'),(483,'Command: send'),(484,'Command: send items'),(485,'Command: send mail'),(486,'Command: send message'),(487,'Command: send money'),(488,'Command: additem'),(489,'Command: additemset'),(490,'Command: appear'),(491,'Command: aura'),(492,'Command: bank'),(493,'Command: bindsight'),(494,'Command: combatstop'),(495,'Command: cometome'),(496,'Command: commands'),(497,'Command: cooldown'),(498,'Command: damage'),(499,'Command: dev'),(500,'Command: die'),(501,'Command: dismount'),(502,'Command: distance'),(503,'Command: flusharenapoints'),(504,'Command: freeze'),(505,'Command: gps'),(506,'Command: guid'),(507,'Command: help'),(508,'Command: hidearea'),(509,'Command: itemmove'),(510,'Command: kick'),(511,'Command: linkgrave'),(512,'Command: listfreeze'),(513,'Command: maxskill'),(514,'Command: movegens'),(515,'Command: mute'),(516,'Command: neargrave'),(517,'Command: pinfo'),(518,'Command: playall'),(519,'Command: possess'),(520,'Command: recall'),(521,'Command: repairitems'),(522,'Command: respawn'),(523,'Command: revive'),(524,'Command: saveall'),(525,'Command: save'),(526,'Command: setskill'),(527,'Command: showarea'),(528,'Command: summon'),(529,'Command: unaura'),(530,'Command: unbindsight'),(531,'Command: unfreeze'),(532,'Command: unmute'),(533,'Command: unpossess'),(534,'Command: unstuck'),(535,'Command: wchange'),(536,'Command: mmap'),(537,'Command: mmap loadedtiles'),(538,'Command: mmap loc'),(539,'Command: mmap path'),(540,'Command: mmap stats'),(541,'Command: mmap testarea'),(542,'Command: morph'),(543,'Command: demorph'),(544,'Command: modify'),(545,'Command: modify arenapoints'),(546,'Command: modify bit'),(547,'Command: modify drunk'),(548,'Command: modify energy'),(549,'Command: modify faction'),(550,'Command: modify gender'),(551,'Command: modify honor'),(552,'Command: modify hp'),(553,'Command: modify mana'),(554,'Command: modify money'),(555,'Command: modify mount'),(556,'Command: modify phase'),(557,'Command: modify rage'),(558,'Command: modify reputation'),(559,'Command: modify runicpower'),(560,'Command: modify scale'),(561,'Command: modify speed'),(562,'Command: modify speed all'),(563,'Command: modify speed backwalk'),(564,'Command: modify speed fly'),(565,'Command: modify speed walk'),(566,'Command: modify speed swim'),(567,'Command: modify spell'),(568,'Command: modify standstate'),(569,'Command: modify talentpoints'),(570,'Command: npc'),(571,'Command: npc add'),(572,'Command: npc add formation'),(573,'Command: npc add item'),(574,'Command: npc add move'),(575,'Command: npc add temp'),(576,'Command: npc add delete'),(577,'Command: npc add delete item'),(578,'Command: npc add follow'),(579,'Command: npc add follow stop'),(580,'Command: npc set'),(581,'Command: npc set allowmove'),(582,'Command: npc set entry'),(583,'Command: npc set factionid'),(584,'Command: npc set flag'),(585,'Command: npc set level'),(586,'Command: npc set link'),(587,'Command: npc set model'),(588,'Command: npc set movetype'),(589,'Command: npc set phase'),(590,'Command: npc set spawndist'),(591,'Command: npc set spawntime'),(592,'Command: npc set data'),(593,'Command: npc info'),(594,'Command: npc near'),(595,'Command: npc move'),(596,'Command: npc playemote'),(597,'Command: npc say'),(598,'Command: npc textemote'),(599,'Command: npc whisper'),(600,'Command: npc yell'),(601,'Command: npc tame'),(602,'Command: quest'),(603,'Command: quest add'),(604,'Command: quest complete'),(605,'Command: quest remove'),(606,'Command: quest reward'),(607,'Command: reload'),(608,'Command: reload access_requirement'),(609,'Command: reload criteria_data'),(610,'Command: reload achievement_reward'),(611,'Command: reload all'),(612,'Command: reload all achievement'),(613,'Command: reload all area'),(615,'Command: reload all gossips'),(616,'Command: reload all item'),(617,'Command: reload all locales'),(618,'Command: reload all loot'),(619,'Command: reload all npc'),(620,'Command: reload all quest'),(621,'Command: reload all scripts'),(623,'Command: reload areatrigger_involvedrelation'),(624,'Command: reload areatrigger_tavern'),(625,'Command: reload areatrigger_teleport'),(626,'Command: reload auctions'),(627,'Command: reload autobroadcast'),(628,'Command: reload command'),(629,'Command: reload conditions'),(630,'Command: reload config'),(631,'Command: reload battleground_template'),(632,'Command: .mutehistory'),(633,'Command: reload creature_linked_respawn'),(634,'Command: reload creature_loot_template'),(635,'Command: reload creature_onkill_reputation'),(636,'Command: reload creature_questender'),(637,'Command: reload creature_queststarter'),(638,'Command: reload creature_summon_groups'),(639,'Command: reload creature_template'),(640,'Command: reload creature_text'),(641,'Command: reload disables'),(642,'Command: reload disenchant_loot_template'),(643,'Command: reload event_scripts'),(644,'Command: reload fishing_loot_template'),(645,'Command: reload game_graveyard_zone'),(646,'Command: reload game_tele'),(647,'Command: reload gameobject_questender'),(648,'Command: reload gameobject_loot_template'),(649,'Command: reload gameobject_queststarter'),(650,'Command: reload support'),(651,'Command: reload gossip_menu'),(652,'Command: reload gossip_menu_option'),(653,'Command: reload item_enchantment_template'),(654,'Command: reload item_loot_template'),(655,'Command: reload item_set_names'),(656,'Command: reload lfg_dungeon_rewards'),(657,'Command: reload locales_achievement_reward'),(658,'Command: reload locales_creature'),(659,'Command: reload locales_creature_text'),(660,'Command: reload locales_gameobject'),(661,'Command: reload locales_gossip_menu_option'),(662,'Command: reload character_template'),(663,'Command: reload locales_item_set_name'),(664,'Command: reload quest_greeting'),(665,'Command: reload locales_page_text'),(666,'Command: reload locales_points_of_interest'),(667,'Command: reload quest_locale'),(668,'Command: reload mail_level_reward'),(669,'Command: reload mail_loot_template'),(670,'Command: reload milling_loot_template'),(671,'Command: reload npc_spellclick_spells'),(672,'Command: reload npc_trainer'),(673,'Command: reload npc_vendor'),(674,'Command: reload page_text'),(675,'Command: reload pickpocketing_loot_template'),(676,'Command: reload points_of_interest'),(677,'Command: reload prospecting_loot_template'),(678,'Command: reload quest_poi'),(679,'Command: reload quest_template'),(680,'Command: reload rbac'),(681,'Command: reload reference_loot_template'),(682,'Command: reload reserved_name'),(683,'Command: reload reputation_reward_rate'),(684,'Command: reload reputation_spillover_template'),(685,'Command: reload skill_discovery_template'),(686,'Command: reload skill_extra_item_template'),(687,'Command: reload skill_fishing_base_level'),(688,'Command: reload skinning_loot_template'),(689,'Command: reload smart_scripts'),(690,'Command: reload spell_required'),(691,'Command: reload spell_area'),(692,'Command: debug send playscene'),(693,'Command: reload spell_group'),(694,'Command: reload spell_learn_spell'),(695,'Command: reload spell_loot_template'),(696,'Command: reload spell_linked_spell'),(697,'Command: reload spell_pet_auras'),(698,'Command: reload spell_proc_event'),(699,'Command: reload spell_proc'),(700,'Command: reload spell_scripts'),(701,'Command: reload spell_target_position'),(702,'Command: reload spell_threats'),(703,'Command: reload spell_group_stack_rules'),(704,'Command: reload trinity_string'),(705,'Command: reload warden_action'),(706,'Command: reload waypoint_scripts'),(707,'Command: reload waypoint_data'),(708,'Command: reload vehicle_accessory'),(709,'Command: reload vehicle_template_accessory'),(710,'Command: reset'),(711,'Command: reset achievements'),(712,'Command: reset honor'),(713,'Command: reset level'),(714,'Command: reset spells'),(715,'Command: reset stats'),(716,'Command: reset talents'),(717,'Command: reset all'),(718,'Command: server'),(719,'Command: server corpses'),(720,'Command: server exit'),(721,'Command: server idlerestart'),(722,'Command: server idlerestart cancel'),(723,'Command: server idleshutdown'),(724,'Command: server idleshutdown cancel'),(725,'Command: server info'),(726,'Command: server plimit'),(727,'Command: server restart'),(728,'Command: server restart cancel'),(729,'Command: server set'),(730,'Command: server set closed'),(731,'Command: server set difftime'),(732,'Command: server set loglevel'),(733,'Command: server set motd'),(734,'Command: server shutdown'),(735,'Command: server shutdown cancel'),(736,'Command: server motd'),(737,'Command: tele'),(738,'Command: tele add'),(739,'Command: tele del'),(740,'Command: tele name'),(741,'Command: tele group'),(742,'Command: ticket'),(753,'Command: ticket reset'),(757,'Command: ticket togglesystem'),(761,'Command: titles'),(762,'Command: titles add'),(763,'Command: titles current'),(764,'Command: titles remove'),(765,'Command: titles set'),(766,'Command: titles set mask'),(767,'Command: wp'),(768,'Command: wp add'),(769,'Command: wp event'),(770,'Command: wp load'),(771,'Command: wp modify'),(772,'Command: wp unload'),(773,'Command: wp reload'),(774,'Command: wp show'),(776,'Command: debug phase'),(777,'Command: mailbox'),(778,'Command: ahbot'),(779,'Command: ahbot items'),(780,'Command: ahbot items gray'),(781,'Command: ahbot items white'),(782,'Command: ahbot items green'),(783,'Command: ahbot items blue'),(784,'Command: ahbot items purple'),(785,'Command: ahbot items orange'),(786,'Command: ahbot items yellow'),(787,'Command: ahbot ratio'),(788,'Command: ahbot ratio alliance'),(789,'Command: ahbot ratio horde'),(790,'Command: ahbot ratio neutral'),(791,'Command: ahbot rebuild'),(792,'Command: ahbot reload'),(793,'Command: ahbot status'),(794,'Command: .guild info'),(797,'Command: pvpstats'),(798,'Command: .mod xp'),(799,'Command: .go bugticket'),(800,'Command: .go complaintticket'),(801,'Command: .go suggestionticket'),(802,'Command: .ticket bug'),(803,'Command: .ticket complaint'),(804,'Command: .ticket suggestion'),(805,'Command: .ticket bug assign'),(806,'Command: .ticket bug close'),(807,'Command: .ticket bug closedlist'),(808,'Command: .ticket bug comment'),(809,'Command: .ticket bug delete'),(810,'Command: .ticket bug list'),(811,'Command: .ticket bug unassign'),(812,'Command: .ticket bug view'),(813,'Command: .ticket complaint assign'),(814,'Command: .ticket complaint close'),(815,'Command: .ticket complaint closedlist'),(816,'Command: .ticket complaint comment'),(817,'Command: .ticket complaint delete'),(818,'Command: .ticket complaint list'),(819,'Command: .ticket complaint unassign'),(820,'Command: .ticket complaint view'),(821,'Command: .ticket suggestion assign'),(822,'Command: .ticket suggestion close'),(823,'Command: .ticket suggestion closedlist'),(824,'Command: .ticket suggestion comment'),(825,'Command: .ticket suggestion delete'),(826,'Command: .ticket suggestion list'),(827,'Command: .ticket suggestion unassign'),(828,'Command: .ticket suggestion view'),(829,'Command: .ticket reset all'),(831,'Command: .ticket reset bug'),(832,'Command: .ticket reset complaint'),(833,'Command: .ticket reset suggestion'),(834,'Command: go quest'),(835,'Command: debug loadcells'),(836,'Command: .debug boundary');
/*!40000 ALTER TABLE `rbac_permissions` ENABLE KEYS */;
UNLOCK TABLES;
@@ -684,7 +684,7 @@ CREATE TABLE `updates` (
LOCK TABLES `updates` WRITE;
/*!40000 ALTER TABLE `updates` DISABLE KEYS */;
-INSERT INTO `updates` VALUES ('2014_10_04_00_auth.sql','C3BC70A6EC381474B7308F442346F1E721176BC6','ARCHIVED','2015-03-21 16:55:52',0),('2014_10_19_00_auth.sql','7472B490A4F86C9D3DA609CDD3197499CB80C87C','ARCHIVED','2015-03-21 16:55:52',0),('2014_10_26_00_auth.sql','75CC67ADE2A3B2E54FD57D6B0DCAA8FE50F4EE35','ARCHIVED','2015-03-21 16:55:52',0),('2014_11_03_00_auth.sql','5948C9F286CF0FEA8E241785C0259FF36B73BDC5','ARCHIVED','2015-03-21 16:55:52',0),('2014_11_04_00_auth.sql','3AFC68B2375C2A417DDEA94583C53AFF83DE50DF','ARCHIVED','2015-03-21 16:55:52',0),('2014_11_09_00_auth.sql','B8DD1A7047C0FDDB80344B239343EC33BF1A0D97','ARCHIVED','2015-03-21 16:55:52',0),('2014_11_10_00_auth.sql','8FBA737A1D3FF4631A1E662A5B500A8BD304EC63','ARCHIVED','2015-03-21 16:55:52',0),('2014_11_10_00_auth_from_335.sql','0E3CB119442D09DD88E967015319BBC8DAFBBFE0','ARCHIVED','2015-03-21 16:55:52',0),('2014_11_10_01_auth.sql','327E77A1DA3546D5275AB249915DD57EDD6FDD3D','ARCHIVED','2015-03-21 16:55:52',0),('2014_11_23_00_auth.sql','0BBEB3EB3AED0FEF277A062819B6B2C00084A742','ARCHIVED','2015-03-21 16:55:52',0),('2014_11_25_00_auth.sql','4F45CDB26BDBB3EE83F1988E3D7818C5926ADC02','ARCHIVED','2015-03-21 16:55:52',0),('2014_12_05_00_auth.sql','6A7BBCEF43111C73A2D2C3CCB6911BE50DE7DD94','ARCHIVED','2015-03-21 16:55:52',0),('2014_12_10_00_auth.sql','821703A96D80F9080074852B5A46E2909C9562EA','ARCHIVED','2015-03-21 16:55:52',0),('2014_12_19_00_auth.sql','44D8E12FFF327AD07878FBDF8D9C16B6B7DCB122','ARCHIVED','2015-03-21 16:55:52',0),('2014_12_20_00_auth.sql','4DAA02AE285C02AE6C82EA2C8B97AC71990F1085','ARCHIVED','2015-03-21 16:55:52',0),('2014_12_25_00_auth.sql','61411930F482BC73FC7FD2C370C811E944F5FF92','ARCHIVED','2015-03-21 16:55:52',0),('2014_12_27_00_auth.sql','CE2E5D2CD82E79C25294539ADED27A1429105B43','ARCHIVED','2015-03-21 16:55:52',0),('2014_12_28_00_auth.sql','0A913217610E76AFF119C27259737BBC523090E6','ARCHIVED','2015-03-21 16:55:52',0),('2015_02_22_00_auth.sql','21CCCF8B01252E16CA3D6C9E3E8DAA4C9B28ED6E','ARCHIVED','2015-03-21 16:55:52',0),('2015_03_01_00_auth.sql','911881E273207FF6182D1FDAC8C85FFAE8F1C852','ARCHIVED','2015-03-21 16:55:52',0),('2015_03_10_00_auth.sql','2CC8502C11412EFEB5C11BE166761A8754A59009','ARCHIVED','2015-03-21 16:55:52',0),('2015_03_20_00_auth.sql','B761760804EA73BD297F296C5C1919687DF7191C','ARCHIVED','2015-03-21 16:55:52',0),('2015_03_20_01_auth.sql','5CCEDF20C8189FB1E8DF064A9F0DDC342841FBF0','ARCHIVED','2015-03-21 16:55:52',0),('2015_03_20_02_auth.sql','85E4ACD9AA099C0C4AC034575F2BB07D348EAC72','ARCHIVED','2015-03-21 16:56:46',0),('2015_03_15_00_auth.sql','1D8E107FBEFE5E7F47E09F45240DFF499B77CDED','ARCHIVED','2015-05-02 13:57:57',0),('2015_03_26_00_auth.sql','34AC8543E6A9C6C832DE58EAB33618EEEF70B9F9','ARCHIVED','2015-05-02 13:57:57',0),('2015_04_04_00_auth.sql','57146B35E54A2EC7869C945034AB078358020311','ARCHIVED','2015-05-02 13:57:57',0),('2015_04_06_00_auth.sql','2A8049DC2923420A002D42FB6F02C2FFCC5CDD22','ARCHIVED','2015-05-02 13:57:57',0),('2015_04_08_00_auth.sql','4D7D8EEF285C982BB676836602266501BEC26764','ARCHIVED','2015-05-02 13:57:57',0),('2015_04_10_00_auth.sql','4AE68FD97A95CEE5143EA20FD33F5D557367AC1F','ARCHIVED','2015-05-02 13:57:57',0),('2015_04_11_00_auth.sql','80A71C8921CFEBB547D264558B6DE27201685B84','ARCHIVED','2015-05-02 13:57:57',0),('2015_04_11_01_auth.sql','3E88183E1A85D11BFD74CF9A32A725C44AE02EEC','ARCHIVED','2015-05-02 13:57:57',0),('2015_04_21_00_auth.sql','1B3B48DBA06368B985C548D166C515C9DD598CB9','ARCHIVED','2015-05-02 13:57:57',0),('2015_05_02_00_auth.sql','96AB595E0D2A088750E3F48B0AF0A8A14F3CFE1E','ARCHIVED','2015-05-02 13:57:57',0),('2015_05_02_01_auth.sql','FB11FB834E488B0FD3AFDABCC1A3113092E7C2E5','ARCHIVED','2015-05-02 13:57:57',0),('2015_07_02_00_auth.sql','E5EE3842AB9B01851E49B360FBAF6FFEEAB2A8DA','ARCHIVED','2015-07-10 19:30:56',0),('2015_07_06_00_auth.sql','6D1ADBA496DC6E6D7B3BF887DA8D4D17D3FBACE0','ARCHIVED','2015-07-10 19:30:56',0),('2015_07_08_00_auth.sql','CB54020AFD1E31742FD8BF9CE16879625E289788','ARCHIVED','2015-07-10 19:30:56',0),('2015_07_08_01_auth.sql','74D281CB82E0DA36D628BDC7AC797AE5498DB461','ARCHIVED','2015-07-10 19:30:56',0),('2015_07_16_00_auth.sql','A057E95B5553B6A57A1642FE3FEC8E2E62EDE3C6','ARCHIVED','2015-10-10 08:30:48',0),('2015_07_29_00_auth.sql','0000FECBC413E96C7C45F303D162E263EFBA7116','ARCHIVED','2015-10-10 08:30:48',0),('2015_08_26_00_auth.sql','3071C02A2EB7DCBF4CEE10279FEFAB7C29A43A3A','ARCHIVED','2015-10-10 08:30:48',0),('2015_09_05_00_auth.sql','F765D82B37873FA67447347D5B83C99C159FB452','ARCHIVED','2015-10-10 08:30:48',0),('2015_09_05_01_auth.sql','97A72DBCBF14D27A1863834A22296905FF276086','ARCHIVED','2015-10-10 08:30:48',0),('2015_09_09_00_auth.sql','495A0CF1B1C49205D4A5D3C25A4E1EB95616D6B4','ARCHIVED','2015-10-10 08:30:48',0),('2015_09_15_00_auth.sql','D1FEFDA4C98F30384DF4B64D5A53187303EB5786','ARCHIVED','2015-10-10 08:30:48',0),('2015_10_09_00_auth.sql','B6D643D444C6AE711503F73B96B6252A852913D6','ARCHIVED','2015-10-10 08:30:48',0),('2015_10_16_00_auth.sql','366AFFD1088762866091A81CE1EC64138B8B35F1','ARCHIVED','2015-11-08 00:46:02',62),('2015_10_17_00_auth.sql','AC0D45E905033F42093852D2C4476663BDACCB3D','ARCHIVED','2015-10-17 12:39:12',0),('2015_11_01_00_auth_2015_08_21_00.sql','C31A9E1D28E11B60BE8F8198637DD51F6D75123F','ARCHIVED','2015-11-01 14:50:26',0),('2015_11_08_00_auth.sql','0ACDD35EC9745231BCFA701B78056DEF94D0CC53','ARCHIVED','2015-11-08 00:51:45',0),('2015_11_21_00_auth.sql','575A1D697CC6C7C517F7CCB950988267C99CE7FA','ARCHIVED','2015-11-21 21:25:38',0),('2015_12_07_00_auth.sql','24A07AC1F38E5D26A3599FC06D29E267418F69F3','ARCHIVED','2015-12-07 20:55:48',0),('2016_01_13_00_auth.sql','114527BCCB0DE286CBE6FDA3029DD0523D1037FA','ARCHIVED','2016-01-13 21:39:13',0),('2016_03_22_01_auth_2016_01_13_00_auth.sql','24615CC69B3CD7BB4699874647C35BA86E8A93FD','ARCHIVED','2016-03-22 22:55:13',0),('2016_03_28_00_auth.sql','BA14D23D81FA24565F04A359090DE86C5E195209','ARCHIVED','2016-03-28 16:49:32',0),('2016_04_11_00_auth.sql','0ACDD35EC9745231BCFA701B78056DEF94D0CC53','RELEASED','2016-04-11 02:24:14',30),('2016_04_17_00_auth.sql','83399B64D1221B56F73A0FFB51889F11A70521BC','RELEASED','2016-04-17 00:22:05',0);
+INSERT INTO `updates` VALUES ('2014_10_04_00_auth.sql','C3BC70A6EC381474B7308F442346F1E721176BC6','ARCHIVED','2015-03-21 16:55:52',0),('2014_10_19_00_auth.sql','7472B490A4F86C9D3DA609CDD3197499CB80C87C','ARCHIVED','2015-03-21 16:55:52',0),('2014_10_26_00_auth.sql','75CC67ADE2A3B2E54FD57D6B0DCAA8FE50F4EE35','ARCHIVED','2015-03-21 16:55:52',0),('2014_11_03_00_auth.sql','5948C9F286CF0FEA8E241785C0259FF36B73BDC5','ARCHIVED','2015-03-21 16:55:52',0),('2014_11_04_00_auth.sql','3AFC68B2375C2A417DDEA94583C53AFF83DE50DF','ARCHIVED','2015-03-21 16:55:52',0),('2014_11_09_00_auth.sql','B8DD1A7047C0FDDB80344B239343EC33BF1A0D97','ARCHIVED','2015-03-21 16:55:52',0),('2014_11_10_00_auth.sql','8FBA737A1D3FF4631A1E662A5B500A8BD304EC63','ARCHIVED','2015-03-21 16:55:52',0),('2014_11_10_00_auth_from_335.sql','0E3CB119442D09DD88E967015319BBC8DAFBBFE0','ARCHIVED','2015-03-21 16:55:52',0),('2014_11_10_01_auth.sql','327E77A1DA3546D5275AB249915DD57EDD6FDD3D','ARCHIVED','2015-03-21 16:55:52',0),('2014_11_23_00_auth.sql','0BBEB3EB3AED0FEF277A062819B6B2C00084A742','ARCHIVED','2015-03-21 16:55:52',0),('2014_11_25_00_auth.sql','4F45CDB26BDBB3EE83F1988E3D7818C5926ADC02','ARCHIVED','2015-03-21 16:55:52',0),('2014_12_05_00_auth.sql','6A7BBCEF43111C73A2D2C3CCB6911BE50DE7DD94','ARCHIVED','2015-03-21 16:55:52',0),('2014_12_10_00_auth.sql','821703A96D80F9080074852B5A46E2909C9562EA','ARCHIVED','2015-03-21 16:55:52',0),('2014_12_19_00_auth.sql','44D8E12FFF327AD07878FBDF8D9C16B6B7DCB122','ARCHIVED','2015-03-21 16:55:52',0),('2014_12_20_00_auth.sql','4DAA02AE285C02AE6C82EA2C8B97AC71990F1085','ARCHIVED','2015-03-21 16:55:52',0),('2014_12_25_00_auth.sql','61411930F482BC73FC7FD2C370C811E944F5FF92','ARCHIVED','2015-03-21 16:55:52',0),('2014_12_27_00_auth.sql','CE2E5D2CD82E79C25294539ADED27A1429105B43','ARCHIVED','2015-03-21 16:55:52',0),('2014_12_28_00_auth.sql','0A913217610E76AFF119C27259737BBC523090E6','ARCHIVED','2015-03-21 16:55:52',0),('2015_02_22_00_auth.sql','21CCCF8B01252E16CA3D6C9E3E8DAA4C9B28ED6E','ARCHIVED','2015-03-21 16:55:52',0),('2015_03_01_00_auth.sql','911881E273207FF6182D1FDAC8C85FFAE8F1C852','ARCHIVED','2015-03-21 16:55:52',0),('2015_03_10_00_auth.sql','2CC8502C11412EFEB5C11BE166761A8754A59009','ARCHIVED','2015-03-21 16:55:52',0),('2015_03_20_00_auth.sql','B761760804EA73BD297F296C5C1919687DF7191C','ARCHIVED','2015-03-21 16:55:52',0),('2015_03_20_01_auth.sql','5CCEDF20C8189FB1E8DF064A9F0DDC342841FBF0','ARCHIVED','2015-03-21 16:55:52',0),('2015_03_20_02_auth.sql','85E4ACD9AA099C0C4AC034575F2BB07D348EAC72','ARCHIVED','2015-03-21 16:56:46',0),('2015_03_15_00_auth.sql','1D8E107FBEFE5E7F47E09F45240DFF499B77CDED','ARCHIVED','2015-05-02 13:57:57',0),('2015_03_26_00_auth.sql','34AC8543E6A9C6C832DE58EAB33618EEEF70B9F9','ARCHIVED','2015-05-02 13:57:57',0),('2015_04_04_00_auth.sql','57146B35E54A2EC7869C945034AB078358020311','ARCHIVED','2015-05-02 13:57:57',0),('2015_04_06_00_auth.sql','2A8049DC2923420A002D42FB6F02C2FFCC5CDD22','ARCHIVED','2015-05-02 13:57:57',0),('2015_04_08_00_auth.sql','4D7D8EEF285C982BB676836602266501BEC26764','ARCHIVED','2015-05-02 13:57:57',0),('2015_04_10_00_auth.sql','4AE68FD97A95CEE5143EA20FD33F5D557367AC1F','ARCHIVED','2015-05-02 13:57:57',0),('2015_04_11_00_auth.sql','80A71C8921CFEBB547D264558B6DE27201685B84','ARCHIVED','2015-05-02 13:57:57',0),('2015_04_11_01_auth.sql','3E88183E1A85D11BFD74CF9A32A725C44AE02EEC','ARCHIVED','2015-05-02 13:57:57',0),('2015_04_21_00_auth.sql','1B3B48DBA06368B985C548D166C515C9DD598CB9','ARCHIVED','2015-05-02 13:57:57',0),('2015_05_02_00_auth.sql','96AB595E0D2A088750E3F48B0AF0A8A14F3CFE1E','ARCHIVED','2015-05-02 13:57:57',0),('2015_05_02_01_auth.sql','FB11FB834E488B0FD3AFDABCC1A3113092E7C2E5','ARCHIVED','2015-05-02 13:57:57',0),('2015_07_02_00_auth.sql','E5EE3842AB9B01851E49B360FBAF6FFEEAB2A8DA','ARCHIVED','2015-07-10 19:30:56',0),('2015_07_06_00_auth.sql','6D1ADBA496DC6E6D7B3BF887DA8D4D17D3FBACE0','ARCHIVED','2015-07-10 19:30:56',0),('2015_07_08_00_auth.sql','CB54020AFD1E31742FD8BF9CE16879625E289788','ARCHIVED','2015-07-10 19:30:56',0),('2015_07_08_01_auth.sql','74D281CB82E0DA36D628BDC7AC797AE5498DB461','ARCHIVED','2015-07-10 19:30:56',0),('2015_07_16_00_auth.sql','A057E95B5553B6A57A1642FE3FEC8E2E62EDE3C6','ARCHIVED','2015-10-10 08:30:48',0),('2015_07_29_00_auth.sql','0000FECBC413E96C7C45F303D162E263EFBA7116','ARCHIVED','2015-10-10 08:30:48',0),('2015_08_26_00_auth.sql','3071C02A2EB7DCBF4CEE10279FEFAB7C29A43A3A','ARCHIVED','2015-10-10 08:30:48',0),('2015_09_05_00_auth.sql','F765D82B37873FA67447347D5B83C99C159FB452','ARCHIVED','2015-10-10 08:30:48',0),('2015_09_05_01_auth.sql','97A72DBCBF14D27A1863834A22296905FF276086','ARCHIVED','2015-10-10 08:30:48',0),('2015_09_09_00_auth.sql','495A0CF1B1C49205D4A5D3C25A4E1EB95616D6B4','ARCHIVED','2015-10-10 08:30:48',0),('2015_09_15_00_auth.sql','D1FEFDA4C98F30384DF4B64D5A53187303EB5786','ARCHIVED','2015-10-10 08:30:48',0),('2015_10_09_00_auth.sql','B6D643D444C6AE711503F73B96B6252A852913D6','ARCHIVED','2015-10-10 08:30:48',0),('2015_10_16_00_auth.sql','366AFFD1088762866091A81CE1EC64138B8B35F1','ARCHIVED','2015-11-08 00:46:02',62),('2015_10_17_00_auth.sql','AC0D45E905033F42093852D2C4476663BDACCB3D','ARCHIVED','2015-10-17 12:39:12',0),('2015_11_01_00_auth_2015_08_21_00.sql','C31A9E1D28E11B60BE8F8198637DD51F6D75123F','ARCHIVED','2015-11-01 14:50:26',0),('2015_11_08_00_auth.sql','0ACDD35EC9745231BCFA701B78056DEF94D0CC53','ARCHIVED','2015-11-08 00:51:45',0),('2015_11_21_00_auth.sql','575A1D697CC6C7C517F7CCB950988267C99CE7FA','ARCHIVED','2015-11-21 21:25:38',0),('2015_12_07_00_auth.sql','24A07AC1F38E5D26A3599FC06D29E267418F69F3','ARCHIVED','2015-12-07 20:55:48',0),('2016_01_13_00_auth.sql','114527BCCB0DE286CBE6FDA3029DD0523D1037FA','ARCHIVED','2016-01-13 21:39:13',0),('2016_03_22_01_auth_2016_01_13_00_auth.sql','24615CC69B3CD7BB4699874647C35BA86E8A93FD','ARCHIVED','2016-03-22 22:55:13',0),('2016_03_28_00_auth.sql','BA14D23D81FA24565F04A359090DE86C5E195209','ARCHIVED','2016-03-28 16:49:32',0),('2016_04_11_00_auth.sql','0ACDD35EC9745231BCFA701B78056DEF94D0CC53','RELEASED','2016-04-11 02:24:14',30),('2016_04_17_00_auth.sql','83399B64D1221B56F73A0FFB51889F11A70521BC','RELEASED','2016-04-17 00:22:05',0),('2016_05_07_00_auth.sql','7E36DCC4F06FCDCDA7155AF3C5EDF8D3A720565F','RELEASED','2016-05-07 01:00:21',0);
/*!40000 ALTER TABLE `updates` ENABLE KEYS */;
UNLOCK TABLES;
diff --git a/sql/base/characters_database.sql b/sql/base/characters_database.sql
index 0230798ef70..bccc4176530 100644
--- a/sql/base/characters_database.sql
+++ b/sql/base/characters_database.sql
@@ -410,7 +410,7 @@ DROP TABLE IF EXISTS `character_achievement`;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `character_achievement` (
`guid` bigint(20) unsigned NOT NULL,
- `achievement` smallint(5) unsigned NOT NULL,
+ `achievement` int(10) unsigned NOT NULL,
`date` int(10) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`guid`,`achievement`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
@@ -2117,7 +2117,7 @@ DROP TABLE IF EXISTS `guild_achievement`;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `guild_achievement` (
`guildId` bigint(20) unsigned NOT NULL,
- `achievement` smallint(5) unsigned NOT NULL,
+ `achievement` int(10) unsigned NOT NULL,
`date` int(10) unsigned NOT NULL DEFAULT '0',
`guids` text NOT NULL,
PRIMARY KEY (`guildId`,`achievement`)
@@ -3109,7 +3109,7 @@ CREATE TABLE `updates` (
LOCK TABLES `updates` WRITE;
/*!40000 ALTER TABLE `updates` DISABLE KEYS */;
-INSERT INTO `updates` VALUES ('2014_10_20_00_characters.sql','A5882DA0979CF4DAE33DA011EBAA006C24BE7230','ARCHIVED','2015-03-21 15:55:55',0),('2014_10_23_00_characters.sql','E2AC4758133EE19B7F08464A445802154D1261C8','ARCHIVED','2015-03-21 15:55:55',0),('2014_10_23_01_characters.sql','20029E6323D9773B32C34D84FFED1711CC60F09F','ARCHIVED','2015-03-21 15:55:55',0),('2014_10_23_02_characters.sql','8A7A16886EE71E7ACDDB3DDA6D0ECAC2FD2FDCA8','ARCHIVED','2015-03-21 15:55:55',0),('2014_10_24_00_characters.sql','D008FE81AE844FCA686439D6ECC5108FB0DD1EB9','ARCHIVED','2015-03-21 15:55:55',0),('2014_10_25_00_characters.sql','A39C7BE46686B54776BDAB9D7A882D91EDEC51A4','ARCHIVED','2015-03-21 15:55:55',0),('2014_10_26_00_characters.sql','C787954CC35FE34B4101FDE6527F14C027F4947C','ARCHIVED','2015-03-21 15:55:55',0),('2014_11_12_00_characters.sql','B160BB2313F1BD5F3B076A5A9279DC10D4796E34','ARCHIVED','2015-03-21 15:55:55',0),('2014_12_23_00_characters.sql','3D9D648B2387B357F4BD090B33F80682F7924882','ARCHIVED','2015-03-21 15:55:55',0),('2014_12_28_00_characters.sql','5362922FF4483A336311D73082A5727309CD9219','ARCHIVED','2015-03-21 15:55:55',0),('2014_12_31_00_characters.sql','498DDF2DD936CF156D74A8208DC93DCE9FCAB5AA','ARCHIVED','2015-03-21 15:55:55',0),('2015_01_02_00_characters.sql','E5940BE836F253982E07930120422E598D08BDE1','ARCHIVED','2015-03-21 15:55:55',0),('2015_01_10_00_characters.sql','30796056C8623699B2FE1BF626A19D38262E9284','ARCHIVED','2015-03-21 15:55:55',0),('2015_01_16_00_characters.sql','96642760A54C8D799AAFE438049A63AA521656F2','ARCHIVED','2015-03-21 15:55:55',0),('2015_01_27_00_characters.sql','EB710E3EB9F2CAFD84AB62CDC84E898403A80A4F','ARCHIVED','2015-03-21 15:55:55',0),('2015_02_13_00_characters.sql','405BEB4ED207DC6076442A37EE2AFB1F21E274A0','ARCHIVED','2015-03-21 15:55:55',0),('2015_02_13_01_characters.sql','35F582D4F33BF55D1685A1BA89273ED895FD09C5','ARCHIVED','2015-03-21 15:55:55',0),('2015_02_17_00_characters.sql','8D21FC5A55BF8B55D6DCDCE5F02CF2B640230E94','ARCHIVED','2015-03-21 15:55:55',0),('2015_03_10_00_characters.sql','E565B89B145C340067742DFF2DEF1B74F5F1BD4E','ARCHIVED','2015-03-21 15:55:55',0),('2015_03_20_00_characters.sql','B761760804EA73BD297F296C5C1919687DF7191C','ARCHIVED','2015-03-21 15:55:55',0),('2015_03_20_01_characters.sql','20BD68468C57FCF7E665B4DA185DCD52FACE8B3F','ARCHIVED','2015-03-21 15:55:55',0),('2015_03_20_02_characters.sql','0296995DCD3676BA9AE6024CA7C91C5F39D927A3','ARCHIVED','2015-03-21 15:56:46',0),('2015_03_29_00_characters.sql','95D6A46BB746A8BD3EE3FE2086DF1A07F7C33B92','ARCHIVED','2015-05-02 15:43:06',0),('2015_04_21_00_characters.sql','F2032B9BF4EDA7EDE5065554724ED392FD91657D','ARCHIVED','2015-05-02 15:43:06',0),('2015_04_28_00_characters.sql','949F62DB3A3461D420A1230ECF7A6A3ED6435703','ARCHIVED','2015-05-02 15:43:06',0),('2015_05_08_00_characters.sql','0F14B7821618D1C872625B6EDDAA9A667B211167','ARCHIVED','2015-07-10 19:32:17',0),('2015_05_22_00_characters.sql','65B82152413FAB23BE413656E59A486A74447FF7','ARCHIVED','2015-07-10 19:32:17',0),('2015_07_08_00_characters.sql','DAB25360ACB5244C8F8E6214CF6BD97160588A5B','ARCHIVED','2015-07-10 19:32:17',0),('2015_07_11_00_characters.sql','B421B6C0E57BD0FD587071358863D9DABF4BA849','ARCHIVED','2015-07-13 21:50:02',0),('2015_07_12_00_characters.sql','E98E7FD61EF6426E7EDE8ED9AD8C15D8D7132589','ARCHIVED','2015-07-13 21:50:02',0),('2015_07_28_00_characters.sql','0711BC3A658D189EF71B0CB68DCFF2E9B781C4A0','ARCHIVED','2015-07-29 16:23:56',0),('2015_08_08_00_characters.sql','EA12BB2DC24FAF2300A96D0888A45BBEA158D5DC','ARCHIVED','2015-08-08 16:34:07',0),('2015_08_12_00_characters.sql','4FD7F89FE5DA51D4E0C33E520719986AA3EBD31B','ARCHIVED','2015-08-12 12:35:20',0),('2015_09_05_00_characters.sql','4C22BB29365BE4B6B95E64DAD84B63CA002304EA','ARCHIVED','2015-09-05 12:35:20',0),('2015_09_09_00_characters.sql','AFC32E693BC17CFD9A17919FE5317B8FE337ACAD','ARCHIVED','2015-09-09 12:35:20',0),('2015_09_10_00_characters.sql','4555A7F35C107E54C13D74D20F141039ED42943E','ARCHIVED','2015-09-10 22:50:42',0),('2015_10_16_00_characters.sql','E3A3FFF0CB42F04A8DCF0CE4362143C16E2083AF','ARCHIVED','2015-10-15 21:54:11',0),('2015_11_06_00_characters_2015_10_12_00.sql','D6F9927BDED72AD0A81D6EC2C6500CBC34A39FA2','ARCHIVED','2015-11-06 23:43:27',0),('2015_11_08_00_characters.sql','0ACDD35EC9745231BCFA701B78056DEF94D0CC53','ARCHIVED','2015-11-08 00:51:45',15),('2015_11_23_00_characters.sql','9FC828E9E48E8E2E9B99A5A0073D6614C5BFC6B5','ARCHIVED','2015-11-22 23:27:34',0),('2016_01_05_00_characters.sql','0EAD24977F40DE2476B4567DA2B477867CC0DA1A','ARCHIVED','2016-01-04 23:07:40',0),('2016_04_05_00_characters_2016_02_10_00_characters.sql','F1B4DA202819CABC7319A4470A2D224A34609E97','ARCHIVED','2016-04-05 20:34:41',0),('2016_04_11_00_characters.sql','0ACDD35EC9745231BCFA701B78056DEF94D0CC53','RELEASED','2016-04-11 02:24:14',30),('2016_04_11_01_characters.sql','CA90F6D99C1EEA7B25BD58BC8368A8D78234BBEF','RELEASED','2016-04-11 18:14:18',0);
+INSERT INTO `updates` VALUES ('2014_10_20_00_characters.sql','A5882DA0979CF4DAE33DA011EBAA006C24BE7230','ARCHIVED','2015-03-21 15:55:55',0),('2014_10_23_00_characters.sql','E2AC4758133EE19B7F08464A445802154D1261C8','ARCHIVED','2015-03-21 15:55:55',0),('2014_10_23_01_characters.sql','20029E6323D9773B32C34D84FFED1711CC60F09F','ARCHIVED','2015-03-21 15:55:55',0),('2014_10_23_02_characters.sql','8A7A16886EE71E7ACDDB3DDA6D0ECAC2FD2FDCA8','ARCHIVED','2015-03-21 15:55:55',0),('2014_10_24_00_characters.sql','D008FE81AE844FCA686439D6ECC5108FB0DD1EB9','ARCHIVED','2015-03-21 15:55:55',0),('2014_10_25_00_characters.sql','A39C7BE46686B54776BDAB9D7A882D91EDEC51A4','ARCHIVED','2015-03-21 15:55:55',0),('2014_10_26_00_characters.sql','C787954CC35FE34B4101FDE6527F14C027F4947C','ARCHIVED','2015-03-21 15:55:55',0),('2014_11_12_00_characters.sql','B160BB2313F1BD5F3B076A5A9279DC10D4796E34','ARCHIVED','2015-03-21 15:55:55',0),('2014_12_23_00_characters.sql','3D9D648B2387B357F4BD090B33F80682F7924882','ARCHIVED','2015-03-21 15:55:55',0),('2014_12_28_00_characters.sql','5362922FF4483A336311D73082A5727309CD9219','ARCHIVED','2015-03-21 15:55:55',0),('2014_12_31_00_characters.sql','498DDF2DD936CF156D74A8208DC93DCE9FCAB5AA','ARCHIVED','2015-03-21 15:55:55',0),('2015_01_02_00_characters.sql','E5940BE836F253982E07930120422E598D08BDE1','ARCHIVED','2015-03-21 15:55:55',0),('2015_01_10_00_characters.sql','30796056C8623699B2FE1BF626A19D38262E9284','ARCHIVED','2015-03-21 15:55:55',0),('2015_01_16_00_characters.sql','96642760A54C8D799AAFE438049A63AA521656F2','ARCHIVED','2015-03-21 15:55:55',0),('2015_01_27_00_characters.sql','EB710E3EB9F2CAFD84AB62CDC84E898403A80A4F','ARCHIVED','2015-03-21 15:55:55',0),('2015_02_13_00_characters.sql','405BEB4ED207DC6076442A37EE2AFB1F21E274A0','ARCHIVED','2015-03-21 15:55:55',0),('2015_02_13_01_characters.sql','35F582D4F33BF55D1685A1BA89273ED895FD09C5','ARCHIVED','2015-03-21 15:55:55',0),('2015_02_17_00_characters.sql','8D21FC5A55BF8B55D6DCDCE5F02CF2B640230E94','ARCHIVED','2015-03-21 15:55:55',0),('2015_03_10_00_characters.sql','E565B89B145C340067742DFF2DEF1B74F5F1BD4E','ARCHIVED','2015-03-21 15:55:55',0),('2015_03_20_00_characters.sql','B761760804EA73BD297F296C5C1919687DF7191C','ARCHIVED','2015-03-21 15:55:55',0),('2015_03_20_01_characters.sql','20BD68468C57FCF7E665B4DA185DCD52FACE8B3F','ARCHIVED','2015-03-21 15:55:55',0),('2015_03_20_02_characters.sql','0296995DCD3676BA9AE6024CA7C91C5F39D927A3','ARCHIVED','2015-03-21 15:56:46',0),('2015_03_29_00_characters.sql','95D6A46BB746A8BD3EE3FE2086DF1A07F7C33B92','ARCHIVED','2015-05-02 15:43:06',0),('2015_04_21_00_characters.sql','F2032B9BF4EDA7EDE5065554724ED392FD91657D','ARCHIVED','2015-05-02 15:43:06',0),('2015_04_28_00_characters.sql','949F62DB3A3461D420A1230ECF7A6A3ED6435703','ARCHIVED','2015-05-02 15:43:06',0),('2015_05_08_00_characters.sql','0F14B7821618D1C872625B6EDDAA9A667B211167','ARCHIVED','2015-07-10 19:32:17',0),('2015_05_22_00_characters.sql','65B82152413FAB23BE413656E59A486A74447FF7','ARCHIVED','2015-07-10 19:32:17',0),('2015_07_08_00_characters.sql','DAB25360ACB5244C8F8E6214CF6BD97160588A5B','ARCHIVED','2015-07-10 19:32:17',0),('2015_07_11_00_characters.sql','B421B6C0E57BD0FD587071358863D9DABF4BA849','ARCHIVED','2015-07-13 21:50:02',0),('2015_07_12_00_characters.sql','E98E7FD61EF6426E7EDE8ED9AD8C15D8D7132589','ARCHIVED','2015-07-13 21:50:02',0),('2015_07_28_00_characters.sql','0711BC3A658D189EF71B0CB68DCFF2E9B781C4A0','ARCHIVED','2015-07-29 16:23:56',0),('2015_08_08_00_characters.sql','EA12BB2DC24FAF2300A96D0888A45BBEA158D5DC','ARCHIVED','2015-08-08 16:34:07',0),('2015_08_12_00_characters.sql','4FD7F89FE5DA51D4E0C33E520719986AA3EBD31B','ARCHIVED','2015-08-12 12:35:20',0),('2015_09_05_00_characters.sql','4C22BB29365BE4B6B95E64DAD84B63CA002304EA','ARCHIVED','2015-09-05 12:35:20',0),('2015_09_09_00_characters.sql','AFC32E693BC17CFD9A17919FE5317B8FE337ACAD','ARCHIVED','2015-09-09 12:35:20',0),('2015_09_10_00_characters.sql','4555A7F35C107E54C13D74D20F141039ED42943E','ARCHIVED','2015-09-10 22:50:42',0),('2015_10_16_00_characters.sql','E3A3FFF0CB42F04A8DCF0CE4362143C16E2083AF','ARCHIVED','2015-10-15 21:54:11',0),('2015_11_06_00_characters_2015_10_12_00.sql','D6F9927BDED72AD0A81D6EC2C6500CBC34A39FA2','ARCHIVED','2015-11-06 23:43:27',0),('2015_11_08_00_characters.sql','0ACDD35EC9745231BCFA701B78056DEF94D0CC53','ARCHIVED','2015-11-08 00:51:45',15),('2015_11_23_00_characters.sql','9FC828E9E48E8E2E9B99A5A0073D6614C5BFC6B5','ARCHIVED','2015-11-22 23:27:34',0),('2016_01_05_00_characters.sql','0EAD24977F40DE2476B4567DA2B477867CC0DA1A','ARCHIVED','2016-01-04 23:07:40',0),('2016_04_05_00_characters_2016_02_10_00_characters.sql','F1B4DA202819CABC7319A4470A2D224A34609E97','ARCHIVED','2016-04-05 20:34:41',0),('2016_04_11_00_characters.sql','0ACDD35EC9745231BCFA701B78056DEF94D0CC53','RELEASED','2016-04-11 02:24:14',30),('2016_04_11_01_characters.sql','CA90F6D99C1EEA7B25BD58BC8368A8D78234BBEF','RELEASED','2016-04-11 18:14:18',0),('2016_05_07_00_characters.sql','D1DB5557B21A552C935564D829B4E98B98149077','RELEASED','2016-05-07 00:00:00',0);
/*!40000 ALTER TABLE `updates` ENABLE KEYS */;
UNLOCK TABLES;
diff --git a/sql/updates/auth/6.x/2016_05_07_00_auth.sql b/sql/updates/auth/6.x/2016_05_07_00_auth.sql
new file mode 100644
index 00000000000..48f9cbd8fe2
--- /dev/null
+++ b/sql/updates/auth/6.x/2016_05_07_00_auth.sql
@@ -0,0 +1,3 @@
+UPDATE `rbac_permissions` SET `name`='Command: disable add criteria' WHERE `id`=350;
+UPDATE `rbac_permissions` SET `name`='Command: disable remove criteria' WHERE `id`=359;
+UPDATE `rbac_permissions` SET `name`='Command: reload criteria_data' WHERE `id`=609;
diff --git a/sql/updates/characters/6.x/2016_05_07_00_characters.sql b/sql/updates/characters/6.x/2016_05_07_00_characters.sql
new file mode 100644
index 00000000000..d9a7fbb4096
--- /dev/null
+++ b/sql/updates/characters/6.x/2016_05_07_00_characters.sql
@@ -0,0 +1,2 @@
+ALTER TABLE `character_achievement` CHANGE `achievement` `achievement` int(10) unsigned NOT NULL;
+ALTER TABLE `guild_achievement` CHANGE `achievement` `achievement` int(10) unsigned NOT NULL;
diff --git a/sql/updates/world/6.x/2016_05_07_00_world.sql b/sql/updates/world/6.x/2016_05_07_00_world.sql
new file mode 100644
index 00000000000..4d1fb2e867b
--- /dev/null
+++ b/sql/updates/world/6.x/2016_05_07_00_world.sql
@@ -0,0 +1,4 @@
+RENAME TABLE `achievement_criteria_data` TO `criteria_data`;
+UPDATE `command` SET `name`='disable add criteria', `help`='Syntax: .disable add criteria $entry $flag $comment' WHERE `name`='disable add achievement_criteria';
+UPDATE `command` SET `name`='disable remove criteria', `help`='Syntax: .disable remove criteria $entry' WHERE `name`='disable remove achievement_criteria';
+UPDATE `command` SET `name`='reload criteria_data', `help`='Syntax: .reload criteria_data\nReload criteria_data table.' WHERE `name`='reload achievement_criteria_data';
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