aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/base/characters_database.sql50
-rw-r--r--sql/updates/characters/master/2017_08_20_00_characters.sql21
-rw-r--r--src/server/database/Database/Implementation/CharacterDatabase.cpp8
-rw-r--r--src/server/database/Database/Implementation/CharacterDatabase.h8
-rw-r--r--src/server/game/Achievements/AchievementMgr.cpp4
-rw-r--r--src/server/game/Achievements/CriteriaHandler.cpp28
-rw-r--r--src/server/game/Achievements/CriteriaHandler.h17
-rw-r--r--src/server/game/Entities/Player/Player.cpp48
-rw-r--r--src/server/game/Entities/Player/Player.h5
-rw-r--r--src/server/game/Handlers/CharacterHandler.cpp8
-rw-r--r--src/server/game/Quests/QuestDef.h6
-rw-r--r--src/server/game/Quests/QuestObjectiveCriteriaMgr.cpp320
-rw-r--r--src/server/game/Quests/QuestObjectiveCriteriaMgr.h64
13 files changed, 573 insertions, 14 deletions
diff --git a/sql/base/characters_database.sql b/sql/base/characters_database.sql
index 6baffea518e..99558dfd839 100644
--- a/sql/base/characters_database.sql
+++ b/sql/base/characters_database.sql
@@ -1186,6 +1186,54 @@ LOCK TABLES `character_queststatus_objectives` WRITE;
UNLOCK TABLES;
--
+-- Table structure for table `character_queststatus_objectives_criteria`
+--
+
+DROP TABLE IF EXISTS `character_queststatus_objectives_criteria`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `character_queststatus_objectives_criteria` (
+ `guid` bigint(20) unsigned NOT NULL,
+ `questObjectiveId` int(10) unsigned NOT NULL,
+ PRIMARY KEY (`guid`,`questObjectiveId`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Player System';
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `character_queststatus_objectives_criteria`
+--
+
+LOCK TABLES `character_queststatus_objectives_criteria` WRITE;
+/*!40000 ALTER TABLE `character_queststatus_objectives_criteria` DISABLE KEYS */;
+/*!40000 ALTER TABLE `character_queststatus_objectives_criteria` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Table structure for table `character_queststatus_objectives_criteria_progress`
+--
+
+DROP TABLE IF EXISTS `character_queststatus_objectives_criteria_progress`;
+/*!40101 SET @saved_cs_client = @@character_set_client */;
+/*!40101 SET character_set_client = utf8 */;
+CREATE TABLE `character_queststatus_objectives_criteria_progress` (
+ `guid` bigint(20) unsigned NOT NULL,
+ `criteriaId` int(10) unsigned NOT NULL,
+ `counter` bigint(20) unsigned NOT NULL,
+ `date` int(10) unsigned NOT NULL DEFAULT '0',
+ PRIMARY KEY (`guid`,`criteriaId`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Player System';
+/*!40101 SET character_set_client = @saved_cs_client */;
+
+--
+-- Dumping data for table `character_queststatus_objectives_criteria_progress`
+--
+
+LOCK TABLES `character_queststatus_objectives_criteria_progress` WRITE;
+/*!40000 ALTER TABLE `character_queststatus_objectives_criteria_progress` DISABLE KEYS */;
+/*!40000 ALTER TABLE `character_queststatus_objectives_criteria_progress` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
-- Table structure for table `character_queststatus_rewarded`
--
@@ -3260,7 +3308,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','ARCHIVED','2016-04-11 02:24:14',30),('2016_04_11_01_characters.sql','CA90F6D99C1EEA7B25BD58BC8368A8D78234BBEF','ARCHIVED','2016-04-11 18:14:18',0),('2016_05_07_00_characters.sql','D1DB5557B21A552C935564D829B4E98B98149077','ARCHIVED','2016-05-07 00:00:00',0),('2016_05_26_00_characters.sql','4179ADC32B96FD8D7D4CF5509A470B1ACE00BE85','ARCHIVED','2016-05-26 17:06:16',0),('2016_07_16_00_characters.sql','EF267FCB92B383FFB33C700508EAF3FBC1F8AC23','ARCHIVED','2016-07-16 14:45:12',0),('2016_07_19_00_characters.sql','AA2C516FA81B451071EA82F58F447E9D13E5D1BD','ARCHIVED','2016-07-19 14:36:25',0),('2016_07_19_01_characters.sql','E9AF46AF4C7CC2E2779E44254AEEDF880D020166','ARCHIVED','2016-07-19 14:36:25',0),('2016_07_19_02_characters.sql','5B1B334449996F3639C9226F587129E03DC4BF6D','ARCHIVED','2016-07-19 14:36:26',0),('2016_07_19_03_characters.sql','7787C8A67D720492FED4BF60ADB22D3CDE1C536D','ARCHIVED','2016-07-19 14:36:26',0),('2016_07_19_04_characters.sql','6D4B536094367AC9EF7CDFF41A4F96EB00B25EE5','ARCHIVED','2016-07-19 14:36:26',0),('2016_07_19_05_characters.sql','12639268DC5F78CE900B59D5C646B10D70842928','ARCHIVED','2016-07-19 14:36:27',0),('2016_07_19_06_characters.sql','9F5A4B533E6BFBAA718DE5160E1FDCB8471A88BF','ARCHIVED','2016-07-19 14:36:28',0),('2016_07_19_07_characters.sql','1E8273FFD4340CBD7BB71D2406E23E9EF7230CFA','ARCHIVED','2016-07-19 14:36:29',0),('2016_07_19_08_characters.sql','FB41FD2F8A7114FEE154021A9D47488C4B12E2A9','ARCHIVED','2016-07-19 14:36:29',0),('2016_08_15_00_characters.sql','BF0B5F453384210CD77C54E262A19B888AAA4095','ARCHIVED','2016-08-14 18:14:32',0),('2016_08_25_00_characters.sql','4AD506C3FCE54238EF452AC07EC562BD41A9D50C','ARCHIVED','2016-08-25 22:54:11',0),('2016_10_17_00_characters.sql','A0EF594CD73690D46A46031137DB0E895F079235','ARCHIVED','2016-10-16 16:33:05',25),('2016_10_25_00_characters.sql','CC894484561CE138C10B69D34F7831CEDFAF496B','ARCHIVED','2016-10-25 17:19:35',0),('2016_11_06_00_characters.sql','C7EC8B65C1BE7722C53BAB79C52C1549054178C0','ARCHIVED','2016-11-06 23:05:44',0),('2016_12_09_00_characters.sql','2A68E4187CE7F7294CBC3804AC39F48B2727E64E','ARCHIVED','2016-12-09 18:38:46',0),('2016_12_26_00_characters.sql','D265DE655DDBFC13E2FA1EB021A435A21189B6E4','ARCHIVED','2016-12-26 18:45:15',0),('2017_01_22_00_characters.sql','62B08B5FB1DA7B207C74DC000C42517A2D6F6BCC','ARCHIVED','2017-01-22 02:06:31',0),('2017_01_29_00_characters.sql','E7475DCC13A0910FF23BF0EFB731629950A73A0D','ARCHIVED','2017-01-29 15:00:00',0),('2017_02_26_00_characters_2016_09_13_00_characters.sql','2EF7AD507D097ABC74FF1E98A65BEC03B12E51C6','ARCHIVED','2017-02-26 19:57:47',0),('2017_04_15_00_characters.sql','F118BA33CD7DDF2EE5673C6749C2965EFFF53C23','ARCHIVED','2017-04-15 12:10:50',0),('2017_04_19_00_characters.sql','5A36FD9015ED024BC085F995F72DC81B47CD1093','RELEASED','2017-04-18 23:16:18',30),('2017_05_08_00_characters.sql','86B5603EEBE1DE0EA56DBB264257967CFE583F46','RELEASED','2017-05-08 23:54:40',0),('2017_05_14_00_characters.sql','3452261F366BFE76BB59C0AAA674FA1513042899','RELEASED','2017-05-14 17:29:04',0),('2017_05_24_00_characters.sql','02701BF57589CD41456A748AEF425CBB2D3E6AD7','RELEASED','2017-05-24 22:00:00',0),('2017_06_04_00_characters.sql','BC80D2B7515CC6E01701070D2DA466727F36DB5E','RELEASED','2017-06-04 14:43:26',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','ARCHIVED','2016-04-11 02:24:14',30),('2016_04_11_01_characters.sql','CA90F6D99C1EEA7B25BD58BC8368A8D78234BBEF','ARCHIVED','2016-04-11 18:14:18',0),('2016_05_07_00_characters.sql','D1DB5557B21A552C935564D829B4E98B98149077','ARCHIVED','2016-05-07 00:00:00',0),('2016_05_26_00_characters.sql','4179ADC32B96FD8D7D4CF5509A470B1ACE00BE85','ARCHIVED','2016-05-26 17:06:16',0),('2016_07_16_00_characters.sql','EF267FCB92B383FFB33C700508EAF3FBC1F8AC23','ARCHIVED','2016-07-16 14:45:12',0),('2016_07_19_00_characters.sql','AA2C516FA81B451071EA82F58F447E9D13E5D1BD','ARCHIVED','2016-07-19 14:36:25',0),('2016_07_19_01_characters.sql','E9AF46AF4C7CC2E2779E44254AEEDF880D020166','ARCHIVED','2016-07-19 14:36:25',0),('2016_07_19_02_characters.sql','5B1B334449996F3639C9226F587129E03DC4BF6D','ARCHIVED','2016-07-19 14:36:26',0),('2016_07_19_03_characters.sql','7787C8A67D720492FED4BF60ADB22D3CDE1C536D','ARCHIVED','2016-07-19 14:36:26',0),('2016_07_19_04_characters.sql','6D4B536094367AC9EF7CDFF41A4F96EB00B25EE5','ARCHIVED','2016-07-19 14:36:26',0),('2016_07_19_05_characters.sql','12639268DC5F78CE900B59D5C646B10D70842928','ARCHIVED','2016-07-19 14:36:27',0),('2016_07_19_06_characters.sql','9F5A4B533E6BFBAA718DE5160E1FDCB8471A88BF','ARCHIVED','2016-07-19 14:36:28',0),('2016_07_19_07_characters.sql','1E8273FFD4340CBD7BB71D2406E23E9EF7230CFA','ARCHIVED','2016-07-19 14:36:29',0),('2016_07_19_08_characters.sql','FB41FD2F8A7114FEE154021A9D47488C4B12E2A9','ARCHIVED','2016-07-19 14:36:29',0),('2016_08_15_00_characters.sql','BF0B5F453384210CD77C54E262A19B888AAA4095','ARCHIVED','2016-08-14 18:14:32',0),('2016_08_25_00_characters.sql','4AD506C3FCE54238EF452AC07EC562BD41A9D50C','ARCHIVED','2016-08-25 22:54:11',0),('2016_10_17_00_characters.sql','A0EF594CD73690D46A46031137DB0E895F079235','ARCHIVED','2016-10-16 16:33:05',25),('2016_10_25_00_characters.sql','CC894484561CE138C10B69D34F7831CEDFAF496B','ARCHIVED','2016-10-25 17:19:35',0),('2016_11_06_00_characters.sql','C7EC8B65C1BE7722C53BAB79C52C1549054178C0','ARCHIVED','2016-11-06 23:05:44',0),('2016_12_09_00_characters.sql','2A68E4187CE7F7294CBC3804AC39F48B2727E64E','ARCHIVED','2016-12-09 18:38:46',0),('2016_12_26_00_characters.sql','D265DE655DDBFC13E2FA1EB021A435A21189B6E4','ARCHIVED','2016-12-26 18:45:15',0),('2017_01_22_00_characters.sql','62B08B5FB1DA7B207C74DC000C42517A2D6F6BCC','ARCHIVED','2017-01-22 02:06:31',0),('2017_01_29_00_characters.sql','E7475DCC13A0910FF23BF0EFB731629950A73A0D','ARCHIVED','2017-01-29 15:00:00',0),('2017_02_26_00_characters_2016_09_13_00_characters.sql','2EF7AD507D097ABC74FF1E98A65BEC03B12E51C6','ARCHIVED','2017-02-26 19:57:47',0),('2017_04_15_00_characters.sql','F118BA33CD7DDF2EE5673C6749C2965EFFF53C23','ARCHIVED','2017-04-15 12:10:50',0),('2017_04_19_00_characters.sql','5A36FD9015ED024BC085F995F72DC81B47CD1093','RELEASED','2017-04-18 23:16:18',30),('2017_05_08_00_characters.sql','86B5603EEBE1DE0EA56DBB264257967CFE583F46','RELEASED','2017-05-08 23:54:40',0),('2017_05_14_00_characters.sql','3452261F366BFE76BB59C0AAA674FA1513042899','RELEASED','2017-05-14 17:29:04',0),('2017_05_24_00_characters.sql','02701BF57589CD41456A748AEF425CBB2D3E6AD7','RELEASED','2017-05-24 22:00:00',0),('2017_06_04_00_characters.sql','BC80D2B7515CC6E01701070D2DA466727F36DB5E','RELEASED','2017-06-04 14:43:26',0),('2017_08_20_00_characters.sql','8C5BBF6AEAA6C7DE2F40A7D3878C8187A4729F13','RELEASED','2017-08-20 17:00:00',0);
/*!40000 ALTER TABLE `updates` ENABLE KEYS */;
UNLOCK TABLES;
diff --git a/sql/updates/characters/master/2017_08_20_00_characters.sql b/sql/updates/characters/master/2017_08_20_00_characters.sql
new file mode 100644
index 00000000000..f4d354081bf
--- /dev/null
+++ b/sql/updates/characters/master/2017_08_20_00_characters.sql
@@ -0,0 +1,21 @@
+--
+-- Table structure for table `character_queststatus_objectives_criteria`
+--
+DROP TABLE IF EXISTS `character_queststatus_objectives_criteria`;
+CREATE TABLE `character_queststatus_objectives_criteria` (
+ `guid` bigint(20) unsigned NOT NULL,
+ `questObjectiveId` int(10) unsigned NOT NULL,
+ PRIMARY KEY (`guid`,`questObjectiveId`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+--
+-- Table structure for table `character_queststatus_objectives_criteria_progress`
+--
+DROP TABLE IF EXISTS `character_queststatus_objectives_criteria_progress`;
+CREATE TABLE `character_queststatus_objectives_criteria_progress` (
+ `guid` bigint(20) unsigned NOT NULL,
+ `criteriaId` int(10) unsigned NOT NULL,
+ `counter` bigint(20) unsigned NOT NULL,
+ `date` int(10) unsigned NOT NULL DEFAULT '0',
+ PRIMARY KEY (`guid`,`criteriaId`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
diff --git a/src/server/database/Database/Implementation/CharacterDatabase.cpp b/src/server/database/Database/Implementation/CharacterDatabase.cpp
index 34bef1ea62a..ad4998b9543 100644
--- a/src/server/database/Database/Implementation/CharacterDatabase.cpp
+++ b/src/server/database/Database/Implementation/CharacterDatabase.cpp
@@ -94,6 +94,8 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_SEL_CHARACTER_SPELL, "SELECT spell, active, disabled FROM character_spell WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_CHARACTER_QUESTSTATUS, "SELECT quest, status, timer FROM character_queststatus WHERE guid = ? AND status <> 0", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_CHARACTER_QUESTSTATUS_OBJECTIVES, "SELECT quest, objective, data FROM character_queststatus_objectives WHERE guid = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_SEL_CHARACTER_QUESTSTATUS_OBJECTIVES_CRITERIA, "SELECT questObjectiveId FROM character_queststatus_objectives_criteria WHERE guid = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_SEL_CHARACTER_QUESTSTATUS_OBJECTIVES_CRITERIA_PROGRESS, "SELECT criteriaId, counter, date FROM character_queststatus_objectives_criteria_progress WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_CHARACTER_QUESTSTATUS_DAILY, "SELECT quest, time FROM character_queststatus_daily WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_CHARACTER_QUESTSTATUS_WEEKLY, "SELECT quest FROM character_queststatus_weekly WHERE guid = ?", CONNECTION_ASYNC);
@@ -549,6 +551,9 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_UPD_CHAR_TAXIMASK, "UPDATE characters SET taximask = ? WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_CHAR_QUESTSTATUS, "DELETE FROM character_queststatus WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_CHAR_QUESTSTATUS_OBJECTIVES, "DELETE FROM character_queststatus_objectives WHERE guid = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_DEL_CHAR_QUESTSTATUS_OBJECTIVES_CRITERIA, "DELETE FROM character_queststatus_objectives_criteria WHERE guid = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_DEL_CHAR_QUESTSTATUS_OBJECTIVES_CRITERIA_PROGRESS, "DELETE FROM character_queststatus_objectives_criteria_progress WHERE guid = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_DEL_CHAR_QUESTSTATUS_OBJECTIVES_CRITERIA_PROGRESS_BY_CRITERIA, "DELETE FROM character_queststatus_objectives_criteria_progress WHERE guid = ? AND criteriaId = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_CHAR_SOCIAL_BY_GUID, "DELETE FROM character_social WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_CHAR_SOCIAL_BY_FRIEND, "DELETE FROM character_social WHERE friend = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_CHAR_ACHIEVEMENT_BY_ACHIEVEMENT, "DELETE FROM character_achievement WHERE achievement = ? AND guid = ?", CONNECTION_ASYNC);
@@ -596,11 +601,14 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_DEL_CHAR_QUESTSTATUS_BY_QUEST, "DELETE FROM character_queststatus WHERE guid = ? AND quest = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_REP_CHAR_QUESTSTATUS_OBJECTIVES, "REPLACE INTO character_queststatus_objectives (guid, quest, objective, data) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_CHAR_QUESTSTATUS_OBJECTIVES_BY_QUEST, "DELETE FROM character_queststatus_objectives WHERE guid = ? AND quest = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_INS_CHAR_QUESTSTATUS_OBJECTIVES_CRITERIA, "INSERT INTO character_queststatus_objectives_criteria (guid, questObjectiveId) VALUES (?, ?)", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_INS_CHAR_QUESTSTATUS_OBJECTIVES_CRITERIA_PROGRESS, "INSERT INTO character_queststatus_objectives_criteria_progress (guid, criteriaId, counter, date) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_INS_CHAR_QUESTSTATUS_REWARDED, "INSERT IGNORE INTO character_queststatus_rewarded (guid, quest, active) VALUES (?, ?, 1)", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_CHAR_QUESTSTATUS_REWARDED_BY_QUEST, "DELETE FROM character_queststatus_rewarded WHERE guid = ? AND quest = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_UPD_CHAR_QUESTSTATUS_REWARDED_FACTION_CHANGE, "UPDATE character_queststatus_rewarded SET quest = ? WHERE quest = ? AND guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_UPD_CHAR_QUESTSTATUS_REWARDED_ACTIVE, "UPDATE character_queststatus_rewarded SET active = 1 WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_UPD_CHAR_QUESTSTATUS_REWARDED_ACTIVE_BY_QUEST, "UPDATE character_queststatus_rewarded SET active = 0 WHERE quest = ? AND guid = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_DEL_INVALID_QUEST_PROGRESS_CRITERIA, "DELETE FROM character_queststatus_objectives_criteria WHERE questObjectiveId = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_CHAR_SKILL_BY_SKILL, "DELETE FROM character_skills WHERE guid = ? AND skill = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_INS_CHAR_SKILLS, "INSERT INTO character_skills (guid, skill, value, max) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_UPD_CHAR_SKILLS, "UPDATE character_skills SET value = ?, max = ? WHERE guid = ? AND skill = ?", CONNECTION_ASYNC);
diff --git a/src/server/database/Database/Implementation/CharacterDatabase.h b/src/server/database/Database/Implementation/CharacterDatabase.h
index c2ea5136261..b2acafc2308 100644
--- a/src/server/database/Database/Implementation/CharacterDatabase.h
+++ b/src/server/database/Database/Implementation/CharacterDatabase.h
@@ -71,6 +71,8 @@ enum CharacterDatabaseStatements : uint32
CHAR_SEL_CHARACTER_QUESTSTATUS,
CHAR_SEL_CHARACTER_QUESTSTATUS_OBJECTIVES,
+ CHAR_SEL_CHARACTER_QUESTSTATUS_OBJECTIVES_CRITERIA,
+ CHAR_SEL_CHARACTER_QUESTSTATUS_OBJECTIVES_CRITERIA_PROGRESS,
CHAR_SEL_CHARACTER_QUESTSTATUS_DAILY,
CHAR_SEL_CHARACTER_QUESTSTATUS_WEEKLY,
CHAR_SEL_CHARACTER_QUESTSTATUS_MONTHLY,
@@ -450,6 +452,9 @@ enum CharacterDatabaseStatements : uint32
CHAR_UPD_CHAR_TAXIMASK,
CHAR_DEL_CHAR_QUESTSTATUS,
CHAR_DEL_CHAR_QUESTSTATUS_OBJECTIVES,
+ CHAR_DEL_CHAR_QUESTSTATUS_OBJECTIVES_CRITERIA,
+ CHAR_DEL_CHAR_QUESTSTATUS_OBJECTIVES_CRITERIA_PROGRESS,
+ CHAR_DEL_CHAR_QUESTSTATUS_OBJECTIVES_CRITERIA_PROGRESS_BY_CRITERIA,
CHAR_DEL_CHAR_SOCIAL_BY_GUID,
CHAR_DEL_CHAR_SOCIAL_BY_FRIEND,
CHAR_DEL_CHAR_ACHIEVEMENT_BY_ACHIEVEMENT,
@@ -497,11 +502,14 @@ enum CharacterDatabaseStatements : uint32
CHAR_DEL_CHAR_QUESTSTATUS_BY_QUEST,
CHAR_REP_CHAR_QUESTSTATUS_OBJECTIVES,
CHAR_DEL_CHAR_QUESTSTATUS_OBJECTIVES_BY_QUEST,
+ CHAR_INS_CHAR_QUESTSTATUS_OBJECTIVES_CRITERIA,
+ CHAR_INS_CHAR_QUESTSTATUS_OBJECTIVES_CRITERIA_PROGRESS,
CHAR_INS_CHAR_QUESTSTATUS_REWARDED,
CHAR_DEL_CHAR_QUESTSTATUS_REWARDED_BY_QUEST,
CHAR_UPD_CHAR_QUESTSTATUS_REWARDED_FACTION_CHANGE,
CHAR_UPD_CHAR_QUESTSTATUS_REWARDED_ACTIVE,
CHAR_UPD_CHAR_QUESTSTATUS_REWARDED_ACTIVE_BY_QUEST,
+ CHAR_DEL_INVALID_QUEST_PROGRESS_CRITERIA,
CHAR_DEL_CHAR_SKILL_BY_SKILL,
CHAR_INS_CHAR_SKILLS,
CHAR_UPD_CHAR_SKILLS,
diff --git a/src/server/game/Achievements/AchievementMgr.cpp b/src/server/game/Achievements/AchievementMgr.cpp
index b4d7ad07eb6..6ab15152d75 100644
--- a/src/server/game/Achievements/AchievementMgr.cpp
+++ b/src/server/game/Achievements/AchievementMgr.cpp
@@ -272,7 +272,7 @@ void PlayerAchievementMgr::LoadFromDB(PreparedQueryResult achievementResult, Pre
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));
+ stmt->setUInt32(0, id);
CharacterDatabase.Execute(stmt);
continue;
@@ -716,7 +716,7 @@ void GuildAchievementMgr::LoadFromDB(PreparedQueryResult achievementResult, Prep
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));
+ stmt->setUInt32(0, id);
CharacterDatabase.Execute(stmt);
continue;
}
diff --git a/src/server/game/Achievements/CriteriaHandler.cpp b/src/server/game/Achievements/CriteriaHandler.cpp
index cbf296ddb7e..f3bb97ecf4b 100644
--- a/src/server/game/Achievements/CriteriaHandler.cpp
+++ b/src/server/game/Achievements/CriteriaHandler.cpp
@@ -2227,19 +2227,34 @@ void CriteriaMgr::LoadCriteriaList()
if (scenarioStep->CriteriaTreeID)
scenarioCriteriaTreeIds[scenarioStep->CriteriaTreeID] = scenarioStep;
+ std::unordered_map<uint32 /*criteriaTreeID*/, QuestObjective const*> questObjectiveCriteriaTreeIds;
+ for (std::pair<uint32 /*questID*/, Quest const*> itr : sObjectMgr->GetQuestTemplates())
+ {
+ for (QuestObjective const& objective : itr.second->Objectives)
+ {
+ if (objective.Type != QUEST_OBJECTIVE_CRITERIA_TREE)
+ continue;
+
+ if (objective.ObjectID)
+ questObjectiveCriteriaTreeIds[objective.ObjectID] = &objective;
+ }
+ }
+
// 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)
+ QuestObjective const* questObjective = GetEntry(questObjectiveCriteriaTreeIds, tree);
+ if (!achievement && !scenarioStep && !questObjective)
continue;
CriteriaTree* criteriaTree = new CriteriaTree();
criteriaTree->ID = tree->ID;
criteriaTree->Achievement = achievement;
criteriaTree->ScenarioStep = scenarioStep;
+ criteriaTree->QuestObjective = questObjective;
criteriaTree->Entry = tree;
_criteriaTrees[criteriaTree->Entry->ID] = criteriaTree;
@@ -2274,6 +2289,7 @@ void CriteriaMgr::LoadCriteriaList()
uint32 criterias = 0;
uint32 guildCriterias = 0;
uint32 scenarioCriterias = 0;
+ uint32 questObjectiveCriterias = 0;
for (CriteriaEntry const* criteriaEntry : sCriteriaStore)
{
ASSERT(criteriaEntry->Type < CRITERIA_TYPE_TOTAL, "CRITERIA_TYPE_TOTAL must be greater than or equal to %u but is currently equal to %u",
@@ -2305,6 +2321,8 @@ void CriteriaMgr::LoadCriteriaList()
}
else if (tree->ScenarioStep)
criteria->FlagsCu |= CRITERIA_FLAG_CU_SCENARIO;
+ else if (tree->QuestObjective)
+ criteria->FlagsCu |= CRITERIA_FLAG_CU_QUEST_OBJECTIVE;
}
if (criteria->FlagsCu & (CRITERIA_FLAG_CU_PLAYER | CRITERIA_FLAG_CU_ACCOUNT))
@@ -2325,6 +2343,12 @@ void CriteriaMgr::LoadCriteriaList()
_scenarioCriteriasByType[criteriaEntry->Type].push_back(criteria);
}
+ if (criteria->FlagsCu & CRITERIA_FLAG_CU_QUEST_OBJECTIVE)
+ {
+ ++questObjectiveCriterias;
+ _questObjectiveCriteriasByType[criteriaEntry->Type].push_back(criteria);
+ }
+
if (criteriaEntry->StartTimer)
_criteriasByTimedType[criteriaEntry->StartEvent].push_back(criteria);
}
@@ -2332,7 +2356,7 @@ void CriteriaMgr::LoadCriteriaList()
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));
+ TC_LOG_INFO("server.loading", ">> Loaded %u criteria, %u guild criteria, %u scenario criteria and %u quest objective criteria in %u ms.", criterias, guildCriterias, scenarioCriterias, questObjectiveCriterias, GetMSTimeDiffToNow(oldMSTime));
}
void CriteriaMgr::LoadCriteriaData()
diff --git a/src/server/game/Achievements/CriteriaHandler.h b/src/server/game/Achievements/CriteriaHandler.h
index c8b96b144cd..7d14df68be1 100644
--- a/src/server/game/Achievements/CriteriaHandler.h
+++ b/src/server/game/Achievements/CriteriaHandler.h
@@ -34,6 +34,7 @@ struct AchievementEntry;
struct CriteriaEntry;
struct CriteriaTreeEntry;
struct ModifierTreeEntry;
+struct QuestObjective;
struct ScenarioStepEntry;
struct ModifierTreeNode
@@ -44,10 +45,11 @@ struct ModifierTreeNode
enum CriteriaFlagsCu
{
- CRITERIA_FLAG_CU_PLAYER = 0x1,
- CRITERIA_FLAG_CU_ACCOUNT = 0x2,
- CRITERIA_FLAG_CU_GUILD = 0x4,
- CRITERIA_FLAG_CU_SCENARIO = 0x8
+ CRITERIA_FLAG_CU_PLAYER = 0x1,
+ CRITERIA_FLAG_CU_ACCOUNT = 0x2,
+ CRITERIA_FLAG_CU_GUILD = 0x4,
+ CRITERIA_FLAG_CU_SCENARIO = 0x8,
+ CRITERIA_FLAG_CU_QUEST_OBJECTIVE = 0x10
};
struct Criteria
@@ -66,6 +68,7 @@ struct CriteriaTree
CriteriaTreeEntry const* Entry = nullptr;
AchievementEntry const* Achievement = nullptr;
ScenarioStepEntry const* ScenarioStep = nullptr;
+ QuestObjective const* QuestObjective = nullptr;
struct Criteria const* Criteria = nullptr;
std::vector<CriteriaTree const*> Children;
};
@@ -331,6 +334,11 @@ public:
return _scenarioCriteriasByType[type];
}
+ CriteriaList const& GetQuestObjectiveCriteriaByType(CriteriaTypes type) const
+ {
+ return _questObjectiveCriteriasByType[type];
+ }
+
CriteriaTreeList const* GetCriteriaTreesByCriteria(uint32 criteriaId) const
{
auto itr = _criteriaTreeByCriteria.find(criteriaId);
@@ -395,6 +403,7 @@ private:
CriteriaList _criteriasByType[CRITERIA_TYPE_TOTAL];
CriteriaList _guildCriteriasByType[CRITERIA_TYPE_TOTAL];
CriteriaList _scenarioCriteriasByType[CRITERIA_TYPE_TOTAL];
+ CriteriaList _questObjectiveCriteriasByType[CRITERIA_TYPE_TOTAL];
CriteriaList _criteriasByTimedType[CRITERIA_TIMED_TYPE_MAX];
};
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 9f5a82f96ea..e2611e9c9ac 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -89,6 +89,7 @@
#include "PetPackets.h"
#include "QueryHolder.h"
#include "QuestDef.h"
+#include "QuestObjectiveCriteriaMgr.h"
#include "QuestPackets.h"
#include "Realm.h"
#include "ReputationMgr.h"
@@ -346,6 +347,7 @@ Player::Player(WorldSession* session) : Unit(true), m_sceneMgr(this)
m_achievementMgr = new PlayerAchievementMgr(this);
m_reputationMgr = new ReputationMgr(this);
+ m_questObjectiveCriteriaMgr = Trinity::make_unique<QuestObjectiveCriteriaMgr>(this);
for (uint8 i = 0; i < MAX_CUF_PROFILES; ++i)
_CUFProfiles[i] = nullptr;
@@ -14745,6 +14747,11 @@ void Player::AddQuestAndCheckCompletion(Quest const* quest, Object* questGiver)
{
AddQuest(quest, questGiver);
+ for (QuestObjective const& obj : quest->GetObjectives())
+ if (obj.Type == QUEST_OBJECTIVE_CRITERIA_TREE)
+ if (m_questObjectiveCriteriaMgr->HasCompletedObjective(&obj))
+ KillCreditCriteriaTreeObjective(obj);
+
if (CanCompleteQuest(quest->GetQuestId()))
CompleteQuest(quest->GetQuestId());
@@ -14900,9 +14907,22 @@ void Player::AddQuest(Quest const* quest, Object* questGiver)
AdjustQuestReqItemCount(quest);
for (QuestObjective const& obj : quest->GetObjectives())
- if (obj.Type == QUEST_OBJECTIVE_MIN_REPUTATION || obj.Type == QUEST_OBJECTIVE_MAX_REPUTATION)
- if (FactionEntry const* factionEntry = sFactionStore.LookupEntry(obj.ObjectID))
- GetReputationMgr().SetVisible(factionEntry);
+ {
+ switch (obj.Type)
+ {
+ case QUEST_OBJECTIVE_MIN_REPUTATION:
+ case QUEST_OBJECTIVE_MAX_REPUTATION:
+ if (FactionEntry const* factionEntry = sFactionStore.LookupEntry(obj.ObjectID))
+ GetReputationMgr().SetVisible(factionEntry);
+ break;
+ case QUEST_OBJECTIVE_CRITERIA_TREE:
+ if (quest->HasFlagEx(QUEST_FLAGS_EX_CLEAR_PROGRESS_OF_CRITERIA_TREE_OBJECTIVES_ON_ACCEPT))
+ m_questObjectiveCriteriaMgr->ResetCriteriaTree(obj.ObjectID);
+ break;
+ default:
+ break;
+ }
+ }
uint32 qtime = 0;
if (quest->HasSpecialFlag(QUEST_SPECIAL_FLAGS_TIMED))
@@ -16563,6 +16583,21 @@ void Player::TalkedToCreature(uint32 entry, ObjectGuid guid)
}
}
+void Player::KillCreditCriteriaTreeObjective(QuestObjective const& questObjective)
+{
+ if (questObjective.Type != QUEST_OBJECTIVE_CRITERIA_TREE)
+ return;
+
+ if (GetQuestStatus(questObjective.QuestID) == QUEST_STATUS_INCOMPLETE)
+ {
+ SetQuestObjectiveData(questObjective, 1);
+ SendQuestUpdateAddCreditSimple(questObjective);
+
+ if (CanCompleteQuest(questObjective.QuestID))
+ CompleteQuest(questObjective.QuestID);
+ }
+}
+
void Player::MoneyChanged(uint64 value)
{
for (uint8 i = 0; i < MAX_QUEST_LOG_SIZE; ++i)
@@ -16813,6 +16848,7 @@ bool Player::IsQuestObjectiveComplete(QuestObjective const& objective) const
return false;
break;
case QUEST_OBJECTIVE_AREATRIGGER:
+ case QUEST_OBJECTIVE_CRITERIA_TREE:
if (!GetQuestObjectiveData(quest, objective.StorageIndex))
return false;
break;
@@ -17389,6 +17425,7 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder)
// 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));
+ m_questObjectiveCriteriaMgr->LoadFromDB(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_QUEST_STATUS_OBJECTIVES_CRITERIA), holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_QUEST_STATUS_OBJECTIVES_CRITERIA_PROGRESS));
uint64 money = fields[8].GetUInt64();
if (money > MAX_MONEY_AMOUNT)
@@ -18056,6 +18093,7 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder)
}
m_achievementMgr->CheckAllAchievementCriteria(this);
+ m_questObjectiveCriteriaMgr->CheckAllQuestObjectiveCriteria(this);
return true;
}
@@ -19966,6 +20004,7 @@ void Player::SaveToDB(bool create /*=false*/)
_SaveSkills(trans);
m_achievementMgr->SaveToDB(trans);
m_reputationMgr->SaveToDB(trans);
+ m_questObjectiveCriteriaMgr->SaveToDB(trans);
_SaveEquipmentSets(trans);
GetSession()->SaveTutorialsData(trans); // changed only while character in game
_SaveInstanceTimeRestrictions(trans);
@@ -23448,6 +23487,7 @@ void Player::SendInitialPacketsBeforeAddToMap()
SendEquipmentSetList();
m_achievementMgr->SendAllData(this);
+ m_questObjectiveCriteriaMgr->SendAllData(this);
/// SMSG_LOGIN_SETTIMESPEED
static float const TimeSpeed = 0.01666667f;
@@ -25876,11 +25916,13 @@ void Player::RemoveCriteriaTimer(CriteriaTimedTypes type, uint32 entry)
void Player::ResetCriteria(CriteriaTypes type, uint64 miscValue1 /*= 0*/, uint64 miscValue2 /*= 0*/, bool evenIfCriteriaComplete /* = false*/)
{
m_achievementMgr->ResetCriteria(type, miscValue1, miscValue2, evenIfCriteriaComplete);
+ m_questObjectiveCriteriaMgr->ResetCriteria(type, miscValue1, miscValue2, evenIfCriteriaComplete);
}
void Player::UpdateCriteria(CriteriaTypes type, uint64 miscValue1 /*= 0*/, uint64 miscValue2 /*= 0*/, uint64 miscValue3 /*= 0*/, Unit* unit /*= NULL*/)
{
m_achievementMgr->UpdateCriteria(type, miscValue1, miscValue2, miscValue3, unit, this);
+ m_questObjectiveCriteriaMgr->UpdateCriteria(type, miscValue1, miscValue2, miscValue3, unit, this);
// Update only individual achievement criteria here, otherwise we may get multiple updates
// from a single boss kill
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index 414515b5e36..4f3f270fdc6 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -77,6 +77,7 @@ class PlayerAI;
class PlayerAchievementMgr;
class PlayerMenu;
class PlayerSocial;
+class QuestObjectiveCriteriaMgr;
class ReputationMgr;
class RestMgr;
class SpellCastTargets;
@@ -785,6 +786,8 @@ enum PlayerLoginQueryIndex
PLAYER_LOGIN_QUERY_LOAD_SPELLS,
PLAYER_LOGIN_QUERY_LOAD_QUEST_STATUS,
PLAYER_LOGIN_QUERY_LOAD_QUEST_STATUS_OBJECTIVES,
+ PLAYER_LOGIN_QUERY_LOAD_QUEST_STATUS_OBJECTIVES_CRITERIA,
+ PLAYER_LOGIN_QUERY_LOAD_QUEST_STATUS_OBJECTIVES_CRITERIA_PROGRESS,
PLAYER_LOGIN_QUERY_LOAD_DAILY_QUEST_STATUS,
PLAYER_LOGIN_QUERY_LOAD_REPUTATION,
PLAYER_LOGIN_QUERY_LOAD_INVENTORY,
@@ -1415,6 +1418,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
void KilledPlayerCredit();
void KillCreditGO(uint32 entry, ObjectGuid guid = ObjectGuid::Empty);
void TalkedToCreature(uint32 entry, ObjectGuid guid);
+ void KillCreditCriteriaTreeObjective(QuestObjective const& questObjective);
void MoneyChanged(uint64 value);
void ReputationChanged(FactionEntry const* factionEntry);
void CurrencyChanged(uint32 currencyId, int32 change);
@@ -2659,6 +2663,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
PlayerAchievementMgr* m_achievementMgr;
ReputationMgr* m_reputationMgr;
+ std::unique_ptr<QuestObjectiveCriteriaMgr> m_questObjectiveCriteriaMgr;
uint32 m_ChampioningFaction;
diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp
index 17ddf3ed8a6..1ee32b74991 100644
--- a/src/server/game/Handlers/CharacterHandler.cpp
+++ b/src/server/game/Handlers/CharacterHandler.cpp
@@ -113,6 +113,14 @@ bool LoginQueryHolder::Initialize()
stmt->setUInt64(0, lowGuid);
res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_QUEST_STATUS_OBJECTIVES, stmt);
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_QUESTSTATUS_OBJECTIVES_CRITERIA);
+ stmt->setUInt64(0, lowGuid);
+ res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_QUEST_STATUS_OBJECTIVES_CRITERIA, stmt);
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_QUESTSTATUS_OBJECTIVES_CRITERIA_PROGRESS);
+ stmt->setUInt64(0, lowGuid);
+ res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_QUEST_STATUS_OBJECTIVES_CRITERIA_PROGRESS, stmt);
+
stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_QUESTSTATUS_DAILY);
stmt->setUInt64(0, lowGuid);
res &= SetPreparedQuery(PLAYER_LOGIN_QUERY_LOAD_DAILY_QUEST_STATUS, stmt);
diff --git a/src/server/game/Quests/QuestDef.h b/src/server/game/Quests/QuestDef.h
index 49bce2fe583..700216ef7e8 100644
--- a/src/server/game/Quests/QuestDef.h
+++ b/src/server/game/Quests/QuestDef.h
@@ -132,7 +132,7 @@ enum QuestGiverStatus
DIALOG_STATUS_SCRIPTED_NO_STATUS = 0x1000
};
-enum QuestFlags
+enum QuestFlags : uint32
{
QUEST_FLAGS_NONE = 0x00000000,
QUEST_FLAGS_STAY_ALIVE = 0x00000001, // Not used currently
@@ -164,7 +164,7 @@ enum QuestFlags
};
// last checked in 19802
-enum QuestFlagsEx
+enum QuestFlagsEx : uint32
{
QUEST_FLAGS_EX_NONE = 0x0000000,
QUEST_FLAGS_EX_KEEP_ADDITIONAL_ITEMS = 0x0000001,
@@ -335,6 +335,8 @@ class TC_GAME_API Quest
bool HasSpecialFlag(uint32 flag) const { return (SpecialFlags & flag) != 0; }
void SetSpecialFlag(uint32 flag) { SpecialFlags |= flag; }
+ bool HasFlagEx(QuestFlagsEx flag) const { return (FlagsEx & uint32(flag)) != 0; }
+
// table data accessors:
uint32 GetQuestId() const { return ID; }
uint32 GetQuestType() const { return Type; }
diff --git a/src/server/game/Quests/QuestObjectiveCriteriaMgr.cpp b/src/server/game/Quests/QuestObjectiveCriteriaMgr.cpp
new file mode 100644
index 00000000000..965cbd804d1
--- /dev/null
+++ b/src/server/game/Quests/QuestObjectiveCriteriaMgr.cpp
@@ -0,0 +1,320 @@
+/*
+ * Copyright (C) 2008-2017 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 "QuestObjectiveCriteriaMgr.h"
+#include "AchievementPackets.h"
+#include "DatabaseEnv.h"
+#include "DB2Structure.h"
+#include "Log.h"
+#include "ObjectMgr.h"
+#include "Player.h"
+
+QuestObjectiveCriteriaMgr::QuestObjectiveCriteriaMgr(Player* owner) : _owner(owner)
+{
+}
+
+QuestObjectiveCriteriaMgr::~QuestObjectiveCriteriaMgr()
+{
+}
+
+void QuestObjectiveCriteriaMgr::CheckAllQuestObjectiveCriteria(Player* referencePlayer)
+{
+ // suppress sending packets
+ for (uint32 i = 0; i < CRITERIA_TYPE_TOTAL; ++i)
+ UpdateCriteria(CriteriaTypes(i), 0, 0, 0, nullptr, referencePlayer);
+}
+
+void QuestObjectiveCriteriaMgr::Reset()
+{
+ for (auto& criteriaProgres : _criteriaProgress)
+ SendCriteriaProgressRemoved(criteriaProgres.first);
+
+ _criteriaProgress.clear();
+
+ DeleteFromDB(_owner->GetGUID());
+
+ // re-fill data
+ CheckAllQuestObjectiveCriteria(_owner);
+}
+
+void QuestObjectiveCriteriaMgr::DeleteFromDB(ObjectGuid const& guid)
+{
+ SQLTransaction trans = CharacterDatabase.BeginTransaction();
+
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_QUESTSTATUS_OBJECTIVES_CRITERIA);
+ stmt->setUInt64(0, guid.GetCounter());
+ trans->Append(stmt);
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_QUESTSTATUS_OBJECTIVES_CRITERIA_PROGRESS);
+ stmt->setUInt64(0, guid.GetCounter());
+ trans->Append(stmt);
+
+ CharacterDatabase.CommitTransaction(trans);
+}
+
+void QuestObjectiveCriteriaMgr::LoadFromDB(PreparedQueryResult objectiveResult, PreparedQueryResult criteriaResult)
+{
+ if (objectiveResult)
+ {
+ do
+ {
+ uint32 objectiveId = (*objectiveResult)[0].GetUInt32();
+
+ QuestObjective const* objective = sObjectMgr->GetQuestObjective(objectiveId);
+ if (!objective)
+ continue;
+
+ _completedObjectives.insert(objectiveId);
+
+ } while (objectiveResult->NextRow());
+ }
+
+ if (criteriaResult)
+ {
+ time_t now = time(nullptr);
+ do
+ {
+ Field* fields = criteriaResult->Fetch();
+ uint32 criteriaId = fields[0].GetUInt32();
+ uint64 counter = fields[1].GetUInt64();
+ time_t date = time_t(fields[2].GetUInt32());
+
+ Criteria const* criteria = sCriteriaMgr->GetCriteria(criteriaId);
+ if (!criteria)
+ {
+ // Removing non-existing criteria data for all characters
+ TC_LOG_ERROR("criteria.quest", "Non-existing quest objective criteria %u data has been removed from the table `character_queststatus_objectives_criteria_progress`.", criteriaId);
+
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_INVALID_QUEST_PROGRESS_CRITERIA);
+ stmt->setUInt32(0, criteriaId);
+ CharacterDatabase.Execute(stmt);
+
+ continue;
+ }
+
+ if (criteria->Entry->StartTimer && time_t(date + criteria->Entry->StartTimer) < now)
+ continue;
+
+ CriteriaProgress& progress = _criteriaProgress[criteriaId];
+ progress.Counter = counter;
+ progress.Date = date;
+ progress.Changed = false;
+ } while (criteriaResult->NextRow());
+ }
+}
+
+void QuestObjectiveCriteriaMgr::SaveToDB(SQLTransaction& trans)
+{
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_QUESTSTATUS_OBJECTIVES_CRITERIA);
+ stmt->setUInt64(0, _owner->GetGUID().GetCounter());
+ trans->Append(stmt);
+
+ if (!_completedObjectives.empty())
+ {
+ for (uint32 completedObjectiveId : _completedObjectives)
+ {
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHAR_QUESTSTATUS_OBJECTIVES_CRITERIA);
+ stmt->setUInt64(0, _owner->GetGUID().GetCounter());
+ stmt->setUInt32(1, completedObjectiveId);
+ trans->Append(stmt);
+ }
+ }
+
+ if (!_criteriaProgress.empty())
+ {
+ for (auto& criteriaProgres : _criteriaProgress)
+ {
+ if (!criteriaProgres.second.Changed)
+ continue;
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_QUESTSTATUS_OBJECTIVES_CRITERIA_PROGRESS_BY_CRITERIA);
+ stmt->setUInt64(0, _owner->GetGUID().GetCounter());
+ stmt->setUInt32(1, criteriaProgres.first);
+ trans->Append(stmt);
+
+ if (criteriaProgres.second.Counter)
+ {
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHAR_QUESTSTATUS_OBJECTIVES_CRITERIA_PROGRESS);
+ stmt->setUInt64(0, _owner->GetGUID().GetCounter());
+ stmt->setUInt32(1, criteriaProgres.first);
+ stmt->setUInt64(2, criteriaProgres.second.Counter);
+ stmt->setUInt32(3, uint32(criteriaProgres.second.Date));
+ trans->Append(stmt);
+ }
+
+ criteriaProgres.second.Changed = false;
+ }
+ }
+}
+
+void QuestObjectiveCriteriaMgr::ResetCriteria(CriteriaTypes type, uint64 miscValue1, uint64 miscValue2, bool evenIfCriteriaComplete)
+{
+ TC_LOG_DEBUG("criteria.quest", "QuestObjectiveCriteriaMgr::ResetCriteria(%u, " UI64FMTD ", " UI64FMTD ")", type, miscValue1, miscValue2);
+
+ // disable for gamemasters with GM-mode enabled
+ if (_owner->IsGameMaster())
+ return;
+
+ CriteriaList const& playerCriteriaList = GetCriteriaByType(type);
+ for (Criteria const* playerCriteria : playerCriteriaList)
+ {
+ if (playerCriteria->Entry->FailEvent != miscValue1 || (playerCriteria->Entry->FailAsset && playerCriteria->Entry->FailAsset != miscValue2))
+ continue;
+
+ std::vector<CriteriaTree const*> const* trees = sCriteriaMgr->GetCriteriaTreesByCriteria(playerCriteria->ID);
+ bool allComplete = true;
+ for (CriteriaTree const* tree : *trees)
+ {
+ // don't update already completed criteria if not forced
+ if (!(IsCompletedCriteriaTree(tree) && !evenIfCriteriaComplete))
+ {
+ allComplete = false;
+ break;
+ }
+ }
+
+ if (allComplete)
+ continue;
+
+ RemoveCriteriaProgress(playerCriteria);
+ }
+}
+
+void QuestObjectiveCriteriaMgr::ResetCriteriaTree(uint32 criteriaTreeId)
+{
+ CriteriaTree const* tree = sCriteriaMgr->GetCriteriaTree(criteriaTreeId);
+ if (!tree)
+ return;
+
+ CriteriaMgr::WalkCriteriaTree(tree, [this](CriteriaTree const* criteriaTree)
+ {
+ RemoveCriteriaProgress(criteriaTree->Criteria);
+ });
+}
+
+void QuestObjectiveCriteriaMgr::SendAllData(Player const* /*receiver*/) const
+{
+ for (const auto& criteriaProgres : _criteriaProgress)
+ {
+ WorldPackets::Achievement::CriteriaUpdate criteriaUpdate;
+
+ criteriaUpdate.CriteriaID = criteriaProgres.first;
+ criteriaUpdate.Quantity = criteriaProgres.second.Counter;
+ criteriaUpdate.PlayerGUID = _owner->GetGUID();
+ criteriaUpdate.Flags = 0;
+
+ criteriaUpdate.CurrentTime = criteriaProgres.second.Date;
+ criteriaUpdate.CreationTime = 0;
+
+ SendPacket(criteriaUpdate.Write());
+ }
+}
+
+void QuestObjectiveCriteriaMgr::CompletedObjective(QuestObjective const* questObjective, Player* referencePlayer)
+{
+ // disable for gamemasters with GM-mode enabled
+ if (_owner->IsGameMaster())
+ return;
+
+ if (HasCompletedObjective(questObjective))
+ return;
+
+ referencePlayer->KillCreditCriteriaTreeObjective(*questObjective);
+
+ TC_LOG_INFO("criteria.quest", "QuestObjectiveCriteriaMgr::CompletedObjective(%u). %s", questObjective->ID, GetOwnerInfo().c_str());
+
+ _completedObjectives.insert(questObjective->ID);
+}
+
+bool QuestObjectiveCriteriaMgr::HasCompletedObjective(QuestObjective const* questObjective) const
+{
+ return _completedObjectives.find(questObjective->ID) != _completedObjectives.end();
+}
+
+void QuestObjectiveCriteriaMgr::SendCriteriaUpdate(Criteria const* criteria, CriteriaProgress const* progress, uint32 timeElapsed, bool timedCompleted) const
+{
+ WorldPackets::Achievement::CriteriaUpdate criteriaUpdate;
+
+ 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
+
+ criteriaUpdate.CurrentTime = progress->Date;
+ criteriaUpdate.ElapsedTime = timeElapsed;
+ criteriaUpdate.CreationTime = 0;
+
+ SendPacket(criteriaUpdate.Write());
+}
+
+void QuestObjectiveCriteriaMgr::SendCriteriaProgressRemoved(uint32 criteriaId)
+{
+ WorldPackets::Achievement::CriteriaDeleted criteriaDeleted;
+ criteriaDeleted.CriteriaID = criteriaId;
+ SendPacket(criteriaDeleted.Write());
+}
+
+bool QuestObjectiveCriteriaMgr::CanUpdateCriteriaTree(Criteria const* criteria, CriteriaTree const* tree, Player* referencePlayer) const
+{
+ QuestObjective const* objective = tree->QuestObjective;
+ if (!objective)
+ return false;
+
+ if (HasCompletedObjective(objective))
+ {
+ TC_LOG_TRACE("criteria.quest", "QuestObjectiveCriteriaMgr::CanUpdateCriteriaTree: (Id: %u Type %s Quest Objective %u) Objective already completed",
+ criteria->ID, CriteriaMgr::GetCriteriaTypeString(criteria->Entry->Type), objective->ID);
+ return false;
+ }
+
+ return CriteriaHandler::CanUpdateCriteriaTree(criteria, tree, referencePlayer);
+}
+
+bool QuestObjectiveCriteriaMgr::CanCompleteCriteriaTree(CriteriaTree const* tree)
+{
+ QuestObjective const* objective = tree->QuestObjective;
+ if (!objective)
+ return false;
+
+ return CriteriaHandler::CanCompleteCriteriaTree(tree);
+}
+
+void QuestObjectiveCriteriaMgr::CompletedCriteriaTree(CriteriaTree const* tree, Player* referencePlayer)
+{
+ QuestObjective const* objective = tree->QuestObjective;
+ if (!objective)
+ return;
+
+ CompletedObjective(objective, referencePlayer);
+}
+
+void QuestObjectiveCriteriaMgr::SendPacket(WorldPacket const* data) const
+{
+ _owner->SendDirectMessage(data);
+}
+
+std::string QuestObjectiveCriteriaMgr::GetOwnerInfo() const
+{
+ return Trinity::StringFormat("%s %s", _owner->GetGUID().ToString().c_str(), _owner->GetName().c_str());
+}
+
+CriteriaList const& QuestObjectiveCriteriaMgr::GetCriteriaByType(CriteriaTypes type) const
+{
+ return sCriteriaMgr->GetQuestObjectiveCriteriaByType(type);
+}
diff --git a/src/server/game/Quests/QuestObjectiveCriteriaMgr.h b/src/server/game/Quests/QuestObjectiveCriteriaMgr.h
new file mode 100644
index 00000000000..76c6bbb8d1d
--- /dev/null
+++ b/src/server/game/Quests/QuestObjectiveCriteriaMgr.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2008-2017 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 QuestObjectiveCriteriaMgr_h__
+#define QuestObjectiveCriteriaMgr_h__
+
+#include "CriteriaHandler.h"
+
+class TC_GAME_API QuestObjectiveCriteriaMgr : public CriteriaHandler
+{
+public:
+ explicit QuestObjectiveCriteriaMgr(Player* owner);
+ ~QuestObjectiveCriteriaMgr();
+
+ void CheckAllQuestObjectiveCriteria(Player* referencePlayer);
+
+ void Reset() override;
+
+ static void DeleteFromDB(ObjectGuid const& guid);
+ void LoadFromDB(PreparedQueryResult objectiveResult, PreparedQueryResult criteriaResult);
+ void SaveToDB(SQLTransaction& trans);
+
+ void ResetCriteria(CriteriaTypes type, uint64 miscValue1 = 0, uint64 miscValue2 = 0, bool evenIfCriteriaComplete = false);
+ void ResetCriteriaTree(uint32 criteriaTreeId);
+
+ void SendAllData(Player const* receiver) const override;
+
+ void CompletedObjective(QuestObjective const* questObjective, Player* referencePlayer);
+ bool HasCompletedObjective(QuestObjective const* questObjective) const;
+
+protected:
+ void SendCriteriaUpdate(Criteria const* entry, CriteriaProgress const* progress, uint32 timeElapsed, bool timedCompleted) const override;
+
+ void SendCriteriaProgressRemoved(uint32 criteriaId) override;
+
+ 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 SendPacket(WorldPacket const* data) const override;
+
+ std::string GetOwnerInfo() const override;
+ CriteriaList const& GetCriteriaByType(CriteriaTypes type) const override;
+
+private:
+ Player* _owner;
+ std::unordered_set<uint32> _completedObjectives;
+};
+
+#endif