aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKrudor <erikstrandberg93@hotmail.com>2016-11-06 23:30:49 +0100
committerShauren <shauren.trinity@gmail.com>2016-11-06 23:30:49 +0100
commit8444ab736568667cb6425757ce5f832cb6068379 (patch)
tree375c6a9d25b9d5a4d351f4e3a7c0b52526dd816f
parent9d88e78961cc92c2914ffb25333f35433a0c9682 (diff)
Core/Instances: Implemented base scenario system and objectives in dungeons
Closes #17905 Closes #18034
-rw-r--r--sql/base/characters_database.sql2
-rw-r--r--sql/updates/characters/master/2016_11_06_00_characters.sql11
-rw-r--r--sql/updates/hotfixes/master/2016_11_06_02_hotfixes.sql57
-rw-r--r--sql/updates/world/master/2016_11_06_00_world.sql233
-rw-r--r--src/server/database/Database/Implementation/CharacterDatabase.cpp8
-rw-r--r--src/server/database/Database/Implementation/CharacterDatabase.h7
-rw-r--r--src/server/database/Database/Implementation/HotfixDatabase.cpp9
-rw-r--r--src/server/database/Database/Implementation/HotfixDatabase.h6
-rw-r--r--src/server/game/Achievements/CriteriaHandler.cpp6
-rw-r--r--src/server/game/DataStores/DB2LoadInfo.h37
-rw-r--r--src/server/game/DataStores/DB2Stores.cpp4
-rw-r--r--src/server/game/DataStores/DB2Stores.h2
-rw-r--r--src/server/game/DataStores/DB2Structure.h29
-rw-r--r--src/server/game/DataStores/DBCEnums.h6
-rw-r--r--src/server/game/Entities/Object/Object.cpp10
-rw-r--r--src/server/game/Entities/Object/Object.h3
-rw-r--r--src/server/game/Entities/Player/KillRewarder.cpp7
-rw-r--r--src/server/game/Entities/Player/Player.cpp18
-rw-r--r--src/server/game/Handlers/ScenarioHandler.cpp43
-rw-r--r--src/server/game/Instances/InstanceSaveMgr.cpp8
-rw-r--r--src/server/game/Instances/InstanceScript.cpp4
-rw-r--r--src/server/game/Maps/Map.cpp13
-rw-r--r--src/server/game/Maps/Map.h4
-rw-r--r--src/server/game/Maps/MapInstanced.cpp9
-rw-r--r--src/server/game/Maps/MapInstanced.h2
-rw-r--r--src/server/game/Scenarios/InstanceScenario.cpp172
-rw-r--r--src/server/game/Scenarios/InstanceScenario.h44
-rw-r--r--src/server/game/Scenarios/Scenario.cpp311
-rw-r--r--src/server/game/Scenarios/Scenario.h101
-rw-r--r--src/server/game/Scenarios/ScenarioMgr.cpp214
-rw-r--r--src/server/game/Scenarios/ScenarioMgr.h131
-rw-r--r--src/server/game/Server/Packets/AchievementPackets.cpp24
-rw-r--r--src/server/game/Server/Packets/AchievementPackets.h2
-rw-r--r--src/server/game/Server/Packets/AllPackets.h1
-rw-r--r--src/server/game/Server/Packets/ScenarioPackets.cpp129
-rw-r--r--src/server/game/Server/Packets/ScenarioPackets.h125
-rw-r--r--src/server/game/Server/Protocol/Opcodes.cpp14
-rw-r--r--src/server/game/Server/WorldSession.h8
-rw-r--r--src/server/game/World/World.cpp8
39 files changed, 1786 insertions, 36 deletions
diff --git a/sql/base/characters_database.sql b/sql/base/characters_database.sql
index 6c7aef6c65f..b6c209edd06 100644
--- a/sql/base/characters_database.sql
+++ b/sql/base/characters_database.sql
@@ -3245,7 +3245,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','RELEASED','2016-10-16 16:33:05',25),('2016_10_25_00_characters.sql','CC894484561CE138C10B69D34F7831CEDFAF496B','RELEASED','2016-10-25 17:19:35',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','RELEASED','2016-10-16 16:33:05',25),('2016_10_25_00_characters.sql','CC894484561CE138C10B69D34F7831CEDFAF496B','RELEASED','2016-10-25 17:19:35',0),('2016_11_06_00_characters.sql','C7EC8B65C1BE7722C53BAB79C52C1549054178C0','RELEASED','2016-11-06 23:05:44',0);
/*!40000 ALTER TABLE `updates` ENABLE KEYS */;
UNLOCK TABLES;
diff --git a/sql/updates/characters/master/2016_11_06_00_characters.sql b/sql/updates/characters/master/2016_11_06_00_characters.sql
new file mode 100644
index 00000000000..1b4f22e24e7
--- /dev/null
+++ b/sql/updates/characters/master/2016_11_06_00_characters.sql
@@ -0,0 +1,11 @@
+--
+-- Table structure for table `instance_scenario_progress`
+--
+DROP TABLE IF EXISTS `instance_scenario_progress`;
+CREATE TABLE `instance_scenario_progress` (
+ `id` int(10) unsigned NOT NULL,
+ `criteria` int(10) unsigned NOT NULL,
+ `counter` bigint(20) unsigned NOT NULL,
+ `date` int(10) unsigned NOT NULL DEFAULT '0',
+ PRIMARY KEY (`id`,`criteria`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
diff --git a/sql/updates/hotfixes/master/2016_11_06_02_hotfixes.sql b/sql/updates/hotfixes/master/2016_11_06_02_hotfixes.sql
new file mode 100644
index 00000000000..fae5062d5fc
--- /dev/null
+++ b/sql/updates/hotfixes/master/2016_11_06_02_hotfixes.sql
@@ -0,0 +1,57 @@
+--
+-- Table structure for table `scenario`
+--
+DROP TABLE IF EXISTS `scenario`;
+CREATE TABLE `scenario` (
+ `ID` int(10) unsigned NOT NULL DEFAULT '0',
+ `Name` text,
+ `Data` smallint(5) unsigned NOT NULL DEFAULT '0',
+ `Flags` tinyint(3) unsigned NOT NULL DEFAULT '0',
+ `Type` tinyint(3) unsigned NOT NULL DEFAULT '0',
+ `VerifiedBuild` smallint(6) NOT NULL DEFAULT '0',
+ PRIMARY KEY (`ID`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8;
+
+--
+-- Table structure for table `scenario_locale`
+--
+DROP TABLE IF EXISTS `scenario_locale`;
+CREATE TABLE `scenario_locale` (
+ `ID` int(10) unsigned NOT NULL DEFAULT '0',
+ `locale` varchar(4) NOT NULL,
+ `Name_lang` text,
+ `VerifiedBuild` smallint(6) NOT NULL DEFAULT '0',
+ PRIMARY KEY (`ID`,`locale`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8;
+
+--
+-- Table structure for table `scenario_step`
+--
+DROP TABLE IF EXISTS `scenario_step`;
+CREATE TABLE `scenario_step` (
+ `ID` int(10) unsigned NOT NULL DEFAULT '0',
+ `Description` text,
+ `Name` text,
+ `CriteriaTreeID` smallint(5) unsigned NOT NULL DEFAULT '0',
+ `ScenarioID` smallint(5) unsigned NOT NULL DEFAULT '0',
+ `PreviousStepID` smallint(5) unsigned NOT NULL DEFAULT '0',
+ `QuestRewardID` smallint(5) unsigned NOT NULL DEFAULT '0',
+ `Step` tinyint(3) unsigned NOT NULL DEFAULT '0',
+ `Flags` tinyint(3) unsigned NOT NULL DEFAULT '0',
+ `BonusRequiredStepID` int(10) unsigned NOT NULL DEFAULT '0',
+ `VerifiedBuild` smallint(6) NOT NULL DEFAULT '0',
+ PRIMARY KEY (`ID`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8;
+
+--
+-- Table structure for table `scenario_step_locale`
+--
+DROP TABLE IF EXISTS `scenario_step_locale`;
+CREATE TABLE `scenario_step_locale` (
+ `ID` int(10) unsigned NOT NULL DEFAULT '0',
+ `locale` varchar(4) NOT NULL,
+ `Description_lang` text,
+ `Name_lang` text,
+ `VerifiedBuild` smallint(6) NOT NULL DEFAULT '0',
+ PRIMARY KEY (`ID`,`locale`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8;
diff --git a/sql/updates/world/master/2016_11_06_00_world.sql b/sql/updates/world/master/2016_11_06_00_world.sql
new file mode 100644
index 00000000000..4fab752d9e2
--- /dev/null
+++ b/sql/updates/world/master/2016_11_06_00_world.sql
@@ -0,0 +1,233 @@
+DROP TABLE IF EXISTS `scenarios`;
+CREATE TABLE `scenarios` (
+ `map` int(10) unsigned NOT NULL DEFAULT '0',
+ `difficulty` tinyint(3) unsigned NOT NULL DEFAULT '0',
+ `scenario_A` int(10) unsigned NOT NULL DEFAULT '0',
+ `scenario_H` int(10) unsigned NOT NULL DEFAULT '0',
+ PRIMARY KEY (`map`,`difficulty`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8;
+
+INSERT INTO `scenarios` (`map`, `difficulty`, `scenario_A`, `scenario_H`) VALUES
+(33, 1, 516, 516),
+(33, 2, 523, 523),
+(34, 1, 510, 0),
+(36, 1, 641, 641),
+(36, 2, 643, 643),
+(43, 1, 515, 515),
+(47, 1, 654, 654),
+(48, 1, 333, 333),
+(70, 1, 648, 648),
+(90, 1, 649, 649),
+(109, 1, 640, 640),
+(129, 1, 647, 647),
+(209, 1, 644, 644),
+(230, 1, 671, 671),
+(269, 1, 610, 610),
+(269, 2, 611, 611),
+(349, 1, 664, 664),
+(389, 1, 511, 511),
+(429, 1, 668, 668),
+(540, 1, 607, 607),
+(540, 2, 608, 608),
+(542, 1, 634, 634),
+(542, 2, 635, 635),
+(543, 1, 638, 638),
+(543, 2, 639, 639),
+(545, 1, 618, 618),
+(545, 2, 619, 619),
+(546, 1, 630, 630),
+(546, 2, 631, 631),
+(547, 1, 632, 632),
+(547, 2, 633, 633),
+(552, 1, 620, 620),
+(552, 2, 621, 621),
+(553, 1, 612, 612),
+(553, 2, 613, 613),
+(554, 1, 614, 614),
+(554, 2, 615, 615),
+(555, 1, 606, 606),
+(555, 2, 609, 609),
+(556, 1, 622, 622),
+(556, 2, 623, 623),
+(557, 1, 628, 628),
+(557, 2, 629, 629),
+(558, 1, 626, 626),
+(558, 2, 627, 627),
+(560, 1, 624, 624),
+(560, 2, 625, 625),
+(568, 2, 574, 574),
+(574, 1, 596, 596),
+(574, 2, 597, 597),
+(575, 1, 577, 577),
+(575, 2, 579, 579),
+(576, 1, 598, 598),
+(576, 2, 605, 599),
+(578, 1, 575, 575),
+(578, 2, 576, 576),
+(585, 1, 616, 616),
+(585, 2, 617, 617),
+(595, 1, 583, 583),
+(595, 2, 585, 585),
+(599, 1, 582, 582),
+(599, 2, 584, 584),
+(600, 1, 590, 590),
+(600, 2, 591, 591),
+(601, 1, 594, 594),
+(601, 2, 595, 595),
+(602, 1, 580, 580),
+(602, 2, 581, 581),
+(604, 1, 586, 586),
+(604, 2, 587, 587),
+(608, 1, 588, 588),
+(608, 2, 589, 589),
+(619, 1, 592, 592),
+(619, 2, 593, 593),
+(632, 1, 566, 566),
+(632, 2, 568, 568),
+(643, 1, 548, 548),
+(643, 2, 550, 550),
+(644, 1, 558, 558),
+(644, 2, 565, 565),
+(645, 1, 542, 542),
+(645, 2, 545, 545),
+(650, 1, 676, 676),
+(650, 2, 677, 677),
+(657, 1, 551, 551),
+(657, 2, 552, 552),
+(658, 1, 569, 569),
+(658, 2, 571, 571),
+(668, 1, 572, 572),
+(668, 2, 573, 573),
+(670, 1, 553, 553),
+(670, 2, 554, 554),
+(725, 1, 674, 674),
+(725, 2, 675, 675),
+(755, 1, 555, 555),
+(755, 2, 557, 557),
+(859, 2, 556, 556),
+(938, 2, 547, 547),
+(939, 2, 567, 567),
+(940, 2, 570, 570),
+(959, 1, 531, 531),
+(959, 2, 535, 535),
+(959, 8, 46, 46),
+(960, 1, 539, 539),
+(960, 2, 540, 540),
+(960, 8, 44, 44),
+(961, 1, 537, 537),
+(961, 2, 538, 538),
+(961, 8, 45, 45),
+(962, 1, 526, 526),
+(962, 2, 527, 527),
+(962, 8, 48, 48),
+(994, 1, 528, 528),
+(994, 2, 536, 536),
+(994, 8, 50, 50),
+(999, 12, 71, 0),
+(1000, 12, 0, 72),
+(1001, 1, 650, 650),
+(1001, 2, 651, 651),
+(1001, 8, 52, 52),
+(1004, 1, 652, 652),
+(1004, 2, 653, 653),
+(1004, 8, 53, 53),
+(1005, 11, 65, 65),
+(1005, 12, 65, 65),
+(1007, 1, 645, 645),
+(1007, 2, 646, 646),
+(1007, 8, 51, 51),
+(1011, 1, 524, 524),
+(1011, 2, 525, 525),
+(1011, 8, 49, 49),
+(1024, 12, 40, 40),
+(1030, 11, 39, 39),
+(1030, 12, 39, 39),
+(1031, 11, 58, 58),
+(1031, 12, 58, 58),
+(1048, 12, 15, 15),
+(1051, 12, 63, 63),
+(1095, 12, 179, 179),
+(1099, 11, 182, 239),
+(1099, 12, 182, 239),
+(1102, 12, 0, 201),
+(1103, 12, 184, 184),
+(1104, 12, 183, 183),
+(1112, 12, 200, 200),
+(1126, 12, 205, 205),
+(1130, 11, 210, 210),
+(1130, 12, 210, 210),
+(1131, 11, 219, 219),
+(1131, 12, 219, 219),
+(1135, 12, 215, 215),
+(1144, 11, 216, 216),
+(1144, 12, 216, 216),
+(1148, 1, 237, 237),
+(1148, 12, 237, 237),
+(1161, 12, 257, 257),
+(1168, 12, 275, 275),
+(1175, 1, 680, 680),
+(1175, 2, 681, 681),
+(1175, 8, 425, 425),
+(1176, 1, 686, 686),
+(1176, 2, 687, 687),
+(1176, 8, 428, 428),
+(1176, 23, 687, 687),
+(1182, 1, 678, 678),
+(1182, 2, 679, 679),
+(1182, 8, 427, 427),
+(1182, 23, 679, 679),
+(1195, 1, 684, 684),
+(1195, 2, 685, 685),
+(1195, 8, 426, 426),
+(1195, 23, 685, 685),
+(1203, 12, 324, 324),
+(1207, 12, 331, 331),
+(1208, 1, 682, 682),
+(1208, 2, 683, 683),
+(1208, 8, 429, 429),
+(1208, 23, 683, 683),
+(1209, 1, 688, 688),
+(1209, 2, 689, 689),
+(1209, 8, 423, 423),
+(1209, 23, 689, 689),
+(1277, 12, 449, 449),
+(1279, 1, 708, 708),
+(1279, 2, 709, 709),
+(1279, 8, 430, 430),
+(1279, 23, 709, 709),
+(1358, 1, 744, 744),
+(1358, 2, 329, 329),
+(1358, 8, 432, 432),
+(1358, 19, 731, 731),
+(1402, 12, 320, 320),
+(1431, 1, 736, 736),
+(1455, 12, 776, 776);
+
+DROP TABLE IF EXISTS `scenario_poi`;
+CREATE TABLE `scenario_poi` (
+ `CriteriaTreeID` INT(11) NOT NULL DEFAULT '0',
+ `BlobIndex` INT(11) NOT NULL DEFAULT '0',
+ `Idx1` INT(11) NOT NULL DEFAULT '0',
+ `MapID` INT(11) NOT NULL DEFAULT '0',
+ `WorldMapAreaId` INT(11) NOT NULL DEFAULT '0',
+ `Floor` INT(11) NOT NULL DEFAULT '0',
+ `Priority` INT(11) NOT NULL DEFAULT '0',
+ `Flags` INT(11) NOT NULL DEFAULT '0',
+ `WorldEffectID` INT(11) NOT NULL DEFAULT '0',
+ `PlayerConditionID` INT(11) NOT NULL DEFAULT '0',
+ `VerifiedBuild` SMALLINT(5) NULL DEFAULT '0',
+ PRIMARY KEY (`CriteriaTreeID`, `BlobIndex`, `Idx1`),
+ INDEX `idx` (`CriteriaTreeID`, `BlobIndex`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8;
+
+DROP TABLE IF EXISTS `scenario_poi_points`;
+CREATE TABLE `scenario_poi_points` (
+ `CriteriaTreeID` INT(11) NOT NULL DEFAULT '0',
+ `Idx1` INT(11) NOT NULL DEFAULT '0',
+ `Idx2` INT(11) NOT NULL DEFAULT '0',
+ `X` INT(11) NOT NULL DEFAULT '0',
+ `Y` INT(11) NOT NULL DEFAULT '0',
+ `VerifiedBuild` SMALLINT(5) NULL DEFAULT '0',
+ PRIMARY KEY (`CriteriaTreeID`, `Idx1`, `Idx2`),
+ INDEX `questId_id` (`CriteriaTreeID`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8;
diff --git a/src/server/database/Database/Implementation/CharacterDatabase.cpp b/src/server/database/Database/Implementation/CharacterDatabase.cpp
index ee5cfeea1ef..5845a0d6a3a 100644
--- a/src/server/database/Database/Implementation/CharacterDatabase.cpp
+++ b/src/server/database/Database/Implementation/CharacterDatabase.cpp
@@ -732,4 +732,12 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_DEL_BLACKMARKET_AUCTIONS, "DELETE FROM blackmarket_auctions WHERE marketId = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_UPD_BLACKMARKET_AUCTIONS, "UPDATE blackmarket_auctions SET currentBid = ?, time = ?, numBids = ?, bidder = ? WHERE marketId = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_INS_BLACKMARKET_AUCTIONS, "INSERT INTO blackmarket_auctions (marketId, currentBid, time, numBids, bidder) VALUES (?, ?, ?, ? ,?)", CONNECTION_ASYNC);
+
+ // Scenario
+ PrepareStatement(CHAR_SEL_SCENARIO_INSTANCE_CRITERIA_FOR_INSTANCE, "SELECT criteria, counter, date FROM instance_scenario_progress WHERE id = ?", CONNECTION_SYNCH);
+ PrepareStatement(CHAR_SEL_SCENARIO_INSTANCE_CRITERIA, "SELECT counter, date FROM instance_scenario_progress WHERE id = ? AND criteria = ?", CONNECTION_SYNCH);
+ PrepareStatement(CHAR_INS_SCENARIO_INSTANCE_CRITERIA, "INSERT INTO instance_scenario_progress (id, criteria, counter, date) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_DEL_SCENARIO_INSTANCE_CRITERIA_FOR_INSTANCE, "DELETE FROM instance_scenario_progress WHERE id = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_UPD_SCENARIO_INSTANCE_CRITERIA, "UPDATE instance_scenario_progress SET counter = ?, date = ? WHERE id = ? AND criteria = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_DEL_INVALID_SCENARIO_INSTANCE_CRITERIA, "DELETE FROM instance_scenario_progress WHERE id = ? AND criteria = ?", CONNECTION_ASYNC);
}
diff --git a/src/server/database/Database/Implementation/CharacterDatabase.h b/src/server/database/Database/Implementation/CharacterDatabase.h
index c94cbdedd04..02969290007 100644
--- a/src/server/database/Database/Implementation/CharacterDatabase.h
+++ b/src/server/database/Database/Implementation/CharacterDatabase.h
@@ -623,6 +623,13 @@ enum CharacterDatabaseStatements
CHAR_UPD_BLACKMARKET_AUCTIONS,
CHAR_INS_BLACKMARKET_AUCTIONS,
+ CHAR_SEL_SCENARIO_INSTANCE_CRITERIA_FOR_INSTANCE,
+ CHAR_SEL_SCENARIO_INSTANCE_CRITERIA,
+ CHAR_INS_SCENARIO_INSTANCE_CRITERIA,
+ CHAR_DEL_SCENARIO_INSTANCE_CRITERIA_FOR_INSTANCE,
+ CHAR_UPD_SCENARIO_INSTANCE_CRITERIA,
+ CHAR_DEL_INVALID_SCENARIO_INSTANCE_CRITERIA,
+
MAX_CHARACTERDATABASE_STATEMENTS
};
diff --git a/src/server/database/Database/Implementation/HotfixDatabase.cpp b/src/server/database/Database/Implementation/HotfixDatabase.cpp
index 774477af109..e9210d0eb38 100644
--- a/src/server/database/Database/Implementation/HotfixDatabase.cpp
+++ b/src/server/database/Database/Implementation/HotfixDatabase.cpp
@@ -686,6 +686,15 @@ void HotfixDatabaseConnection::DoPrepareStatements()
PrepareStatement(HOTFIX_SEL_SCALING_STAT_DISTRIBUTION, "SELECT ID, ItemLevelCurveID, MinLevel, MaxLevel FROM scaling_stat_distribution"
" ORDER BY ID DESC", CONNECTION_SYNCH);
+ // Scenario.db2
+ PrepareStatement(HOTFIX_SEL_SCENARIO, "SELECT ID, Name, Data, Flags, Type FROM scenario ORDER BY ID DESC", CONNECTION_SYNCH);
+ PREPARE_LOCALE_STMT(HOTFIX_SEL_SCENARIO, "SELECT ID, Name_lang FROM scenario_locale WHERE locale = ?", CONNECTION_SYNCH);
+
+ // ScenarioStep.db2
+ PrepareStatement(HOTFIX_SEL_SCENARIO_STEP, "SELECT ID, Description, Name, CriteriaTreeID, ScenarioID, PreviousStepID, QuestRewardID, Step, Flags, "
+ "BonusRequiredStepID FROM scenario_step ORDER BY ID DESC", CONNECTION_SYNCH);
+ PREPARE_LOCALE_STMT(HOTFIX_SEL_SCENARIO_STEP, "SELECT ID, Description_lang, Name_lang FROM scenario_step_locale WHERE locale = ?", CONNECTION_SYNCH);
+
// SceneScript.db2
PrepareStatement(HOTFIX_SEL_SCENE_SCRIPT, "SELECT ID, Name, Script, PrevScriptId, NextScriptId FROM scene_script ORDER BY ID DESC", CONNECTION_SYNCH);
diff --git a/src/server/database/Database/Implementation/HotfixDatabase.h b/src/server/database/Database/Implementation/HotfixDatabase.h
index eafc14e07e3..552dbdcc491 100644
--- a/src/server/database/Database/Implementation/HotfixDatabase.h
+++ b/src/server/database/Database/Implementation/HotfixDatabase.h
@@ -372,6 +372,12 @@ enum HotfixDatabaseStatements
HOTFIX_SEL_SCALING_STAT_DISTRIBUTION,
+ HOTFIX_SEL_SCENARIO,
+ HOTFIX_SEL_SCENARIO_LOCALE,
+
+ HOTFIX_SEL_SCENARIO_STEP,
+ HOTFIX_SEL_SCENARIO_STEP_LOCALE,
+
HOTFIX_SEL_SCENE_SCRIPT,
HOTFIX_SEL_SCENE_SCRIPT_PACKAGE,
diff --git a/src/server/game/Achievements/CriteriaHandler.cpp b/src/server/game/Achievements/CriteriaHandler.cpp
index b917cb02cb4..01a06c52548 100644
--- a/src/server/game/Achievements/CriteriaHandler.cpp
+++ b/src/server/game/Achievements/CriteriaHandler.cpp
@@ -2073,9 +2073,9 @@ void CriteriaMgr::LoadCriteriaList()
achievementCriteriaTreeIds[achievement->CriteriaTree] = achievement;
std::unordered_map<uint32 /*criteriaTreeID*/, ScenarioStepEntry const*> scenarioCriteriaTreeIds;
- //for (ScenarioStepEntry const* scenarioStep : sScenarioStepStore)
- // if (scenarioStep->CriteriaTreeID)
- // scenarioCriteriaTreeIds[scenarioStep->CriteriaTreeID] = scenarioStep;
+ for (ScenarioStepEntry const* scenarioStep : sScenarioStepStore)
+ if (scenarioStep->CriteriaTreeID)
+ scenarioCriteriaTreeIds[scenarioStep->CriteriaTreeID] = scenarioStep;
// Load criteria tree nodes
for (CriteriaTreeEntry const* tree : sCriteriaTreeStore)
diff --git a/src/server/game/DataStores/DB2LoadInfo.h b/src/server/game/DataStores/DB2LoadInfo.h
index 4c05ac1b7eb..9975f0a92ea 100644
--- a/src/server/game/DataStores/DB2LoadInfo.h
+++ b/src/server/game/DataStores/DB2LoadInfo.h
@@ -3359,6 +3359,43 @@ struct ScalingStatDistributionLoadInfo
}
};
+struct ScenarioLoadInfo
+{
+ static DB2LoadInfo Instance()
+ {
+ static DB2FieldMeta const fields[] =
+ {
+ { false, FT_INT, "ID" },
+ { false, FT_STRING, "Name" },
+ { false, FT_SHORT, "Data" },
+ { false, FT_BYTE, "Flags" },
+ { false, FT_BYTE, "Type" },
+ };
+ return { &fields[0], std::extent<decltype(fields)>::value, ScenarioMeta::Instance(), HOTFIX_SEL_SCENARIO };
+ }
+};
+
+struct ScenarioStepLoadInfo
+{
+ static DB2LoadInfo Instance()
+ {
+ static DB2FieldMeta const fields[] =
+ {
+ { false, FT_INT, "ID" },
+ { false, FT_STRING, "Description" },
+ { false, FT_STRING, "Name" },
+ { false, FT_SHORT, "CriteriaTreeID" },
+ { false, FT_SHORT, "ScenarioID" },
+ { false, FT_SHORT, "PreviousStepID" },
+ { false, FT_SHORT, "QuestRewardID" },
+ { false, FT_BYTE, "Step" },
+ { false, FT_BYTE, "Flags" },
+ { false, FT_INT, "BonusRequiredStepID" },
+ };
+ return { &fields[0], std::extent<decltype(fields)>::value, ScenarioStepMeta::Instance(), HOTFIX_SEL_SCENARIO_STEP };
+ }
+};
+
struct SceneScriptLoadInfo
{
static DB2LoadInfo Instance()
diff --git a/src/server/game/DataStores/DB2Stores.cpp b/src/server/game/DataStores/DB2Stores.cpp
index 16657ce3960..e6b5290b752 100644
--- a/src/server/game/DataStores/DB2Stores.cpp
+++ b/src/server/game/DataStores/DB2Stores.cpp
@@ -170,6 +170,8 @@ DB2Storage<QuestXPEntry> sQuestXPStore("QuestXP.db2", Que
DB2Storage<RandPropPointsEntry> sRandPropPointsStore("RandPropPoints.db2", RandPropPointsLoadInfo::Instance());
DB2Storage<RulesetItemUpgradeEntry> sRulesetItemUpgradeStore("RulesetItemUpgrade.db2", RulesetItemUpgradeLoadInfo::Instance());
DB2Storage<ScalingStatDistributionEntry> sScalingStatDistributionStore("ScalingStatDistribution.db2", ScalingStatDistributionLoadInfo::Instance());
+DB2Storage<ScenarioEntry> sScenarioStore("Scenario.db2", ScenarioLoadInfo::Instance());
+DB2Storage<ScenarioStepEntry> sScenarioStepStore("ScenarioStep.db2", ScenarioStepLoadInfo::Instance());
DB2Storage<SceneScriptEntry> sSceneScriptStore("SceneScript.db2", SceneScriptLoadInfo::Instance());
DB2Storage<SceneScriptPackageEntry> sSceneScriptPackageStore("SceneScriptPackage.db2", SceneScriptPackageLoadInfo::Instance());
DB2Storage<SkillLineEntry> sSkillLineStore("SkillLine.db2", SkillLineLoadInfo::Instance());
@@ -465,6 +467,8 @@ void DB2Manager::LoadStores(std::string const& dataPath, uint32 defaultLocale)
LOAD_DB2(sRandPropPointsStore);
LOAD_DB2(sRulesetItemUpgradeStore);
LOAD_DB2(sScalingStatDistributionStore);
+ LOAD_DB2(sScenarioStore);
+ LOAD_DB2(sScenarioStepStore);
LOAD_DB2(sSceneScriptStore);
LOAD_DB2(sSceneScriptPackageStore);
LOAD_DB2(sSkillLineStore);
diff --git a/src/server/game/DataStores/DB2Stores.h b/src/server/game/DataStores/DB2Stores.h
index cebd561bb26..2a4e42b27ed 100644
--- a/src/server/game/DataStores/DB2Stores.h
+++ b/src/server/game/DataStores/DB2Stores.h
@@ -135,6 +135,8 @@ TC_GAME_API extern DB2Storage<QuestSortEntry> sQuestSortSt
TC_GAME_API extern DB2Storage<QuestXPEntry> sQuestXPStore;
TC_GAME_API extern DB2Storage<RandPropPointsEntry> sRandPropPointsStore;
TC_GAME_API extern DB2Storage<ScalingStatDistributionEntry> sScalingStatDistributionStore;
+TC_GAME_API extern DB2Storage<ScenarioEntry> sScenarioStore;
+TC_GAME_API extern DB2Storage<ScenarioStepEntry> sScenarioStepStore;
TC_GAME_API extern DB2Storage<SkillLineEntry> sSkillLineStore;
TC_GAME_API extern DB2Storage<SceneScriptEntry> sSceneScriptStore;
TC_GAME_API extern DB2Storage<SceneScriptPackageEntry> sSceneScriptPackageStore;
diff --git a/src/server/game/DataStores/DB2Structure.h b/src/server/game/DataStores/DB2Structure.h
index 1072a7b2ef4..93cd5833dc8 100644
--- a/src/server/game/DataStores/DB2Structure.h
+++ b/src/server/game/DataStores/DB2Structure.h
@@ -2050,6 +2050,35 @@ struct ScalingStatDistributionEntry
uint32 MaxLevel;
};
+struct ScenarioEntry
+{
+ uint32 ID;
+ LocalizedString* Name;
+ uint16 Data; // Seems to indicate different things, for zone invasions, this is the area id
+ uint8 Flags;
+ uint8 Type;
+};
+
+struct ScenarioStepEntry
+{
+ uint32 ID;
+ LocalizedString* Description;
+ LocalizedString* Name;
+ uint16 CriteriaTreeID;
+ uint16 ScenarioID;
+ uint16 PreviousStepID; // Used in conjunction with Proving Grounds scenarios, when sequencing steps (Not using step order?)
+ uint16 QuestRewardID;
+ uint8 Step;
+ uint8 Flags;
+ uint32 BonusRequiredStepID; // Bonus step can only be completed if scenario is in the step specified in this field
+
+ // helpers
+ bool IsBonusObjective() const
+ {
+ return Flags & SCENARIO_STEP_FLAG_BONUS_OBJECTIVE;
+ }
+};
+
struct SceneScriptEntry
{
uint32 ID;
diff --git a/src/server/game/DataStores/DBCEnums.h b/src/server/game/DataStores/DBCEnums.h
index 7f8d7c23111..3519f7987c9 100644
--- a/src/server/game/DataStores/DBCEnums.h
+++ b/src/server/game/DataStores/DBCEnums.h
@@ -706,6 +706,12 @@ enum QuestPackageFilter
QUEST_PACKAGE_FILTER_EVERYONE = 3 // Players can always select this quest reward
};
+enum ScenarioStepFlags
+{
+ SCENARIO_STEP_FLAG_BONUS_OBJECTIVE = 0x1,
+ SCENARIO_STEP_FLAG_HEROIC_ONLY = 0x2
+};
+
enum SkillRaceClassInfoFlags
{
SKILL_FLAG_NO_SKILLUP_MESSAGE = 0x2,
diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp
index 047966d710c..7d557cf2b6c 100644
--- a/src/server/game/Entities/Object/Object.cpp
+++ b/src/server/game/Entities/Object/Object.cpp
@@ -45,6 +45,7 @@
#include "BattlefieldMgr.h"
#include "GameObjectPackets.h"
#include "MiscPackets.h"
+#include "InstanceScenario.h"
Object::Object()
{
@@ -2367,6 +2368,15 @@ void WorldObject::SetZoneScript()
}
}
+Scenario* WorldObject::GetScenario() const
+{
+ if (IsInWorld())
+ if (InstanceMap* instanceMap = GetMap()->ToInstanceMap())
+ return instanceMap->GetInstanceScenario();
+
+ return nullptr;
+}
+
TempSummon* WorldObject::SummonCreature(uint32 entry, const Position &pos, TempSummonType spwtype, uint32 duration, uint32 /*vehId*/) const
{
if (Map* map = FindMap())
diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h
index 42d53ed2dc0..471e60c42b5 100644
--- a/src/server/game/Entities/Object/Object.h
+++ b/src/server/game/Entities/Object/Object.h
@@ -82,6 +82,7 @@ class DynamicObject;
class GameObject;
class InstanceScript;
class Player;
+class Scenario;
class TempSummon;
class Transport;
class Unit;
@@ -643,6 +644,8 @@ class TC_GAME_API WorldObject : public Object, public WorldLocation
void SetZoneScript();
ZoneScript* GetZoneScript() const { return m_zoneScript; }
+ Scenario* GetScenario() const;
+
TempSummon* SummonCreature(uint32 id, Position const &pos, TempSummonType spwtype = TEMPSUMMON_MANUAL_DESPAWN, uint32 despwtime = 0, uint32 vehId = 0) const;
TempSummon* SummonCreature(uint32 id, float x, float y, float z, float ang = 0, TempSummonType spwtype = TEMPSUMMON_MANUAL_DESPAWN, uint32 despwtime = 0) const;
GameObject* SummonGameObject(uint32 entry, float x, float y, float z, float ang, float rotation0, float rotation1, float rotation2, float rotation3, uint32 respawnTime /* s */);
diff --git a/src/server/game/Entities/Player/KillRewarder.cpp b/src/server/game/Entities/Player/KillRewarder.cpp
index c26c2261c4b..3573a40d956 100644
--- a/src/server/game/Entities/Player/KillRewarder.cpp
+++ b/src/server/game/Entities/Player/KillRewarder.cpp
@@ -25,6 +25,7 @@
#include "InstanceScript.h"
#include "Pet.h"
#include "Player.h"
+#include "Scenario.h"
// == KillRewarder ====================================================
// KillRewarder encapsulates logic of rewarding player upon kill with:
@@ -67,6 +68,7 @@
// 4.4. Give kill credit (player must not be in group, or he must be alive or without corpse).
// 5. Credit instance encounter.
// 6. Update guild achievements.
+ // 7. Scenario credit
KillRewarder::KillRewarder(Player* killer, Unit* victim, bool isBattleGround) :
// 1. Initialize internal variables to default values.
@@ -269,6 +271,7 @@ void KillRewarder::Reward()
// 5. Credit instance encounter.
// 6. Update guild achievements.
+ // 7. Credit scenario criterias
if (Creature* victim = _victim->ToCreature())
{
if (victim->IsDungeonBoss())
@@ -278,6 +281,8 @@ void KillRewarder::Reward()
if (ObjectGuid::LowType guildId = victim->GetMap()->GetOwnerGuildId())
if (Guild* guild = sGuildMgr->GetGuildById(guildId))
guild->UpdateCriteria(CRITERIA_TYPE_KILL_CREATURE, victim->GetEntry(), 1, 0, victim, _killer);
- }
+ if (Scenario* scenario = victim->GetScenario())
+ scenario->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 38675cf6b52..aacc602d3d6 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -23,18 +23,18 @@
#include "ArenaTeamMgr.h"
#include "Battlefield.h"
#include "BattlefieldMgr.h"
-#include "BattlefieldWG.h"
#include "BattlefieldTB.h"
+#include "BattlefieldWG.h"
#include "Battleground.h"
#include "BattlegroundMgr.h"
#include "BattlegroundScore.h"
#include "BattlePetMgr.h"
#include "CellImpl.h"
+#include "Channel.h"
#include "ChannelMgr.h"
#include "CharacterDatabaseCleaner.h"
#include "CharacterPackets.h"
#include "Chat.h"
-#include "Channel.h"
#include "ChatPackets.h"
#include "CombatLogPackets.h"
#include "CombatPackets.h"
@@ -50,6 +50,7 @@
#include "GameEventMgr.h"
#include "GameObjectAI.h"
#include "Garrison.h"
+#include "GitRevision.h"
#include "GossipDef.h"
#include "GridNotifiers.h"
#include "GridNotifiersImpl.h"
@@ -80,7 +81,7 @@
#include "QuestDef.h"
#include "QuestPackets.h"
#include "ReputationMgr.h"
-#include "GitRevision.h"
+#include "Scenario.h"
#include "SkillDiscovery.h"
#include "SocialMgr.h"
#include "Spell.h"
@@ -90,8 +91,8 @@
#include "SpellMgr.h"
#include "SpellPackets.h"
#include "TalentPackets.h"
-#include "TransmogrificationPackets.h"
#include "ToyPackets.h"
+#include "TransmogrificationPackets.h"
#include "Transport.h"
#include "UpdateData.h"
#include "UpdateFieldFlags.h"
@@ -25367,16 +25368,17 @@ void Player::ResetCriteria(CriteriaTypes type, uint64 miscValue1 /*= 0*/, uint64
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);
- 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 (CriteriaMgr::IsGroupCriteriaType(type))
return;
- guild->UpdateCriteria(type, miscValue1, miscValue2, miscValue3, unit, this);
+ if (Scenario* scenario = GetScenario())
+ scenario->UpdateCriteria(type, miscValue1, miscValue2, miscValue3, unit, this);
+
+ if (Guild* guild = sGuildMgr->GetGuildById(GetGuildId()))
+ guild->UpdateCriteria(type, miscValue1, miscValue2, miscValue3, unit, this);
}
void Player::CompletedAchievement(AchievementEntry const* entry)
diff --git a/src/server/game/Handlers/ScenarioHandler.cpp b/src/server/game/Handlers/ScenarioHandler.cpp
new file mode 100644
index 00000000000..e5745e1bfab
--- /dev/null
+++ b/src/server/game/Handlers/ScenarioHandler.cpp
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2008-2015 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 "ScenarioMgr.h"
+#include "ScenarioPackets.h"
+#include "WorldSession.h"
+
+void WorldSession::HandleQueryScenarioPOI(WorldPackets::Scenario::QueryScenarioPOI& queryScenarioPOI)
+{
+ WorldPackets::Scenario::ScenarioPOIs response;
+
+ // Read criteria tree ids and add the in a unordered_set so we don't send POIs for the same criteria tree multiple times
+ std::unordered_set<int32> criteriaTreeIds;
+ for (size_t i = 0; i < queryScenarioPOI.MissingScenarioPOIs.size(); ++i)
+ criteriaTreeIds.insert(queryScenarioPOI.MissingScenarioPOIs[i]); // CriteriaTreeID
+
+ for (int32 criteriaTreeId : criteriaTreeIds)
+ {
+ if (ScenarioPOIVector const* poiVector = sScenarioMgr->GetScenarioPOIs(criteriaTreeId))
+ {
+ WorldPackets::Scenario::ScenarioPOIData scenarioPOIData;
+ scenarioPOIData.CriteriaTreeID = criteriaTreeId;
+ scenarioPOIData.ScenarioPOIs = poiVector;
+ response.ScenarioPOIDataStats.push_back(scenarioPOIData);
+ }
+ }
+
+ SendPacket(response.Write());
+}
diff --git a/src/server/game/Instances/InstanceSaveMgr.cpp b/src/server/game/Instances/InstanceSaveMgr.cpp
index 4fa2682c7b6..cc088d8954a 100644
--- a/src/server/game/Instances/InstanceSaveMgr.cpp
+++ b/src/server/game/Instances/InstanceSaveMgr.cpp
@@ -31,6 +31,7 @@
#include "World.h"
#include "Group.h"
#include "InstanceScript.h"
+#include "InstanceScenario.h"
uint16 InstanceSaveManager::ResetTimeDelay[] = {3600, 900, 300, 60};
@@ -148,6 +149,10 @@ void InstanceSaveManager::DeleteInstanceFromDB(uint32 instanceid)
stmt->setUInt32(0, instanceid);
trans->Append(stmt);
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_SCENARIO_INSTANCE_CRITERIA_FOR_INSTANCE);
+ stmt->setUInt32(0, instanceid);
+ trans->Append(stmt);
+
CharacterDatabase.CommitTransaction(trans);
// Respawn times should be deleted only when the map gets unloaded
}
@@ -208,6 +213,9 @@ void InstanceSave::SaveToDB()
completedEncounters = instanceScript->GetCompletedEncounterMask();
m_entranceId = instanceScript->GetEntranceLocation();
}
+
+ if (InstanceScenario* scenario = map->ToInstanceMap()->GetInstanceScenario())
+ scenario->SaveToDB();
}
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_INSTANCE_SAVE);
diff --git a/src/server/game/Instances/InstanceScript.cpp b/src/server/game/Instances/InstanceScript.cpp
index 9854e46f1cb..91101a5aeff 100644
--- a/src/server/game/Instances/InstanceScript.cpp
+++ b/src/server/game/Instances/InstanceScript.cpp
@@ -32,6 +32,7 @@
#include "Opcodes.h"
#include "ScriptReloadMgr.h"
#include "ScriptMgr.h"
+#include "InstanceScenario.h"
BossBoundaryData::~BossBoundaryData()
{
@@ -54,6 +55,9 @@ _entranceId(0), _temporaryEntranceId(0), _combatResurrectionTimer(0), _combatRes
void InstanceScript::SaveToDB()
{
+ if (InstanceScenario* scenario = instance->ToInstanceMap()->GetInstanceScenario())
+ scenario->SaveToDB();
+
std::string data = GetSaveData();
if (data.empty())
return;
diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp
index 0a7138616e0..a40367ad7a3 100644
--- a/src/server/game/Maps/Map.cpp
+++ b/src/server/game/Maps/Map.cpp
@@ -28,6 +28,7 @@
#include "GridStates.h"
#include "Group.h"
#include "InstancePackets.h"
+#include "InstanceScenario.h"
#include "InstanceScript.h"
#include "MapInstanced.h"
#include "MiscPackets.h"
@@ -3046,7 +3047,7 @@ template TC_GAME_API void Map::RemoveFromMap(AreaTrigger*, bool);
InstanceMap::InstanceMap(uint32 id, time_t expiry, uint32 InstanceId, uint8 SpawnMode, Map* _parent)
: Map(id, expiry, InstanceId, SpawnMode, _parent),
m_resetAfterUnload(false), m_unloadWhenEmpty(false),
- i_data(NULL), i_script_id(0)
+ i_data(NULL), i_script_id(0), i_scenario(nullptr)
{
//lets initialize visibility distance for dungeons
InstanceMap::InitVisibilityDistance();
@@ -3059,7 +3060,7 @@ InstanceMap::InstanceMap(uint32 id, time_t expiry, uint32 InstanceId, uint8 Spaw
InstanceMap::~InstanceMap()
{
delete i_data;
- i_data = NULL;
+ delete i_scenario;
}
void InstanceMap::InitVisibilityDistance()
@@ -3224,6 +3225,9 @@ bool InstanceMap::AddPlayerToMap(Player* player, bool initPlayer /*= true*/)
if (i_data)
i_data->OnPlayerEnter(player);
+ if (i_scenario)
+ i_scenario->OnPlayerEnter(player);
+
return true;
}
@@ -3236,6 +3240,9 @@ void InstanceMap::Update(const uint32 t_diff)
i_data->Update(t_diff);
i_data->UpdateCombatResurrection(t_diff);
}
+
+ if (i_scenario)
+ i_scenario->Update(t_diff);
}
void InstanceMap::RemovePlayerFromMap(Player* player, bool remove)
@@ -3244,6 +3251,8 @@ void InstanceMap::RemovePlayerFromMap(Player* player, bool remove)
//if last player set unload timer
if (!m_unloadTimer && m_mapRefManager.getSize() == 1)
m_unloadTimer = m_unloadWhenEmpty ? MIN_UNLOAD_DELAY : std::max(sWorld->getIntConfig(CONFIG_INSTANCE_UNLOAD_DELAY), (uint32)MIN_UNLOAD_DELAY);
+ if (i_scenario)
+ i_scenario->OnPlayerExit(player);
Map::RemovePlayerFromMap(player, remove);
// for normal instances schedule the reset after all players have left
SetResetSchedule(true);
diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h
index 89edf9823b7..cca480cf94a 100644
--- a/src/server/game/Maps/Map.h
+++ b/src/server/game/Maps/Map.h
@@ -42,6 +42,7 @@ class Group;
class InstanceMap;
class InstanceSave;
class InstanceScript;
+class InstanceScenario;
class MapInstanced;
class Object;
class Player;
@@ -766,6 +767,8 @@ class TC_GAME_API InstanceMap : public Map
bool Reset(uint8 method);
uint32 GetScriptId() const { return i_script_id; }
InstanceScript* GetInstanceScript() { return i_data; }
+ InstanceScenario* GetInstanceScenario() { return i_scenario; }
+ void SetInstanceScenario(InstanceScenario* scenario) { i_scenario = scenario; }
void PermBindAllPlayers(Player* source);
void UnloadAll() override;
EnterState CannotEnter(Player* player) override;
@@ -784,6 +787,7 @@ class TC_GAME_API InstanceMap : public Map
bool m_unloadWhenEmpty;
InstanceScript* i_data;
uint32 i_script_id;
+ InstanceScenario* i_scenario;
};
class TC_GAME_API BattlegroundMap : public Map
diff --git a/src/server/game/Maps/MapInstanced.cpp b/src/server/game/Maps/MapInstanced.cpp
index f80c04d7c8c..ad7d1c240be 100644
--- a/src/server/game/Maps/MapInstanced.cpp
+++ b/src/server/game/Maps/MapInstanced.cpp
@@ -27,6 +27,7 @@
#include "Group.h"
#include "Player.h"
#include "GarrisonMap.h"
+#include "ScenarioMgr.h"
MapInstanced::MapInstanced(uint32 id, time_t expiry) : Map(id, expiry, 0, DIFFICULTY_NORMAL)
{
@@ -178,7 +179,7 @@ Map* MapInstanced::CreateInstanceForPlayer(const uint32 mapId, Player* player, u
map = FindInstanceMap(newInstanceId);
// it is possible that the save exists but the map doesn't
if (!map)
- map = CreateInstance(newInstanceId, pSave, pSave->GetDifficultyID());
+ map = CreateInstance(newInstanceId, pSave, pSave->GetDifficultyID(), player->GetTeamId());
}
else
{
@@ -191,7 +192,7 @@ Map* MapInstanced::CreateInstanceForPlayer(const uint32 mapId, Player* player, u
//ASSERT(!FindInstanceMap(NewInstanceId));
map = FindInstanceMap(newInstanceId);
if (!map)
- map = CreateInstance(newInstanceId, NULL, diff);
+ map = CreateInstance(newInstanceId, NULL, diff, player->GetTeamId());
}
}
else
@@ -205,7 +206,7 @@ Map* MapInstanced::CreateInstanceForPlayer(const uint32 mapId, Player* player, u
return map;
}
-InstanceMap* MapInstanced::CreateInstance(uint32 InstanceId, InstanceSave* save, Difficulty difficulty)
+InstanceMap* MapInstanced::CreateInstance(uint32 InstanceId, InstanceSave* save, Difficulty difficulty, TeamId team)
{
// load/create a map
std::lock_guard<std::mutex> lock(_mapLock);
@@ -237,6 +238,8 @@ InstanceMap* MapInstanced::CreateInstance(uint32 InstanceId, InstanceSave* save,
bool load_data = save != NULL;
map->CreateInstanceData(load_data);
+ if (InstanceScenario* instanceScenario = sScenarioMgr->CreateInstanceScenario(map, team))
+ map->SetInstanceScenario(instanceScenario);
if (sWorld->getBoolConfig(CONFIG_INSTANCEMAP_LOAD_GRIDS))
map->LoadAllCells();
diff --git a/src/server/game/Maps/MapInstanced.h b/src/server/game/Maps/MapInstanced.h
index 7d89d446846..3e8d60f892e 100644
--- a/src/server/game/Maps/MapInstanced.h
+++ b/src/server/game/Maps/MapInstanced.h
@@ -66,7 +66,7 @@ class TC_GAME_API MapInstanced : public Map
virtual void InitVisibilityDistance() override;
private:
- InstanceMap* CreateInstance(uint32 InstanceId, InstanceSave* save, Difficulty difficulty);
+ InstanceMap* CreateInstance(uint32 InstanceId, InstanceSave* save, Difficulty difficulty, TeamId team);
BattlegroundMap* CreateBattleground(uint32 InstanceId, Battleground* bg);
GarrisonMap* CreateGarrison(uint32 instanceId, Player* owner);
diff --git a/src/server/game/Scenarios/InstanceScenario.cpp b/src/server/game/Scenarios/InstanceScenario.cpp
new file mode 100644
index 00000000000..60f3a364af5
--- /dev/null
+++ b/src/server/game/Scenarios/InstanceScenario.cpp
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2008-2015 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 "InstanceScenario.h"
+#include "Player.h"
+#include "InstanceSaveMgr.h"
+#include "ObjectMgr.h"
+
+InstanceScenario::InstanceScenario(Map* map, ScenarioData const* scenarioData) : Scenario(scenarioData), _map(map)
+{
+ ASSERT(_map);
+ LoadInstanceData(_map->GetInstanceId());
+
+ Map::PlayerList const& players = map->GetPlayers();
+ for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
+ if (Player* player = itr->GetSource()->ToPlayer())
+ SendScenarioState(player);
+}
+
+void InstanceScenario::SaveToDB()
+{
+ if (_criteriaProgress.empty())
+ return;
+
+ DifficultyEntry const* difficultyEntry = sDifficultyStore.LookupEntry(_map->GetDifficultyID());
+ if (!difficultyEntry || difficultyEntry->Flags & DIFFICULTY_FLAG_CHALLENGE_MODE) // Map should have some sort of "CanSave" boolean that returns whether or not the map is savable. (Challenge modes cannot be saved for example)
+ return;
+
+ uint32 id = _map->GetInstanceId();
+ if (!id)
+ {
+ TC_LOG_DEBUG("scenario", "Scenario::SaveToDB: Can not save scenario progress without an instance save. Map::GetInstanceId() did not return an instance save.");
+ return;
+ }
+
+ SQLTransaction trans = CharacterDatabase.BeginTransaction();
+ for (auto iter = _criteriaProgress.begin(); iter != _criteriaProgress.end(); ++iter)
+ {
+ if (!iter->second.Changed)
+ continue;
+
+ Criteria const* criteria = sCriteriaMgr->GetCriteria(iter->first);
+ switch (CriteriaTypes(criteria->Entry->Type))
+ {
+ // Blizzard only appears to store creature kills
+ case CRITERIA_TYPE_KILL_CREATURE:
+ break;
+ default:
+ continue;
+ }
+
+ if (iter->second.Counter)
+ {
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_SCENARIO_INSTANCE_CRITERIA);
+ stmt->setUInt32(0, id);
+ stmt->setUInt32(1, iter->first);
+ PreparedQueryResult result = CharacterDatabase.Query(stmt);
+ if (result)
+ {
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_SCENARIO_INSTANCE_CRITERIA);
+ stmt->setUInt64(0, iter->second.Counter);
+ stmt->setUInt32(1, uint32(iter->second.Date));
+ stmt->setUInt32(2, id);
+ stmt->setUInt32(3, iter->first);
+ trans->Append(stmt);
+ }
+ else
+ {
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_SCENARIO_INSTANCE_CRITERIA);
+ stmt->setUInt32(0, id);
+ stmt->setUInt32(1, iter->first);
+ stmt->setUInt64(2, iter->second.Counter);
+ stmt->setUInt32(3, uint32(iter->second.Date));
+ trans->Append(stmt);
+ }
+ }
+
+ iter->second.Changed = false;
+ }
+
+ CharacterDatabase.CommitTransaction(trans);
+}
+
+void InstanceScenario::LoadInstanceData(uint32 instanceId)
+{
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_SCENARIO_INSTANCE_CRITERIA_FOR_INSTANCE);
+ stmt->setUInt32(0, instanceId);
+
+ PreparedQueryResult result = CharacterDatabase.Query(stmt);
+ if (result)
+ {
+ SQLTransaction trans = CharacterDatabase.BeginTransaction();
+ time_t now = time(nullptr);
+
+ std::vector<CriteriaTree const*> criteriaTrees;
+ do
+ {
+ Field* fields = result->Fetch();
+ uint32 id = fields[0].GetUInt32();
+ uint64 counter = fields[1].GetUInt64();
+ time_t date = time_t(fields[2].GetUInt32());
+
+ Criteria const* criteria = sCriteriaMgr->GetCriteria(id);
+ if (!criteria)
+ {
+ // Removing non-existing criteria data for all instances
+ TC_LOG_ERROR("criteria.instancescenarios", "Removing scenario criteria %u data from the table `instance_scenario_progress`.", id);
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_INVALID_SCENARIO_INSTANCE_CRITERIA);
+ stmt->setUInt32(0, instanceId);
+ stmt->setUInt32(1, uint32(id));
+ trans->Append(stmt);
+ continue;
+ }
+
+ if (criteria->Entry->StartTimer && time_t(date + criteria->Entry->StartTimer) < now)
+ continue;
+
+ switch (CriteriaTypes(criteria->Entry->Type))
+ {
+ // Blizzard appears to only stores creatures killed progress for unknown reasons. Either technical shortcoming or intentional
+ case CRITERIA_TYPE_KILL_CREATURE:
+ break;
+ default:
+ continue;
+ }
+
+ SetCriteriaProgress(criteria, counter, nullptr, PROGRESS_SET);
+
+ if (CriteriaTreeList const* trees = sCriteriaMgr->GetCriteriaTreesByCriteria(criteria->ID))
+ for (CriteriaTree const* tree : *trees)
+ criteriaTrees.push_back(tree);
+ }
+ while (result->NextRow());
+
+ CharacterDatabase.CommitTransaction(trans);
+
+ for (CriteriaTree const* tree : criteriaTrees)
+ {
+ ScenarioStepEntry const* step = tree->ScenarioStep;
+ if (!step)
+ continue;
+
+ if (IsCompletedCriteriaTree(tree))
+ SetStepState(step, SCENARIO_STEP_DONE);
+ }
+ }
+}
+
+std::string InstanceScenario::GetOwnerInfo() const
+{
+ return Trinity::StringFormat("Instance ID %u", _map->GetInstanceId());
+}
+
+void InstanceScenario::SendPacket(WorldPacket const* data) const
+{
+ _map->SendToPlayers(data);
+}
diff --git a/src/server/game/Scenarios/InstanceScenario.h b/src/server/game/Scenarios/InstanceScenario.h
new file mode 100644
index 00000000000..9582d0cf2ba
--- /dev/null
+++ b/src/server/game/Scenarios/InstanceScenario.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2008-2015 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 InstanceScenario_h__
+#define InstanceScenario_h__
+
+#include "Scenario.h"
+
+class Map;
+
+typedef std::unordered_map<uint8, CriteriaProgressMap> StepCriteriaProgressMap;
+
+class TC_GAME_API InstanceScenario : public Scenario
+{
+ public:
+ InstanceScenario(Map* map, ScenarioData const* scenarioData);
+
+ void SaveToDB();
+ void LoadInstanceData(uint32 instanceId);
+
+ protected:
+ std::string GetOwnerInfo() const override;
+ void SendPacket(WorldPacket const* data) const override;
+
+ Map* _map;
+ ScenarioData const* _data;
+ StepCriteriaProgressMap _stepCriteriaProgress;
+};
+
+#endif // InstanceScenario_h__
diff --git a/src/server/game/Scenarios/Scenario.cpp b/src/server/game/Scenarios/Scenario.cpp
new file mode 100644
index 00000000000..a4e39b2caa6
--- /dev/null
+++ b/src/server/game/Scenarios/Scenario.cpp
@@ -0,0 +1,311 @@
+/*
+ * Copyright (C) 2008-2015 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 "Scenario.h"
+#include "Player.h"
+#include "ScenarioMgr.h"
+#include "InstanceSaveMgr.h"
+#include "ObjectMgr.h"
+#include "ScenarioPackets.h"
+
+Scenario::Scenario(ScenarioData const* scenarioData) : _data(scenarioData), _currentstep(nullptr)
+{
+ ASSERT(_data);
+
+ for (auto step : _data->Steps)
+ SetStepState(step.second, SCENARIO_STEP_NOT_STARTED);
+
+ if (ScenarioStepEntry const* step = GetFirstStep())
+ SetStep(step);
+ else
+ TC_LOG_ERROR("scenario", "Scenario::Scenario: Could not launch Scenario (id: %u), found no valid scenario step", _data->Entry->ID);
+}
+
+Scenario::~Scenario()
+{
+ for (ObjectGuid guid : _players)
+ if (Player* player = ObjectAccessor::FindPlayer(guid))
+ SendBootPlayer(player);
+
+ _players.clear();
+}
+
+void Scenario::Reset()
+{
+ CriteriaHandler::Reset();
+ SetStep(GetFirstStep());
+}
+
+void Scenario::CompleteStep(ScenarioStepEntry const* step)
+{
+ if (Quest const* quest = sObjectMgr->GetQuestTemplate(step->QuestRewardID))
+ for (ObjectGuid guid : _players)
+ if (Player* player = ObjectAccessor::FindPlayer(guid))
+ player->RewardQuest(quest, 0, nullptr, false);
+
+ if (step->IsBonusObjective())
+ return;
+
+ ScenarioStepEntry const* newStep = nullptr;
+ for (auto _step : _data->Steps)
+ {
+ if (_step.second->IsBonusObjective())
+ continue;
+
+ if (GetStepState(_step.second) == SCENARIO_STEP_DONE)
+ continue;
+
+ if (!newStep || _step.second->Step < newStep->Step)
+ newStep = _step.second;
+ }
+
+ SetStep(newStep);
+ if (IsComplete())
+ CompleteScenario();
+ else
+ TC_LOG_ERROR("scenario", "Scenario::CompleteStep: Scenario (id: %u, step: %u) was completed, but could not determine new step, or validate scenario completion.", step->ScenarioID, step->ID);
+}
+
+void Scenario::CompleteScenario()
+{
+ return SendPacket(WorldPackets::Scenario::ScenarioCompleted(_data->Entry->ID).Write());
+}
+
+void Scenario::SetStep(ScenarioStepEntry const* step)
+{
+ _currentstep = step;
+ if (step)
+ SetStepState(step, SCENARIO_STEP_IN_PROGRESS);
+
+ WorldPackets::Scenario::ScenarioState scenarioState;
+ BuildScenarioState(&scenarioState);
+ SendPacket(scenarioState.Write());
+}
+
+void Scenario::OnPlayerEnter(Player* player)
+{
+ _players.insert(player->GetGUID());
+ SendScenarioState(player);
+}
+
+void Scenario::OnPlayerExit(Player* player)
+{
+ _players.erase(player->GetGUID());
+ SendBootPlayer(player);
+}
+
+bool Scenario::IsComplete()
+{
+ for (auto step : _data->Steps)
+ {
+ if (step.second->IsBonusObjective())
+ continue;
+
+ if (GetStepState(step.second) != SCENARIO_STEP_DONE)
+ return false;
+ }
+
+ return true;
+}
+
+ScenarioStepState Scenario::GetStepState(ScenarioStepEntry const* step)
+{
+ std::map<ScenarioStepEntry const*, ScenarioStepState>::const_iterator itr = _stepStates.find(step);
+ if (itr == _stepStates.end())
+ return SCENARIO_STEP_INVALID;
+
+ return itr->second;
+}
+
+void Scenario::SendCriteriaUpdate(Criteria const * criteria, CriteriaProgress const * progress, uint32 timeElapsed, bool timedCompleted) const
+{
+ WorldPackets::Scenario::ScenarioProgressUpdate progressUpdate;
+ progressUpdate.CriteriaProgress.Id = criteria->ID;
+ progressUpdate.CriteriaProgress.Quantity = progress->Counter;
+ progressUpdate.CriteriaProgress.Player = progress->PlayerGUID;
+ progressUpdate.CriteriaProgress.Date = progress->Date;
+ if (criteria->Entry->StartTimer)
+ progressUpdate.CriteriaProgress.Flags = timedCompleted ? 1 : 0;
+
+ progressUpdate.CriteriaProgress.TimeFromStart = timeElapsed;
+ progressUpdate.CriteriaProgress.TimeFromCreate = 0;
+
+ SendPacket(progressUpdate.Write());
+}
+
+bool Scenario::CanUpdateCriteriaTree(Criteria const * /*criteria*/, CriteriaTree const * tree, Player * /*referencePlayer*/) const
+{
+ ScenarioStepEntry const* step = tree->ScenarioStep;
+ if (!step)
+ return false;
+
+ if (step->ScenarioID != _data->Entry->ID)
+ return false;
+
+ ScenarioStepEntry const* currentStep = GetStep();
+ if (!currentStep)
+ return false;
+
+ if (step->IsBonusObjective())
+ return true;
+
+ return currentStep == step;
+}
+
+bool Scenario::CanCompleteCriteriaTree(CriteriaTree const* tree)
+{
+ ScenarioStepEntry const* step = tree->ScenarioStep;
+ if (!step)
+ return false;
+
+ if (step->ScenarioID != _data->Entry->ID)
+ return false;
+
+ if (step->IsBonusObjective())
+ return !IsComplete();
+
+ if (step != GetStep())
+ return false;
+
+ return true;
+}
+
+void Scenario::CompletedCriteriaTree(CriteriaTree const* tree, Player* /*referencePlayer*/)
+{
+ ScenarioStepEntry const* step = tree->ScenarioStep;
+ if (!step)
+ return;
+
+ if (!step->IsBonusObjective() && step != GetStep())
+ return;
+
+ if (GetStepState(step) == SCENARIO_STEP_DONE)
+ return;
+
+ SetStepState(step, SCENARIO_STEP_DONE);
+ CompleteStep(step);
+}
+
+void Scenario::SendPacket(WorldPacket const* data) const
+{
+ for (ObjectGuid guid : _players)
+ if (Player* player = ObjectAccessor::FindPlayer(guid))
+ player->SendDirectMessage(data);
+}
+
+void Scenario::BuildScenarioState(WorldPackets::Scenario::ScenarioState* scenarioState)
+{
+ scenarioState->ScenarioID = _data->Entry->ID;
+ if (ScenarioStepEntry const* step = GetStep())
+ scenarioState->CurrentStep = step->ID;
+ scenarioState->CriteriaProgress = GetCriteriasProgress();
+ scenarioState->BonusObjectives = GetBonusObjectivesData();
+ // Don't know exactly what this is for, but seems to contain list of scenario steps that we're either on or that are completed
+ for (auto state : _stepStates)
+ {
+ if (state.first->IsBonusObjective())
+ continue;
+
+ switch (state.second)
+ {
+ case SCENARIO_STEP_IN_PROGRESS:
+ case SCENARIO_STEP_DONE:
+ break;
+ case SCENARIO_STEP_NOT_STARTED:
+ default:
+ continue;
+ }
+
+ scenarioState->PickedSteps.push_back(state.first->ID);
+ }
+ scenarioState->ScenarioComplete = IsComplete();
+}
+
+ScenarioStepEntry const* Scenario::GetFirstStep() const
+{
+ // Do it like this because we don't know what order they're in inside the container.
+ ScenarioStepEntry const* firstStep = nullptr;
+ for (auto scenarioStep : _data->Steps)
+ {
+ if (scenarioStep.second->IsBonusObjective())
+ continue;
+
+ if (!firstStep || scenarioStep.second->Step < firstStep->Step)
+ firstStep = scenarioStep.second;
+ }
+
+ return firstStep;
+}
+
+void Scenario::SendScenarioState(Player* player)
+{
+ WorldPackets::Scenario::ScenarioState scenarioState;
+ BuildScenarioState(&scenarioState);
+ player->SendDirectMessage(scenarioState.Write());
+}
+
+std::vector<WorldPackets::Scenario::BonusObjectiveData> Scenario::GetBonusObjectivesData()
+{
+ std::vector<WorldPackets::Scenario::BonusObjectiveData> bonusObjectivesData;
+ for (auto itr = _data->Steps.begin(); itr != _data->Steps.end(); ++itr)
+ {
+ if (!itr->second->IsBonusObjective())
+ continue;
+
+ if (CriteriaTree const* tree = sCriteriaMgr->GetCriteriaTree(itr->second->CriteriaTreeID))
+ {
+ WorldPackets::Scenario::BonusObjectiveData bonusObjectiveData;
+ bonusObjectiveData.BonusObjectiveID = itr->second->ID;
+ bonusObjectiveData.ObjectiveComplete = GetStepState(itr->second) == SCENARIO_STEP_DONE;
+ bonusObjectivesData.push_back(bonusObjectiveData);
+ }
+ }
+
+ return bonusObjectivesData;
+}
+
+std::vector<WorldPackets::Achievement::CriteriaProgress> Scenario::GetCriteriasProgress()
+{
+ std::vector<WorldPackets::Achievement::CriteriaProgress> criteriasProgress;
+
+ if (!_criteriaProgress.empty())
+ {
+ for (auto critItr = _criteriaProgress.begin(); critItr != _criteriaProgress.end(); ++critItr)
+ {
+ WorldPackets::Achievement::CriteriaProgress criteriaProgress;
+ criteriaProgress.Id = critItr->first;
+ criteriaProgress.Quantity = critItr->second.Counter;
+ criteriaProgress.Date = critItr->second.Date;
+ criteriaProgress.Player = critItr->second.PlayerGUID;
+ criteriasProgress.push_back(criteriaProgress);
+ }
+ }
+
+ return criteriasProgress;
+}
+
+CriteriaList const& Scenario::GetCriteriaByType(CriteriaTypes type) const
+{
+ return sCriteriaMgr->GetScenarioCriteriaByType(type);
+}
+
+void Scenario::SendBootPlayer(Player* player)
+{
+ WorldPackets::Scenario::ScenarioBoot scenarioBoot;
+ scenarioBoot.ScenarioID = _data->Entry->ID;
+ player->SendDirectMessage(scenarioBoot.Write());
+}
diff --git a/src/server/game/Scenarios/Scenario.h b/src/server/game/Scenarios/Scenario.h
new file mode 100644
index 00000000000..1b37c6abca4
--- /dev/null
+++ b/src/server/game/Scenarios/Scenario.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2008-2015 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 Scenario_h__
+#define Scenario_h__
+
+#include "CriteriaHandler.h"
+
+struct ScenarioData;
+struct ScenarioStepEntry;
+
+namespace WorldPackets
+{
+ namespace Achievement
+ {
+ struct CriteriaProgress;
+ }
+
+ namespace Scenario
+ {
+ struct BonusObjectiveData;
+ class ScenarioState;
+ }
+}
+
+enum ScenarioStepState
+{
+ SCENARIO_STEP_INVALID = 0,
+ SCENARIO_STEP_NOT_STARTED = 1,
+ SCENARIO_STEP_IN_PROGRESS = 2,
+ SCENARIO_STEP_DONE = 3
+};
+
+class TC_GAME_API Scenario : public CriteriaHandler
+{
+ public:
+ Scenario(ScenarioData const* scenarioData);
+ ~Scenario();
+
+ void Reset() override;
+ void SetStep(ScenarioStepEntry const* step);
+
+ virtual void CompleteStep(ScenarioStepEntry const* step);
+ virtual void CompleteScenario();
+
+ virtual void OnPlayerEnter(Player* player);
+ virtual void OnPlayerExit(Player* player);
+ virtual void Update(uint32 /*diff*/) { }
+
+ bool IsComplete();
+ void SetStepState(ScenarioStepEntry const* step, ScenarioStepState state) { _stepStates[step] = state; }
+ ScenarioStepState GetStepState(ScenarioStepEntry const* step);
+ ScenarioStepEntry const* GetStep() const { return _currentstep; }
+ ScenarioStepEntry const* GetFirstStep() const;
+
+ void SendScenarioState(Player* player);
+ void SendBootPlayer(Player* player);
+
+ protected:
+ GuidUnorderedSet _players;
+
+ void SendCriteriaUpdate(Criteria const* criteria, 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 AfterCriteriaTreeUpdate(CriteriaTree const* /*tree*/, Player* /*referencePlayer*/) override { }
+
+ void SendPacket(WorldPacket const* data) const override;
+
+ void SendAllData(Player const* /*receiver*/) const override { }
+
+ void BuildScenarioState(WorldPackets::Scenario::ScenarioState* scenarioState);
+
+ std::vector<WorldPackets::Scenario::BonusObjectiveData> GetBonusObjectivesData();
+ std::vector<WorldPackets::Achievement::CriteriaProgress> GetCriteriasProgress();
+
+ CriteriaList const& GetCriteriaByType(CriteriaTypes type) const override;
+ ScenarioData const* _data;
+
+ private:
+ ScenarioStepEntry const* _currentstep;
+ std::map<ScenarioStepEntry const*, ScenarioStepState> _stepStates;
+};
+
+#endif // Scenario_h__
diff --git a/src/server/game/Scenarios/ScenarioMgr.cpp b/src/server/game/Scenarios/ScenarioMgr.cpp
new file mode 100644
index 00000000000..cecf9d6caf0
--- /dev/null
+++ b/src/server/game/Scenarios/ScenarioMgr.cpp
@@ -0,0 +1,214 @@
+/*
+ * Copyright (C) 2008-2015 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 "ScenarioMgr.h"
+#include "DatabaseEnv.h"
+#include "DB2Stores.h"
+#include "InstanceScenario.h"
+#include "Map.h"
+#include "ScenarioPackets.h"
+
+ScenarioMgr* ScenarioMgr::Instance()
+{
+ static ScenarioMgr instance;
+ return &instance;
+}
+
+InstanceScenario* ScenarioMgr::CreateInstanceScenario(Map* map, TeamId team)
+{
+ auto dbDataItr = _scenarioDBData.find(std::make_pair(map->GetId(), map->GetDifficultyID()));
+ // No scenario registered for this map and difficulty in the database
+ if (dbDataItr == _scenarioDBData.end())
+ return nullptr;
+
+ uint32 scenarioID = 0;
+ switch (team)
+ {
+ case TEAM_ALLIANCE:
+ scenarioID = dbDataItr->second.Scenario_A;
+ break;
+ case TEAM_HORDE:
+ scenarioID = dbDataItr->second.Scenario_H;
+ break;
+ default:
+ break;
+ }
+
+ auto itr = _scenarioData.find(scenarioID);
+ if (itr == _scenarioData.end())
+ {
+ TC_LOG_ERROR("scenario", "Table `scenarios` contained data linking scenario (Id: %u) to map (Id: %u), difficulty (Id: %u) but no scenario data was found related to that scenario Id.", scenarioID, map->GetId(), map->GetDifficultyID());
+ return nullptr;
+ }
+
+ return new InstanceScenario(map, &itr->second);
+}
+
+void ScenarioMgr::LoadDBData()
+{
+ _scenarioDBData.clear();
+
+ uint32 oldMSTime = getMSTime();
+
+ QueryResult result = WorldDatabase.Query("SELECT map, difficulty, scenario_A, scenario_H FROM scenarios");
+
+ if (!result)
+ {
+ TC_LOG_INFO("server.loading", ">> Loaded 0 scenarios. DB table `scenarios` is empty!");
+ return;
+ }
+
+ do
+ {
+ Field* fields = result->Fetch();
+
+ uint32 mapId = fields[0].GetUInt32();
+ uint8 difficulty = fields[1].GetUInt8();
+
+ uint32 scenarioAllianceId = fields[2].GetUInt32();
+ if (scenarioAllianceId > 0 && _scenarioData.find(scenarioAllianceId) == _scenarioData.end())
+ {
+ TC_LOG_ERROR("sql.sql", "ScenarioMgr::LoadDBData: DB Table `scenarios`, column scenario_A contained an invalid scenario (Id: %u)!", scenarioAllianceId);
+ continue;
+ }
+
+ uint32 scenarioHordeId = fields[3].GetUInt32();
+ if (scenarioHordeId > 0 && _scenarioData.find(scenarioHordeId) == _scenarioData.end())
+ {
+ TC_LOG_ERROR("sql.sql", "ScenarioMgr::LoadDBData: DB Table `scenarios`, column scenario_H contained an invalid scenario (Id: %u)!", scenarioHordeId);
+ continue;
+ }
+
+ if (scenarioHordeId == 0)
+ scenarioHordeId = scenarioAllianceId;
+
+ ScenarioDBData& data = _scenarioDBData[std::make_pair(mapId, difficulty)];
+ data.MapID = mapId;
+ data.DifficultyID = difficulty;
+ data.Scenario_A = scenarioAllianceId;
+ data.Scenario_H = scenarioHordeId;
+ }
+ while (result->NextRow());
+
+ TC_LOG_INFO("server.loading", ">> Loaded " SZFMTD " instance scenario entries in %u ms", _scenarioDBData.size(), GetMSTimeDiffToNow(oldMSTime));
+}
+
+void ScenarioMgr::LoadDB2Data()
+{
+ _scenarioData.clear();
+
+ std::unordered_map<uint32, std::map<uint8, ScenarioStepEntry const*>> scenarioSteps;
+ uint32 deepestCriteriaTreeSize = 0;
+
+ for (ScenarioStepEntry const* step : sScenarioStepStore)
+ {
+ scenarioSteps[step->ScenarioID][step->Step] = step;
+ if (CriteriaTree const* tree = sCriteriaMgr->GetCriteriaTree(step->CriteriaTreeID))
+ {
+ uint32 criteriaTreeSize = 0;
+ CriteriaMgr::WalkCriteriaTree(tree, [&criteriaTreeSize](CriteriaTree const* /*tree*/)
+ {
+ ++criteriaTreeSize;
+ });
+ deepestCriteriaTreeSize = std::max(deepestCriteriaTreeSize, criteriaTreeSize);
+ }
+ }
+
+ ASSERT(deepestCriteriaTreeSize < MAX_ALLOWED_SCENARIO_POI_QUERY_SIZE, "MAX_ALLOWED_SCENARIO_POI_QUERY_SIZE must be at least %u", deepestCriteriaTreeSize + 1);
+
+ for (ScenarioEntry const* scenario : sScenarioStore)
+ {
+ ScenarioData& data = _scenarioData[scenario->ID];
+ data.Entry = scenario;
+ data.Steps = std::move(scenarioSteps[scenario->ID]);
+ }
+}
+
+void ScenarioMgr::LoadScenarioPOI()
+{
+ uint32 oldMSTime = getMSTime();
+
+ _scenarioPOIStore.clear(); // need for reload case
+
+ uint32 count = 0;
+
+ // 0 1 2 6 7 8 9 10 11 12
+ QueryResult result = WorldDatabase.Query("SELECT CriteriaTreeID, BlobIndex, Idx1, MapID, WorldMapAreaId, Floor, Priority, Flags, WorldEffectID, PlayerConditionID FROM scenario_poi ORDER BY CriteriaTreeID, Idx1");
+ if (!result)
+ {
+ TC_LOG_ERROR("server.loading", ">> Loaded 0 scenario POI definitions. DB table `scenario_poi` is empty.");
+ return;
+ }
+
+ // 0 1 2 3
+ QueryResult points = WorldDatabase.Query("SELECT CriteriaTreeID, Idx1, X, Y FROM scenario_poi_points ORDER BY CriteriaTreeID DESC, Idx1, Idx2");
+
+ std::vector<std::vector<std::vector<ScenarioPOIPoint>>> POIs;
+
+ if (points)
+ {
+ // The first result should have the highest criteriaTreeId
+ Field* fields = points->Fetch();
+ uint32 criteriaTreeIdMax = fields[0].GetInt32();
+ POIs.resize(criteriaTreeIdMax + 1);
+
+ do
+ {
+ fields = points->Fetch();
+
+ int32 CriteriaTreeID = fields[0].GetInt32();
+ int32 Idx1 = fields[1].GetInt32();
+ int32 X = fields[2].GetInt32();
+ int32 Y = fields[3].GetInt32();
+
+ if (int32(POIs[CriteriaTreeID].size()) <= Idx1 + 1)
+ POIs[CriteriaTreeID].resize(Idx1 + 10);
+
+ ScenarioPOIPoint point(X, Y);
+ POIs[CriteriaTreeID][Idx1].push_back(point);
+ } while (points->NextRow());
+ }
+
+ do
+ {
+ Field* fields = result->Fetch();
+
+ int32 CriteriaTreeID = fields[0].GetInt32();
+ int32 BlobIndex = fields[1].GetInt32();
+ int32 Idx1 = fields[2].GetInt32();
+ int32 MapID = fields[3].GetInt32();
+ int32 WorldMapAreaId = fields[4].GetInt32();
+ int32 Floor = fields[5].GetInt32();
+ int32 Priority = fields[6].GetInt32();
+ int32 Flags = fields[7].GetInt32();
+ int32 WorldEffectID = fields[8].GetInt32();
+ int32 PlayerConditionID = fields[9].GetInt32();
+
+ if (!sCriteriaMgr->GetCriteriaTree(CriteriaTreeID))
+ TC_LOG_ERROR("sql.sql", "`scenario_poi` CriteriaTreeID (%u) Idx1 (%u) does not correspond to a valid criteria tree", CriteriaTreeID, Idx1);
+
+ if (CriteriaTreeID < int32(POIs.size()) && Idx1 < int32(POIs[CriteriaTreeID].size()))
+ _scenarioPOIStore[CriteriaTreeID].emplace_back(BlobIndex, MapID, WorldMapAreaId, Floor, Priority, Flags, WorldEffectID, PlayerConditionID, POIs[CriteriaTreeID][Idx1]);
+ else
+ TC_LOG_ERROR("server.loading", "Table scenario_poi references unknown scenario poi points for criteria tree id %i POI id %i", CriteriaTreeID, BlobIndex);
+
+ ++count;
+ } while (result->NextRow());
+
+ TC_LOG_INFO("server.loading", ">> Loaded %u scenario POI definitions in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
+}
+
diff --git a/src/server/game/Scenarios/ScenarioMgr.h b/src/server/game/Scenarios/ScenarioMgr.h
new file mode 100644
index 00000000000..00c04ac1e4c
--- /dev/null
+++ b/src/server/game/Scenarios/ScenarioMgr.h
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2008-2015 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 ScenarioMgr_h__
+#define ScenarioMgr_h__
+
+#include "Common.h"
+#include "SharedDefines.h"
+
+class InstanceScenario;
+class Map;
+struct ScenarioEntry;
+struct ScenarioStepEntry;
+
+struct ScenarioData
+{
+ ScenarioEntry const* Entry;
+ std::map<uint8, ScenarioStepEntry const*> Steps;
+};
+
+/*
+ Scenario data should be loaded on demand.
+ The server will get data from the database which scenario ids is linked with which map id/difficulty/player team.
+ The first time a scenario is loaded, the map loads and stores the scenario data for future scenario instance launches.
+*/
+
+struct ScenarioDBData
+{
+ uint32 MapID;
+ uint8 DifficultyID;
+ uint32 Scenario_A;
+ uint32 Scenario_H;
+};
+
+typedef std::unordered_map<std::pair<uint32, uint8>, ScenarioDBData> ScenarioDBDataContainer;
+typedef std::map<uint32, ScenarioData> ScenarioDataContainer;
+
+enum ScenarioType
+{
+ SCENARIO_TYPE_SCENARIO = 0,
+ SCENARIO_TYPE_CHALLENGE_MODE = 1,
+ SCENARIO_TYPE_SOLO = 2,
+ SCENARIO_TYPE_DUNGEON = 10,
+};
+
+struct ScenarioPOIPoint
+{
+ int32 X;
+ int32 Y;
+
+ ScenarioPOIPoint() : X(0), Y(0) { }
+ ScenarioPOIPoint(int32 _X, int32 _Y) : X(_X), Y(_Y) { }
+};
+
+struct ScenarioPOI
+{
+ int32 BlobIndex;
+ int32 ObjectiveIndex;
+ int32 QuestObjectiveID;
+ int32 QuestObjectID;
+ int32 MapID;
+ int32 WorldMapAreaID;
+ int32 Floor;
+ int32 Priority;
+ int32 Flags;
+ int32 WorldEffectID;
+ int32 PlayerConditionID;
+ std::vector<ScenarioPOIPoint> Points;
+
+ ScenarioPOI() : BlobIndex(0), MapID(0), WorldMapAreaID(0), Floor(0), Priority(0), Flags(0), WorldEffectID(0), PlayerConditionID(0) { }
+
+ ScenarioPOI(int32 _BlobIndex, int32 _MapID, int32 _WorldMapAreaID, int32 _Floor, int32 _Priority, int32 _Flags, int32 _WorldEffectID,
+ int32 _PlayerConditionID, std::vector<ScenarioPOIPoint> points) :
+ BlobIndex(_BlobIndex), MapID(_MapID), WorldMapAreaID(_WorldMapAreaID), Floor(_Floor), Priority(_Priority), Flags(_Flags), WorldEffectID(_WorldEffectID),
+ PlayerConditionID(_PlayerConditionID), Points(std::move(points)) { }
+
+ ScenarioPOI(ScenarioPOI&& scenarioPOI) :
+ BlobIndex(scenarioPOI.BlobIndex), MapID(scenarioPOI.MapID), WorldMapAreaID(scenarioPOI.WorldMapAreaID), Floor(scenarioPOI.Floor), Priority(scenarioPOI.Priority),
+ Flags(scenarioPOI.Flags), WorldEffectID(scenarioPOI.WorldEffectID), PlayerConditionID(scenarioPOI.PlayerConditionID), Points(std::move(scenarioPOI.Points)) { }
+};
+
+typedef std::vector<ScenarioPOI> ScenarioPOIVector;
+typedef std::unordered_map<uint32, ScenarioPOIVector> ScenarioPOIContainer;
+
+class TC_GAME_API ScenarioMgr
+{
+private:
+ ScenarioMgr() { }
+ ~ScenarioMgr() { }
+
+public:
+ static ScenarioMgr* Instance();
+
+ void LoadDBData();
+ void LoadDB2Data();
+ void LoadScenarioPOI();
+
+ ScenarioPOIVector const* GetScenarioPOIs(int32 CriteriaTreeID)
+ {
+ auto itr = _scenarioPOIStore.find(CriteriaTreeID);
+ if (itr != _scenarioPOIStore.end())
+ return &itr->second;
+
+ return nullptr;
+ }
+
+ InstanceScenario* CreateInstanceScenario(Map* map, TeamId team);
+
+private:
+ ScenarioDataContainer _scenarioData;
+ ScenarioPOIContainer _scenarioPOIStore;
+ ScenarioDBDataContainer _scenarioDBData;
+};
+
+#define sScenarioMgr ScenarioMgr::Instance()
+
+#endif // ScenarioMgr_h__
diff --git a/src/server/game/Server/Packets/AchievementPackets.cpp b/src/server/game/Server/Packets/AchievementPackets.cpp
index c5098caa53d..155fa43b806 100644
--- a/src/server/game/Server/Packets/AchievementPackets.cpp
+++ b/src/server/game/Server/Packets/AchievementPackets.cpp
@@ -27,6 +27,19 @@ ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Achievement::EarnedAchiev
return data;
}
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Achievement::CriteriaProgress const& criteria)
+{
+ data << uint32(criteria.Id);
+ data << uint64(criteria.Quantity);
+ data << criteria.Player;
+ data.AppendPackedTime(criteria.Date);
+ data << uint32(criteria.TimeFromStart);
+ data << uint32(criteria.TimeFromCreate);
+ data.WriteBits(criteria.Flags, 4);
+ data.FlushBits();
+ return data;
+}
+
ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Achievement::AllAchievements const& allAchievements)
{
data << uint32(allAchievements.Earned.size());
@@ -36,16 +49,7 @@ ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Achievement::AllAchieveme
data << earned;
for (WorldPackets::Achievement::CriteriaProgress const& progress : allAchievements.Progress)
- {
- data << uint32(progress.Id);
- data << uint64(progress.Quantity);
- data << progress.Player;
- data.AppendPackedTime(progress.Date);
- data << uint32(progress.TimeFromStart);
- data << uint32(progress.TimeFromCreate);
- data.WriteBits(progress.Flags, 4);
- data.FlushBits();
- }
+ data << progress;
return data;
}
diff --git a/src/server/game/Server/Packets/AchievementPackets.h b/src/server/game/Server/Packets/AchievementPackets.h
index bf200ffb242..70feedaf1e4 100644
--- a/src/server/game/Server/Packets/AchievementPackets.h
+++ b/src/server/game/Server/Packets/AchievementPackets.h
@@ -216,4 +216,6 @@ namespace WorldPackets
}
}
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Achievement::CriteriaProgress const& criteria);
+
#endif // game_AchievementPackets_h__
diff --git a/src/server/game/Server/Packets/AllPackets.h b/src/server/game/Server/Packets/AllPackets.h
index 7c4f7ba39ab..6f36a93c799 100644
--- a/src/server/game/Server/Packets/AllPackets.h
+++ b/src/server/game/Server/Packets/AllPackets.h
@@ -60,6 +60,7 @@
#include "QuestPackets.h"
#include "ReferAFriendPackets.h"
#include "ReputationPackets.h"
+#include "ScenarioPackets.h"
#include "ScenePackets.h"
#include "SocialPackets.h"
#include "SpellPackets.h"
diff --git a/src/server/game/Server/Packets/ScenarioPackets.cpp b/src/server/game/Server/Packets/ScenarioPackets.cpp
new file mode 100644
index 00000000000..46e4324e961
--- /dev/null
+++ b/src/server/game/Server/Packets/ScenarioPackets.cpp
@@ -0,0 +1,129 @@
+/*
+ * 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 "ScenarioPackets.h"
+#include "ScenarioMgr.h"
+
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Scenario::BonusObjectiveData const& bonusObjective)
+{
+ data << int32(bonusObjective.BonusObjectiveID);
+ data.WriteBit(bonusObjective.ObjectiveComplete);
+ data.FlushBits();
+ return data;
+}
+
+ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Scenario::ScenarioSpellUpdate const& spell)
+{
+ data << uint32(spell.SpellID);
+ data.WriteBit(spell.Usable);
+ data.FlushBits();
+ return data;
+}
+
+WorldPacket const* WorldPackets::Scenario::ScenarioState::Write()
+{
+ _worldPacket << int32(ScenarioID);
+ _worldPacket << int32(CurrentStep);
+ _worldPacket << uint32(DifficultyID);
+ _worldPacket << uint32(WaveCurrent);
+ _worldPacket << uint32(WaveMax);
+ _worldPacket << uint32(TimerDuration);
+ _worldPacket << uint32(CriteriaProgress.size());
+ _worldPacket << uint32(BonusObjectives.size());
+ _worldPacket << uint32(PickedSteps.size());
+ _worldPacket << uint32(Spells.size());
+
+ for (uint32 i = 0; i < PickedSteps.size(); ++i)
+ _worldPacket << uint32(PickedSteps[i]);
+
+ _worldPacket.WriteBit(ScenarioComplete);
+ _worldPacket.FlushBits();
+
+ for (WorldPackets::Achievement::CriteriaProgress const& progress : CriteriaProgress)
+ _worldPacket << progress;
+
+ for (WorldPackets::Scenario::BonusObjectiveData const& bonusObjective : BonusObjectives)
+ _worldPacket << bonusObjective;
+
+ for (WorldPackets::Scenario::ScenarioSpellUpdate const& spell : Spells)
+ _worldPacket << spell;
+
+ return &_worldPacket;
+}
+
+WorldPacket const* WorldPackets::Scenario::ScenarioProgressUpdate::Write()
+{
+ _worldPacket << CriteriaProgress;
+
+ return &_worldPacket;
+}
+
+WorldPacket const* WorldPackets::Scenario::ScenarioCompleted::Write()
+{
+ _worldPacket << uint32(ScenarioID);
+
+ return &_worldPacket;
+}
+
+WorldPacket const* WorldPackets::Scenario::ScenarioBoot::Write()
+{
+ _worldPacket << int32(ScenarioID);
+ _worldPacket << int32(Unk1);
+ _worldPacket.WriteBits(Unk2, 2);
+ _worldPacket.FlushBits();
+
+ return &_worldPacket;
+}
+
+void WorldPackets::Scenario::QueryScenarioPOI::Read()
+{
+ MissingScenarioPOIs.resize(_worldPacket.read<uint32>());
+ for (int32& scenarioPOI : MissingScenarioPOIs)
+ _worldPacket >> scenarioPOI;
+}
+
+WorldPacket const* WorldPackets::Scenario::ScenarioPOIs::Write()
+{
+ _worldPacket << uint32(ScenarioPOIDataStats.size());
+
+ for (ScenarioPOIData const& scenarioPOIData : ScenarioPOIDataStats)
+ {
+ _worldPacket << int32(scenarioPOIData.CriteriaTreeID);
+ _worldPacket << uint32(scenarioPOIData.ScenarioPOIs->size());
+
+ for (ScenarioPOI const& scenarioPOI : *scenarioPOIData.ScenarioPOIs)
+ {
+ _worldPacket << int32(scenarioPOI.BlobIndex);
+ _worldPacket << int32(scenarioPOI.MapID);
+ _worldPacket << int32(scenarioPOI.WorldMapAreaID);
+ _worldPacket << int32(scenarioPOI.Floor);
+ _worldPacket << int32(scenarioPOI.Priority);
+ _worldPacket << int32(scenarioPOI.Flags);
+ _worldPacket << int32(scenarioPOI.WorldEffectID);
+ _worldPacket << int32(scenarioPOI.PlayerConditionID);
+ _worldPacket << uint32(scenarioPOI.Points.size());
+
+ for (ScenarioPOIPoint const& scenarioPOIBlobPoint : scenarioPOI.Points)
+ {
+ _worldPacket << int32(scenarioPOIBlobPoint.X);
+ _worldPacket << int32(scenarioPOIBlobPoint.Y);
+ }
+ }
+ }
+
+ return &_worldPacket;
+}
diff --git a/src/server/game/Server/Packets/ScenarioPackets.h b/src/server/game/Server/Packets/ScenarioPackets.h
new file mode 100644
index 00000000000..9e365e3a2e9
--- /dev/null
+++ b/src/server/game/Server/Packets/ScenarioPackets.h
@@ -0,0 +1,125 @@
+/*
+ * 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 ScenarioPackets_h__
+#define ScenarioPackets_h__
+
+#include "Packet.h"
+#include "PacketUtilities.h"
+#include "AchievementPackets.h"
+
+#define MAX_ALLOWED_SCENARIO_POI_QUERY_SIZE 35
+
+struct ScenarioPOI;
+
+namespace WorldPackets
+{
+ namespace Scenario
+ {
+ struct BonusObjectiveData
+ {
+ int32 BonusObjectiveID = 0;
+ bool ObjectiveComplete = false;
+ };
+
+ struct ScenarioSpellUpdate
+ {
+ uint32 SpellID = 0;
+ bool Usable = true;
+ };
+
+ class ScenarioState final : public ServerPacket
+ {
+ public:
+ ScenarioState() : ServerPacket(SMSG_SCENARIO_STATE) { }
+
+ WorldPacket const* Write() override;
+
+ int32 ScenarioID = 0;
+ int32 CurrentStep = -1;
+ uint32 DifficultyID = 0;
+ uint32 WaveCurrent = 0;
+ uint32 WaveMax = 0;
+ uint32 TimerDuration = 0;
+ std::vector<WorldPackets::Achievement::CriteriaProgress> CriteriaProgress;
+ std::vector<BonusObjectiveData> BonusObjectives;
+ std::vector<uint32> PickedSteps;
+ std::vector<ScenarioSpellUpdate> Spells;
+ bool ScenarioComplete = false;
+ };
+
+ class ScenarioProgressUpdate final : public ServerPacket
+ {
+ public:
+ ScenarioProgressUpdate() : ServerPacket(SMSG_SCENARIO_PROGRESS_UPDATE) { }
+
+ WorldPacket const* Write() override;
+
+ WorldPackets::Achievement::CriteriaProgress CriteriaProgress;
+ };
+
+ class ScenarioCompleted final : public ServerPacket
+ {
+ public:
+ ScenarioCompleted(uint32 scenarioId) : ServerPacket(SMSG_SCENARIO_COMPLETED, 4), ScenarioID(scenarioId) { }
+
+ WorldPacket const* Write() override;
+
+ uint32 ScenarioID = 0;
+ };
+
+ class ScenarioBoot final : public ServerPacket
+ {
+ public:
+ ScenarioBoot() : ServerPacket(SMSG_SCENARIO_BOOT, 4 + 4 + 1) { }
+
+ WorldPacket const* Write() override;
+
+ int32 ScenarioID = 0;
+ int32 Unk1 = 0;
+ uint8 Unk2 = 0;
+ };
+
+ class QueryScenarioPOI final : public ClientPacket
+ {
+ public:
+ QueryScenarioPOI(WorldPacket&& packet) : ClientPacket(CMSG_QUERY_SCENARIO_POI, std::move(packet)) { }
+
+ void Read() override;
+
+ Array<int32, MAX_ALLOWED_SCENARIO_POI_QUERY_SIZE> MissingScenarioPOIs;
+ };
+
+ struct ScenarioPOIData
+ {
+ int32 CriteriaTreeID = 0;
+ std::vector<ScenarioPOI> const* ScenarioPOIs = nullptr;
+ };
+
+ class ScenarioPOIs final : public ServerPacket
+ {
+ public:
+ ScenarioPOIs() : ServerPacket(SMSG_SCENARIO_POIS) { }
+
+ WorldPacket const* Write() override;
+
+ std::vector<ScenarioPOIData> ScenarioPOIDataStats;
+ };
+ }
+}
+
+#endif // ScenarioPackets_h__
diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp
index 7cd5e23def7..e24e9153121 100644
--- a/src/server/game/Server/Protocol/Opcodes.cpp
+++ b/src/server/game/Server/Protocol/Opcodes.cpp
@@ -627,7 +627,7 @@ void OpcodeTable::Initialize()
DEFINE_HANDLER(CMSG_QUERY_QUEST_INFO, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestQueryOpcode);
DEFINE_HANDLER(CMSG_QUERY_QUEST_REWARDS, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_QUERY_REALM_NAME, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL);
- DEFINE_HANDLER(CMSG_QUERY_SCENARIO_POI, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL);
+ DEFINE_HANDLER(CMSG_QUERY_SCENARIO_POI, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQueryScenarioPOI);
DEFINE_HANDLER(CMSG_QUERY_TIME, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQueryTimeOpcode);
DEFINE_HANDLER(CMSG_QUERY_VOID_STORAGE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleVoidStorageQuery);
DEFINE_HANDLER(CMSG_QUEST_CONFIRM_ACCEPT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestConfirmAccept);
@@ -1602,12 +1602,12 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_ROLE_CHOSEN, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_ROLE_POLL_INFORM, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_RUNE_REGEN_DEBUG, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_SCENARIO_BOOT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_SCENARIO_COMPLETED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_SCENARIO_POIS, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_SCENARIO_PROGRESS_UPDATE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_SCENARIO_SPELL_UPDATE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_SCENARIO_STATE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_SCENARIO_BOOT, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_SCENARIO_COMPLETED, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_SCENARIO_POIS, STATUS_NEVER, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_SCENARIO_PROGRESS_UPDATE, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_SCENARIO_SPELL_UPDATE, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_SCENARIO_STATE, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SCENE_OBJECT_EVENT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SCENE_OBJECT_PET_BATTLE_FINAL_ROUND, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_SCENE_OBJECT_PET_BATTLE_FINISHED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h
index 11ada4c421f..5c49c0887c9 100644
--- a/src/server/game/Server/WorldSession.h
+++ b/src/server/game/Server/WorldSession.h
@@ -581,6 +581,11 @@ namespace WorldPackets
class UseToy;
}
+ namespace Scenario
+ {
+ class QueryScenarioPOI;
+ }
+
namespace Scenes
{
class SceneTriggerEvent;
@@ -1736,6 +1741,9 @@ class TC_GAME_API WorldSession
void HandleArtifactSetAppearance(WorldPackets::Artifact::ArtifactSetAppearance& artifactSetAppearance);
void HandleConfirmArtifactRespec(WorldPackets::Artifact::ConfirmArtifactRespec& confirmArtifactRespec);
+ // Scenario
+ void HandleQueryScenarioPOI(WorldPackets::Scenario::QueryScenarioPOI& queryScenarioPOI);
+
union ConnectToKey
{
struct
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index 677b40da524..2b6a3da5cd3 100644
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -59,6 +59,7 @@
#include "Player.h"
#include "PoolMgr.h"
#include "GitRevision.h"
+#include "ScenarioMgr.h"
#include "ScriptMgr.h"
#include "ScriptReloadMgr.h"
#include "SkillDiscovery.h"
@@ -2120,6 +2121,13 @@ void World::SetInitialWorldSettings()
TC_LOG_INFO("server.loading", "Loading battle pets info...");
BattlePetMgr::Initialize();
+ TC_LOG_INFO("server.loading", "Loading scenarios");
+ sScenarioMgr->LoadDB2Data();
+ sScenarioMgr->LoadDBData();
+
+ TC_LOG_INFO("server.loading", "Loading scenario poi data");
+ sScenarioMgr->LoadScenarioPOI();
+
// Preload all cells, if required for the base maps
if (sWorld->getBoolConfig(CONFIG_BASEMAP_LOAD_GRIDS))
{