diff options
144 files changed, 6313 insertions, 895 deletions
diff --git a/dep/CascLib/src/CascPort.h b/dep/CascLib/src/CascPort.h index 6d0595ce522..3bf1efde4b8 100644 --- a/dep/CascLib/src/CascPort.h +++ b/dep/CascLib/src/CascPort.h @@ -66,6 +66,7 @@ #include <stdlib.h> #include <dirent.h> #include <errno.h> + #include <stddef.h> // Support for PowerPC on Max OS X #if (__ppc__ == 1) || (__POWERPC__ == 1) || (_ARCH_PPC == 1) diff --git a/dep/PackageList.txt b/dep/PackageList.txt index 12e0de314f7..ae4bf880c5b 100644 --- a/dep/PackageList.txt +++ b/dep/PackageList.txt @@ -38,7 +38,7 @@ recastnavigation (Recast is state of the art navigation mesh construction toolse CascLib (An open-source implementation of library for reading CASC storage from Blizzard games since 2014) https://github.com/ladislav-zezula/CascLib - Version: d3d17de30a1c5678375049f4cf3301a0a7962780 + Version: 3e3f4f443cb7b2893cbbe60b0a6efafebf48bc40 zmqpp (C++ binding for 0mq/zmq is a 'high-level' library that hides most of the c-style interface core 0mq provides.) https://github.com/zeromq/zmqpp diff --git a/sql/base/auth_database.sql b/sql/base/auth_database.sql index caeba7ec348..4610af447d9 100644 --- a/sql/base/auth_database.sql +++ b/sql/base/auth_database.sql @@ -545,7 +545,7 @@ CREATE TABLE `rbac_linked_permissions` ( LOCK TABLES `rbac_linked_permissions` WRITE; /*!40000 ALTER TABLE `rbac_linked_permissions` DISABLE KEYS */; -INSERT INTO `rbac_linked_permissions` VALUES (192,21),(192,42),(192,43),(192,193),(192,196),(192,778),(192,779),(192,780),(192,781),(192,782),(192,783),(192,784),(192,785),(192,786),(192,787),(192,788),(192,789),(192,790),(192,791),(192,792),(192,793),(192,794),(193,48),(193,194),(193,197),(194,1),(194,2),(194,11),(194,13),(194,14),(194,15),(194,16),(194,17),(194,18),(194,19),(194,20),(194,22),(194,23),(194,25),(194,26),(194,27),(194,28),(194,29),(194,30),(194,31),(194,32),(194,33),(194,34),(194,35),(194,36),(194,37),(194,38),(194,39),(194,40),(194,41),(194,44),(194,46),(194,47),(194,195),(194,198),(195,3),(195,4),(195,5),(195,6),(195,24),(195,49),(195,199),(196,200),(196,201),(196,208),(196,212),(196,213),(196,226),(196,227),(196,230),(196,231),(196,233),(196,234),(196,235),(196,238),(196,239),(196,240),(196,241),(196,242),(196,243),(196,244),(196,245),(196,246),(196,247),(196,248),(196,249),(196,250),(196,251),(196,252),(196,253),(196,254),(196,255),(196,256),(196,257),(196,258),(196,259),(196,260),(196,261),(196,262),(196,264),(196,265),(196,266),(196,267),(196,268),(196,269),(196,270),(196,271),(196,272),(196,279),(196,280),(196,283),(196,287),(196,288),(196,289),(196,290),(196,291),(196,292),(196,293),(196,294),(196,295),(196,296),(196,297),(196,298),(196,299),(196,302),(196,303),(196,304),(196,305),(196,306),(196,307),(196,308),(196,309),(196,310),(196,313),(196,314),(196,319),(196,320),(196,321),(196,322),(196,323),(196,324),(196,325),(196,326),(196,327),(196,328),(196,329),(196,330),(196,331),(196,332),(196,333),(196,334),(196,335),(196,336),(196,337),(196,338),(196,339),(196,340),(196,341),(196,342),(196,343),(196,344),(196,345),(196,346),(196,347),(196,348),(196,349),(196,350),(196,351),(196,352),(196,353),(196,354),(196,355),(196,356),(196,357),(196,358),(196,359),(196,360),(196,361),(196,362),(196,363),(196,364),(196,365),(196,366),(196,373),(196,375),(196,400),(196,401),(196,402),(196,403),(196,404),(196,405),(196,406),(196,407),(196,417),(196,418),(196,419),(196,420),(196,421),(196,422),(196,423),(196,424),(196,425),(196,426),(196,427),(196,428),(196,429),(196,434),(196,435),(196,436),(196,437),(196,438),(196,439),(196,440),(196,441),(196,442),(196,443),(196,444),(196,445),(196,446),(196,447),(196,448),(196,449),(196,450),(196,451),(196,452),(196,453),(196,454),(196,455),(196,456),(196,457),(196,458),(196,459),(196,461),(196,463),(196,464),(196,465),(196,472),(196,473),(196,474),(196,475),(196,476),(196,477),(196,478),(196,488),(196,489),(196,491),(196,492),(196,493),(196,495),(196,497),(196,498),(196,499),(196,500),(196,502),(196,503),(196,505),(196,508),(196,511),(196,513),(196,514),(196,516),(196,519),(196,522),(196,523),(196,526),(196,527),(196,529),(196,530),(196,533),(196,535),(196,536),(196,537),(196,538),(196,539),(196,540),(196,541),(196,556),(196,581),(196,582),(196,592),(196,593),(196,596),(196,602),(196,603),(196,604),(196,605),(196,606),(196,607),(196,608),(196,609),(196,610),(196,611),(196,612),(196,613),(196,614),(196,615),(196,616),(196,617),(196,618),(196,619),(196,620),(196,621),(196,622),(196,623),(196,624),(196,625),(196,626),(196,627),(196,628),(196,629),(196,630),(196,631),(194,632),(196,633),(196,634),(196,635),(196,636),(196,637),(196,638),(196,639),(196,640),(196,641),(196,642),(196,643),(196,644),(196,645),(196,646),(196,647),(196,648),(196,649),(196,650),(196,651),(196,652),(196,653),(196,654),(196,655),(196,656),(196,657),(196,658),(196,659),(196,660),(196,661),(196,662),(196,663),(196,664),(196,665),(196,666),(196,667),(196,668),(196,669),(196,670),(196,671),(196,672),(196,673),(196,674),(196,675),(196,676),(196,677),(196,678),(196,679),(196,680),(196,681),(196,682),(196,683),(196,684),(196,685),(196,686),(196,687),(196,688),(196,689),(196,690),(196,691),(196,692),(196,693),(196,694),(196,695),(196,696),(196,697),(196,698),(196,699),(196,700),(196,701),(196,702),(196,703),(196,704),(196,705),(196,706),(196,707),(196,708),(196,709),(196,710),(196,711),(196,712),(196,713),(196,714),(196,715),(196,716),(196,717),(196,718),(196,719),(196,721),(196,722),(196,723),(196,724),(196,725),(196,726),(196,727),(196,728),(196,729),(196,730),(196,733),(196,734),(196,735),(196,736),(196,738),(196,739),(196,748),(196,753),(196,757),(196,773),(196,777),(197,232),(197,236),(197,237),(197,273),(197,274),(197,275),(197,276),(197,277),(197,284),(197,285),(197,286),(197,301),(197,311),(197,387),(197,388),(197,389),(197,390),(197,391),(197,392),(197,393),(197,394),(197,395),(197,396),(197,397),(197,398),(197,399),(197,479),(197,480),(197,481),(197,482),(197,485),(197,486),(197,487),(197,494),(197,506),(197,509),(197,510),(197,517),(197,518),(197,521),(197,542),(197,543),(197,550),(197,558),(197,568),(197,571),(197,572),(197,573),(197,574),(197,575),(197,576),(197,577),(197,578),(197,579),(197,580),(197,583),(197,584),(197,585),(197,586),(197,587),(197,588),(197,589),(197,590),(197,591),(197,594),(197,595),(197,601),(197,743),(197,750),(197,758),(197,761),(197,762),(197,763),(197,764),(197,765),(197,766),(197,767),(197,768),(197,769),(197,770),(197,771),(197,772),(197,774),(198,218),(198,300),(198,312),(198,315),(198,316),(198,317),(198,318),(198,367),(198,368),(198,369),(198,370),(198,371),(198,372),(198,374),(198,376),(198,377),(198,378),(198,379),(198,380),(198,381),(198,382),(198,383),(198,384),(198,385),(198,386),(198,408),(198,409),(198,410),(198,411),(198,412),(198,413),(198,414),(198,415),(198,416),(198,430),(198,431),(198,432),(198,433),(198,462),(198,466),(198,467),(198,468),(198,469),(198,470),(198,471),(198,483),(198,484),(198,490),(198,504),(198,512),(198,515),(198,520),(198,524),(198,528),(198,531),(198,532),(198,544),(198,545),(198,546),(198,547),(198,548),(198,549),(198,551),(198,552),(198,553),(198,554),(198,555),(198,557),(198,559),(198,560),(198,561),(198,562),(198,563),(198,564),(198,565),(198,566),(198,567),(198,569),(198,570),(198,597),(198,598),(198,599),(198,600),(198,737),(198,740),(198,741),(198,742),(198,744),(198,745),(198,746),(198,747),(198,749),(198,751),(198,752),(198,754),(198,755),(198,756),(198,759),(198,760),(199,207),(199,209),(199,210),(199,211),(199,217),(199,221),(199,222),(199,223),(199,225),(199,263),(199,496),(199,501),(199,507),(199,525),(199,534); +INSERT INTO `rbac_linked_permissions` VALUES (192,21),(192,42),(192,43),(192,193),(192,196),(192,778),(192,779),(192,780),(192,781),(192,782),(192,783),(192,784),(192,785),(192,786),(192,787),(192,788),(192,789),(192,790),(192,791),(192,792),(192,793),(192,794),(193,48),(193,194),(193,197),(194,1),(194,2),(194,11),(194,13),(194,14),(194,15),(194,16),(194,17),(194,18),(194,19),(194,20),(194,22),(194,23),(194,25),(194,26),(194,27),(194,28),(194,29),(194,30),(194,31),(194,32),(194,33),(194,34),(194,35),(194,36),(194,37),(194,38),(194,39),(194,40),(194,41),(194,44),(194,46),(194,47),(194,195),(194,198),(195,3),(195,4),(195,5),(195,6),(195,24),(195,49),(195,199),(196,200),(196,201),(196,208),(196,212),(196,213),(196,214),(196,215),(196,216),(196,226),(196,227),(196,230),(196,231),(196,233),(196,234),(196,235),(196,238),(196,239),(196,240),(196,241),(196,242),(196,243),(196,244),(196,245),(196,246),(196,247),(196,248),(196,249),(196,250),(196,251),(196,252),(196,253),(196,254),(196,255),(196,256),(196,257),(196,258),(196,259),(196,260),(196,261),(196,262),(196,264),(196,265),(196,266),(196,267),(196,268),(196,269),(196,270),(196,271),(196,272),(196,279),(196,280),(196,283),(196,287),(196,288),(196,289),(196,290),(196,291),(196,292),(196,293),(196,294),(196,295),(196,296),(196,297),(196,298),(196,299),(196,302),(196,303),(196,304),(196,305),(196,306),(196,307),(196,308),(196,309),(196,310),(196,313),(196,314),(196,319),(196,320),(196,321),(196,322),(196,323),(196,324),(196,325),(196,326),(196,327),(196,328),(196,329),(196,330),(196,331),(196,332),(196,333),(196,334),(196,335),(196,336),(196,337),(196,338),(196,339),(196,340),(196,341),(196,342),(196,343),(196,344),(196,345),(196,346),(196,347),(196,348),(196,349),(196,350),(196,351),(196,352),(196,353),(196,354),(196,355),(196,356),(196,357),(196,358),(196,359),(196,360),(196,361),(196,362),(196,363),(196,364),(196,365),(196,366),(196,373),(196,375),(196,400),(196,401),(196,402),(196,403),(196,404),(196,405),(196,406),(196,407),(196,417),(196,418),(196,419),(196,420),(196,421),(196,422),(196,423),(196,424),(196,425),(196,426),(196,427),(196,428),(196,429),(196,434),(196,435),(196,436),(196,437),(196,438),(196,439),(196,440),(196,441),(196,442),(196,443),(196,444),(196,445),(196,446),(196,447),(196,448),(196,449),(196,450),(196,451),(196,452),(196,453),(196,454),(196,455),(196,456),(196,457),(196,458),(196,459),(196,461),(196,463),(196,464),(196,465),(196,472),(196,473),(196,474),(196,475),(196,476),(196,477),(196,478),(196,488),(196,489),(196,491),(196,492),(196,493),(196,495),(196,497),(196,498),(196,499),(196,500),(196,502),(196,503),(196,505),(196,508),(196,511),(196,513),(196,514),(196,516),(196,519),(196,522),(196,523),(196,526),(196,527),(196,529),(196,530),(196,533),(196,535),(196,536),(196,537),(196,538),(196,539),(196,540),(196,541),(196,556),(196,581),(196,582),(196,592),(196,593),(196,596),(196,602),(196,603),(196,604),(196,605),(196,606),(196,607),(196,608),(196,609),(196,610),(196,611),(196,612),(196,613),(196,614),(196,615),(196,616),(196,617),(196,618),(196,619),(196,620),(196,621),(196,622),(196,623),(196,624),(196,625),(196,626),(196,627),(196,628),(196,629),(196,630),(196,631),(194,632),(196,633),(196,634),(196,635),(196,636),(196,637),(196,638),(196,639),(196,640),(196,641),(196,642),(196,643),(196,644),(196,645),(196,646),(196,647),(196,648),(196,649),(196,650),(196,651),(196,652),(196,653),(196,654),(196,655),(196,656),(196,657),(196,658),(196,659),(196,660),(196,661),(196,662),(196,663),(196,664),(196,665),(196,666),(196,667),(196,668),(196,669),(196,670),(196,671),(196,672),(196,673),(196,674),(196,675),(196,676),(196,677),(196,678),(196,679),(196,680),(196,681),(196,682),(196,683),(196,684),(196,685),(196,686),(196,687),(196,688),(196,689),(196,690),(196,691),(196,692),(196,693),(196,694),(196,695),(196,696),(196,697),(196,698),(196,699),(196,700),(196,701),(196,702),(196,703),(196,704),(196,705),(196,706),(196,707),(196,708),(196,709),(196,710),(196,711),(196,712),(196,713),(196,714),(196,715),(196,716),(196,717),(196,718),(196,719),(196,721),(196,722),(196,723),(196,724),(196,725),(196,726),(196,727),(196,728),(196,729),(196,730),(196,733),(196,734),(196,735),(196,736),(196,738),(196,739),(196,748),(196,753),(196,757),(196,773),(196,777),(197,232),(197,236),(197,237),(197,273),(197,274),(197,275),(197,276),(197,277),(197,284),(197,285),(197,286),(197,301),(197,311),(197,387),(197,388),(197,389),(197,390),(197,391),(197,392),(197,393),(197,394),(197,395),(197,396),(197,397),(197,398),(197,399),(197,479),(197,480),(197,481),(197,482),(197,485),(197,486),(197,487),(197,494),(197,506),(197,509),(197,510),(197,517),(197,518),(197,521),(197,542),(197,543),(197,550),(197,558),(197,568),(197,571),(197,572),(197,573),(197,574),(197,575),(197,576),(197,577),(197,578),(197,579),(197,580),(197,583),(197,584),(197,585),(197,586),(197,587),(197,588),(197,589),(197,590),(197,591),(197,594),(197,595),(197,601),(197,743),(197,750),(197,758),(197,761),(197,762),(197,763),(197,764),(197,765),(197,766),(197,767),(197,768),(197,769),(197,770),(197,771),(197,772),(197,774),(198,218),(198,300),(198,312),(198,315),(198,316),(198,317),(198,318),(198,367),(198,368),(198,369),(198,370),(198,371),(198,372),(198,374),(198,376),(198,377),(198,378),(198,379),(198,380),(198,381),(198,382),(198,383),(198,384),(198,385),(198,386),(198,408),(198,409),(198,410),(198,411),(198,412),(198,413),(198,414),(198,415),(198,416),(198,430),(198,431),(198,432),(198,433),(198,462),(198,466),(198,467),(198,468),(198,469),(198,470),(198,471),(198,483),(198,484),(198,490),(198,504),(198,512),(198,515),(198,520),(198,524),(198,528),(198,531),(198,532),(198,544),(198,545),(198,546),(198,547),(198,548),(198,549),(198,551),(198,552),(198,553),(198,554),(198,555),(198,557),(198,559),(198,560),(198,561),(198,562),(198,563),(198,564),(198,565),(198,566),(198,567),(198,569),(198,570),(198,597),(198,598),(198,599),(198,600),(198,737),(198,740),(198,741),(198,742),(198,744),(198,745),(198,746),(198,747),(198,749),(198,751),(198,752),(198,754),(198,755),(198,756),(198,759),(198,760),(199,207),(199,209),(199,210),(199,211),(199,217),(199,221),(199,222),(199,223),(199,225),(199,263),(199,496),(199,501),(199,507),(199,525),(199,534); /*!40000 ALTER TABLE `rbac_linked_permissions` ENABLE KEYS */; UNLOCK TABLES; @@ -617,7 +617,7 @@ CREATE TABLE `realmlist` ( `timezone` tinyint(3) unsigned NOT NULL DEFAULT '0', `allowedSecurityLevel` tinyint(3) unsigned NOT NULL DEFAULT '0', `population` float unsigned NOT NULL DEFAULT '0', - `gamebuild` int(10) unsigned NOT NULL DEFAULT '15595', + `gamebuild` int(10) unsigned NOT NULL DEFAULT '19057', `Region` tinyint(3) unsigned NOT NULL DEFAULT '2', `Battlegroup` tinyint(3) unsigned NOT NULL DEFAULT '1', PRIMARY KEY (`id`), @@ -631,7 +631,7 @@ CREATE TABLE `realmlist` ( LOCK TABLES `realmlist` WRITE; /*!40000 ALTER TABLE `realmlist` DISABLE KEYS */; -INSERT INTO `realmlist` VALUES (1,'Trinity','127.0.0.1','127.0.0.1','255.255.255.0',8085,1,0,1,0,0,15595,2,1); +INSERT INTO `realmlist` VALUES (1,'Trinity','127.0.0.1','127.0.0.1','255.255.255.0',8085,0,0,1,0,0,19057,2,1); /*!40000 ALTER TABLE `realmlist` ENABLE KEYS */; UNLOCK TABLES; diff --git a/sql/updates/auth/2014_11_09_00_auth.sql b/sql/updates/auth/2014_11_09_00_auth.sql new file mode 100644 index 00000000000..8cbe649b440 --- /dev/null +++ b/sql/updates/auth/2014_11_09_00_auth.sql @@ -0,0 +1,2 @@ +UPDATE `realmlist` SET `gamebuild`=19057; +ALTER TABLE `realmlist` CHANGE `gamebuild` `gamebuild` INT(10) UNSIGNED NOT NULL DEFAULT '19057'; diff --git a/sql/updates/auth/2014_11_10_00_auth.sql b/sql/updates/auth/2014_11_10_00_auth.sql new file mode 100644 index 00000000000..ce4d814f620 --- /dev/null +++ b/sql/updates/auth/2014_11_10_00_auth.sql @@ -0,0 +1,11 @@ +DELETE FROM `rbac_permissions` WHERE `id` IN (214,215,216); +INSERT INTO `rbac_permissions` (`id`, `name`) VALUES +(214, 'Command: bnetaccount link'), +(215, 'Command: bnetaccount unlink'), +(216, 'Command: bnetaccount gameaccountcreate'); + +DELETE FROM `rbac_linked_permissions` WHERE `linkedId` IN (214,215,216); +INSERT INTO `rbac_linked_permissions` (`id`, `linkedId`) VALUES +(196, 214), +(196, 215), +(196, 216); diff --git a/sql/updates/world/2014_11_07_00_world.sql b/sql/updates/world/2014_11_07_00_world.sql new file mode 100644 index 00000000000..f10ca6690e0 --- /dev/null +++ b/sql/updates/world/2014_11_07_00_world.sql @@ -0,0 +1,38 @@ +UPDATE `creature_template` SET `AIName`='SmartAI',`ScriptName`='' WHERE `entry` IN(26158,26167,26162); +DELETE FROM `smart_scripts` WHERE `entryorguid` IN(26158,26167,26162) AND `source_type`=0; +DELETE FROM `smart_scripts` WHERE `entryorguid` IN(2616700,2616701,2616702,2616703) AND `source_type`=9; + +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(26158, 0, 0, 0, 19, 0, 100, 0, 11930, 0, 0, 0, 85, 46657, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'Mother Tauranook - On Quest Accept (Across Transborea) - Invoker Cast Taunka''le Evacuee'), +(26167, 0, 0, 0, 11, 0, 100, 0, 0, 0, 0, 0, 11, 46669, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Taunka''le Evacuee - On Spawn - Cast Evacuee Random Action'), +(26167, 0, 1, 0, 8, 0, 100, 0, 46663, 0, 0, 0, 87, 2616700, 2616701, 2616702, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Taunka''le Evacuee - On Spellhit (Evacuee Random Action) - Run Random Script'), +(26167, 0, 2, 0, 8, 0, 100, 1, 46677, 0, 0, 0, 80, 2616703, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Taunka''le Evacuee - On Spellhit (Evacuee Reaches Dragonblight) - Run Script'), +(26162, 0, 0, 0, 1, 0, 100, 0, 0, 0, 1000, 1000, 11, 46677, 0, 0, 0, 0, 0, 19, 26167, 0, 0, 0, 0, 0, 0, 'Transborea Generator 001 - OOC - Cast Evacuee Reaches Dragonblight'), +(2616700, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Taunka''le Evacuee - Script 1 - Say Line'), +(2616701, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Taunka''le Evacuee - Script 2 - Say Line'), +(2616701, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 11, 46694, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 'Taunka''le Evacuee - Script 2 - Cast Feed'), +(2616702, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 11, 46670, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Taunka''le Evacuee - Script 3 - Cast Transborea Monster'), +(2616702, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Taunka''le Evacuee - Script 3 - Say Line'), +(2616703, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 28, 46669, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Taunka''le Evacuee - Script 4 - Remove Aura Evacuee Random Action'), +(2616703, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 1, 3, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Taunka''le Evacuee - Script 4 - Say Line'), +(2616703, 9, 2, 0, 0, 0, 100, 0, 6000, 6000, 0, 0, 1, 4, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Taunka''le Evacuee - Script 4 - Say Line'), +(2616703, 9, 3, 0, 0, 0, 100, 0, 6000, 6000, 0, 0, 1, 5, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Taunka''le Evacuee - Script 4 - Say Line'), +(2616703, 9, 4, 0, 0, 0, 100, 0, 6000, 6000, 0, 0, 1, 6, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Taunka''le Evacuee - Script 4 - Say Line'), +(2616703, 9, 5, 0, 0, 0, 100, 0, 6000, 6000, 0, 0, 1, 7, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Taunka''le Evacuee - Script 4 - Say Line'), +(2616703, 9, 6, 0, 0, 0, 100, 0, 0, 0, 0, 0, 11, 46676, 0, 0, 0, 0, 0, 23, 0, 0, 0, 0, 0, 0, 0, 'Taunka''le Evacuee - Script 4 - Cast Across Transborea Complete'), +(2616703, 9, 7, 0, 0, 0, 100, 0, 0, 0, 0, 0, 41, 3000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Taunka''le Evacuee - Script 4 - Despawn'); + +DELETE FROM `creature_template_addon` WHERE `entry`=26167; +INSERT INTO `creature_template_addon` (`entry`, `path_id`, `mount`, `bytes1`, `bytes2`, `emote`, `auras`) VALUES +(26167, 0, 0, 0, 4097, 0, '46669'); + +DELETE FROM `creature_text` WHERE `entry`=26167; +INSERT INTO `creature_text` (`entry`, `groupid`, `id`, `text`, `type`, `language`, `probability`, `emote`, `duration`, `sound`, `comment`, `BroadcastTextID`) VALUES +(26167, 0, 0, '%s cries.', 16, 1, 100, 18, 0, 0, 'Taunka''le Evacuee',25304), +(26167, 1, 0, 'Stop!', 12, 1, 100, 5, 0, 0, 'Taunka''le Evacuee',25294), +(26167, 2, 0, 'Look out!', 12, 1, 100, 0, 0, 0, 'Taunka''le Evacuee',25299), +(26167, 3, 0, '%s points northeast.', 16, 1, 100, 25, 0, 0, 'Taunka''le Evacuee',25311), +(26167, 4, 0, 'The smoke in the distance... It is Wartook. He is trying to tell us something...', 12, 1, 100, 1, 0, 0, 'Taunka''le Evacuee',25312), +(26167, 5, 0, '%s expertly identifies the messages hidden within the smoke signals.', 16, 1, 100, 20, 0, 0, 'Taunka''le Evacuee',25315), +(26167, 6, 0, 'No... It cannot be true...', 12, 1, 100, 274, 0, 0, 'Taunka''le Evacuee',25313), +(26167, 7, 0, 'Icemist... Not Icemist... NO!!! Come quickly, hero! Follow me!', 12, 1, 100, 15, 0, 0, 'Taunka''le Evacuee',25314); diff --git a/sql/updates/world/2014_11_07_01_world.sql b/sql/updates/world/2014_11_07_01_world.sql new file mode 100644 index 00000000000..9586e499b69 --- /dev/null +++ b/sql/updates/world/2014_11_07_01_world.sql @@ -0,0 +1,43 @@ +SET @OGuid := 5513; + +UPDATE `creature_template` SET `ainame`='SmartAI', `scriptname`='' WHERE `entry` IN(25379,25761,25759); +DELETE FROM `smart_scripts` WHERE `entryorguid` IN(25379,25761,25759) AND `source_type`=0; +DELETE FROM `smart_scripts` WHERE `entryorguid` =2575900 AND `source_type`=9; + +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(25379, 0, 0, 0, 19, 0, 100, 0, 11711, 0, 0, 0, 85, 45963, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'Warden Nork Bloodfrenzy - On Quest Accept (Coward Delivery... Under 30 Minutes or its Free - Invoker Cast Call Alliance Deserter'), +(25379, 0, 1, 2, 62, 0, 100, 0, 9184, 0, 0, 0, 85, 45963, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'Warden Nork Bloodfrenzy - On Gossip Option 0 Selected - Invoker Cast Call Alliance Deserter'), +(25379, 0, 2, 3, 61, 0, 100, 0, 0, 0, 0, 0, 72, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'Warden Nork Bloodfrenzy - On Gossip Option 0 Selected - Close Gossip'), +(25379, 0, 3, 0, 61, 0, 100, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'Warden Nork Bloodfrenzy - On Gossip Option 0 Selected - Say'), +(25761, 0, 0, 0, 54, 0, 100, 0, 0, 0, 0, 0, 11, 45957, 0, 0, 0, 0, 0, 23, 0, 0, 0, 0, 0, 0, 0, 'Alliance Deserter - On Just Summoned - Cast Escorting Alliance Deserter'), +(25761, 0, 1, 0, 8, 0, 100, 0, 45981, 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Alliance Deserter - On Spellhit (Escorting Alliance Deserter) - Despawn'), +(25761, 0, 2, 0, 38, 0, 100, 0, 1, 1, 0, 0, 41, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Alliance Deserter - On Spellhit (Escorting Alliance Deserter) - Despawn'), +(25759, 0, 0, 1, 54, 0, 100, 0, 0, 0, 0, 0, 64, 1, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'Valiance Keep Officer - On Just Summoned - Store Targetlist'), +(25759, 0, 1, 0, 61, 0, 100, 0, 0, 0, 0, 0, 80, 2575900, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Valiance Keep Officer - On Just Summoned - Run Script'), +(2575900, 9, 0, 0, 0, 0, 100, 0, 5000, 5000, 0, 0, 1, 0, 0, 0, 0, 0, 0, 12, 1, 0, 0, 0, 0, 0, 0, 'Valiance Keep Officer - Script - Say'), +(2575900, 9, 1, 0, 0, 0, 100, 0, 5000, 5000, 0, 0, 11, 45981, 2, 0, 0, 0, 0, 12, 1, 0, 0, 0, 0, 0, 0, 'Valiance Keep Officer - Script - Cast Escorting Alliance Deserter'), +(2575900, 9, 2, 0, 0, 0, 100, 0, 0, 0, 0, 0, 15,11711, 0, 0, 0, 0, 0, 12, 1, 0, 0, 0, 0, 0, 0, 'Valiance Keep Officer - Script - Complete quest'), +(2575900, 9, 3, 0, 0, 0, 100, 0, 0, 0, 0, 0, 45,1, 1, 0, 0, 0, 0, 19, 25761, 0, 0, 0, 0, 0, 0, 'Valiance Keep Officer - Script - Set Data on Alliance Deserter '), +(2575900, 9, 4, 0, 0, 0, 100, 0, 5000, 5000, 0, 0, 41, 10000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Valiance Keep Officer - Script - Despawn'); + +DELETE FROM `creature_text` WHERE `entry` IN(25379,25759); +INSERT INTO `creature_text` (`entry`, `groupid`, `id`, `text`, `type`, `language`, `probability`, `emote`, `duration`, `sound`, `comment`,`BroadcastTextID`) VALUES +(25379, 0, 0, 'Try to not lose this one, $n. It is important that we at least try and keep up appearances with the Alliance.', 15, 1, 100, 0, 0, 0, 'Warden Nork Bloodfrenzy',24977), +(25759, 0, 0, 'Thank you, $r. I will take this miserable cur from you now.', 12, 1, 100, 1, 0, 0, 'Valiance Keep Officer',24966); + +DELETE FROM `gossip_menu_option` WHERE `menu_id`=9184; +INSERT INTO `gossip_menu_option` (`menu_id`, `id`, `option_icon`, `option_text`, `OptionBroadcastTextID`, `option_id`, `npc_option_npcflag`, `action_menu_id`, `action_poi_id`, `box_coded`, `box_money`, `box_text`, `BoxBroadcastTextID`) VALUES +(9184, 0, 0, 'I am embarassed to say it, Nork, but my deserter has gone missing.', 24976, 1, 1, 0, 0, 0, 0, '', 0); -- 25379 + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=15 AND `SourceGroup`=9184; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES +(15, 9184, 0, 0, 0,9, 0, 11711, 0, 0, 0, 0, 0, '', 'Warden Nork Bloodfrenzy - Show Gossip option only if player has Coward Delivery... Under 30 Minutes or its Free in quest log'), +(15, 9184, 0, 0, 0,1, 0, 45963, 0, 0, 1, 0, 0, '', 'Warden Nork Bloodfrenzy - Show Gossip option only if player does not have aura Call Alliance Deserter'); + +DELETE FROM `gameobject` WHERE `id`=187894; +INSERT INTO `gameobject` (`guid`, `id`, `map`, `spawnMask`, `phaseMask`, `position_x`, `position_y`, `position_z`, `orientation`, `rotation0`, `rotation1`, `rotation2`, `rotation3`, `spawntimesecs`, `animprogress`, `state`, `VerifiedBuild`) VALUES +(@OGuid, 187894, 571, 1, 1, 2942.86, 5381.48, 60.6052, 2.28369, 0, 0, 0.909402, 0.415919, 300, 0, 1, 0); + +DELETE FROM `spell_scripts` WHERE `id`=45958; +INSERT INTO `spell_scripts` (`id`, `effIndex`, `delay`, `command`, `datalong`, `datalong2`, `dataint`, `x`, `y`, `z`, `o`) VALUES +(45958, 0, 0, 15, 45956, 0, 0, 0, 0, 0, 0); diff --git a/sql/updates/world/2014_11_08_00_world.sql b/sql/updates/world/2014_11_08_00_world.sql new file mode 100644 index 00000000000..64a59180b46 --- /dev/null +++ b/sql/updates/world/2014_11_08_00_world.sql @@ -0,0 +1,350 @@ +-- The Stonecore +DELETE FROM `instance_template` WHERE `map` = 725; +INSERT INTO `instance_template` (`map`, `parent`, `script`, `allowMount`) VALUES +(725, 0, 'instance_stonecore', 0); + +DELETE FROM `instance_encounters` WHERE `entry` IN (1056, 1059, 1058, 1057); +INSERT INTO `instance_encounters` (`entry`, `creditType`, `creditEntry`, `lastEncounterDungeon`, `comment`) VALUES +(1056, 0, 43438, 0, 'Corborus'), +(1059, 0, 43214, 0, 'Slabhide'), +(1058, 0, 42188, 0, 'Ozruk'), +(1057, 0, 42333, 0, 'High Priestess Azil'); + +UPDATE `creature_template` SET `mechanic_immune_mask` = 617299839 WHERE `entry` IN (43391, 43438, 43214, 42188, 42333); + +-- Script names +UPDATE `creature_template` SET `ScriptName` = 'boss_corborus' WHERE `entry` = 43438; +UPDATE `creature_template` SET `ScriptName` = 'boss_slabhide' WHERE `entry` = 43214; +UPDATE `creature_template` SET `ScriptName` = 'boss_ozruk' WHERE `entry` = 42188; +UPDATE `creature_template` SET `ScriptName` = 'boss_high_priestess_azil' WHERE `entry` = 42333; +UPDATE `creature_template` SET `ScriptName` = 'npc_rock_borer' WHERE `entry` = 43917; +UPDATE `creature_template` SET `ScriptName` = 'npc_sc_millhouse_manastorm' WHERE `entry` = 43391; +UPDATE `creature_template` SET `ScriptName` = 'npc_lava_fissure' WHERE `entry` = 43242; +UPDATE `creature_template` SET `ScriptName` = 'npc_stalactite_trigger' WHERE `entry` = 43159; +UPDATE `creature_template` SET `ScriptName` = 'npc_devout_follower' WHERE `entry` = 42428; +UPDATE `creature_template` SET `ScriptName` = 'npc_gravity_well' WHERE `entry` = 42499; +UPDATE `creature_template` SET `ScriptName` = 'npc_seismic_shard' WHERE `entry` = 42355; + +DELETE FROM `spell_script_names` WHERE `spell_id` IN (81459, 45313, 93167, 81008, 81035, 81028, 80650, 80654, 80643, 92653, 80647, 92309, 92306, 92300, 92393, 78835, 92429, 79200, 79196, 79251, 79249, 79332, 86862, 86863, 79015); +INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES +(81459, 'spell_force_of_earth'), +(45313, 'spell_sc_anchor_here'), +(93167, 'spell_sc_twilight_documents'), +(81008, 'spell_sc_quake'), +(81035, 'spell_s81035_stalactite'), +(81028, 'spell_s81028_s80650_stalactite'), +(80650, 'spell_s81028_s80650_stalactite'), +(80654, 'spell_stalactite_mod_dest_height'), +(80643, 'spell_stalactite_mod_dest_height'), +(92653, 'spell_stalactite_mod_dest_height'), +(80647, 'spell_stalactite_mod_dest_height'), +(92309, 'spell_stalactite_mod_dest_height'), +(92306, 'spell_s92306_crystal_storm'), +(92300, 'spell_s92300_crystal_storm'), +(92393, 'spell_rupture'), +(78835, 'spell_elementium_spike_shield'), +(92429, 'spell_elementium_spike_shield'), +(79200, 'spell_summon_wave_south'), +(79196, 'spell_summon_wave_west'), +(79251, 'spell_gravity_well_damage_nearby'), +(79249, 'spell_gravity_well_damage'), +(79332, 'spell_gravity_well_pull'), +(86862, 'spell_seismic_shard_prepare'), +(86863, 'spell_seismic_shard_change_seat'), +(79015, 'spell_seismic_shard'); + +DELETE FROM `areatrigger_scripts` WHERE `entry` IN (6076, 6070); +INSERT INTO `areatrigger_scripts` (`entry`, `ScriptName`) VALUES +(6076, 'at_sc_corborus_intro'), +(6070, 'at_sc_slabhide_intro'); + +-- Twilight Documents object is spawned by Millhouse. +DELETE FROM `gameobject` WHERE `id` = 207415; + +-- Millhouse Manastorm texts +DELETE FROM `creature_text` WHERE `entry` IN (43391); +INSERT INTO `creature_text` (`entry`, `groupid`, `id`, `text`, `type`, `language`, `probability`, `emote`, `duration`, `sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES +(43391, 0, 1, 'Follow me if you dare!', 14, 0, 100, 0, 0, 21783, 0, 0, 'Millhouse Manastorm'), +(43391, 0, 2, 'It''s time for a tactical retreat!', 14, 0, 100, 0, 0, 21784, 0, 0, 'Millhouse Manastorm'), +(43391, 0, 3, 'You''re gonna be sorry!', 14, 0, 100, 0, 0, 21785, 0, 0, 'Millhouse Manastorm'), +(43391, 0, 4, 'Don''t say I didn''t warn ya!', 14, 0, 100, 0, 0, 21786, 0, 0, 'Millhouse Manastorm'), +(43391, 1, 1, 'Ah-ha! I''ve got you right where I want you!', 14, 0, 100, 0, 0, 21787, 0, 0, 'Millhouse Manastorm'), +(43391, 1, 2, 'Now... witness the full power of Millhouse Manastorm!', 14, 0, 100, 0, 0, 21788, 0, 0, 'Millhouse Manastorm'), +(43391, 1, 3, 'Prison taught me one very important lesson, well, two if you count how to hold your soap, but yes! SURVIVAL!', 14, 0, 100, 0, 0, 21789, 0, 0, 'Millhouse Manastorm'); + +-- Creature formations for Millhouse event (340418 -> trash, 340492 -> last group) +DELETE FROM `creature_formations` WHERE `leaderGUID` IN (340418, 340392, 340492); +INSERT INTO `creature_formations` (`leaderGUID`, `memberGUID`, `dist`, `angle`, `groupAI`, `point_1`, `point_2`) VALUES +(340418, 340418, 0, 0, 0, 0, 0), +(340418, 340419, 0, 0, 0, 0, 0), +(340418, 340421, 0, 0, 0, 0, 0), +(340418, 340422, 0, 0, 0, 0, 0), +(340418, 340465, 0, 0, 0, 0, 0), +(340418, 340466, 0, 0, 0, 0, 0), +(340418, 340467, 0, 0, 0, 0, 0), +(340418, 340469, 0, 0, 0, 0, 0), +(340418, 340476, 0, 0, 0, 0, 0), +(340418, 340477, 0, 0, 0, 0, 0), +(340418, 340478, 0, 0, 0, 0, 0), +(340418, 340479, 0, 0, 0, 0, 0), +(340492, 340492, 0, 0, 0, 0, 0), +(340492, 340493, 0, 0, 0, 0, 0), +(340492, 340494, 0, 0, 0, 0, 0), +(340492, 340495, 0, 0, 0, 0, 0), +(340492, 340496, 0, 0, 0, 0, 0), +(340492, 340497, 0, 0, 0, 0, 0), +(340492, 340498, 0, 0, 0, 0, 0), +(340492, 340499, 0, 0, 0, 0, 0), +(340492, 340500, 0, 0, 0, 0, 0); + +-- Stonecore Flayer SAI +UPDATE `creature_template` SET `AIName` = "SmartAI" WHERE `entry` = 42808; +DELETE FROM `smart_scripts` WHERE `entryorguid` = 42808 AND `source_type` = 0; +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(42808, 0, 0, 0, 1, 0, 100, 0, 0, 0, 60000, 60000, 17, 438, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "Stonecore Flayer - In Combat - Set emote state 438"), +(42808, 0, 1, 0, 4, 0, 100, 0, 2500, 10000, 10000, 15000, 17, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "Stonecore Flayer - On Aggro - Set emote state 0"), +(42808, 0, 2, 0, 0, 0, 100, 0, 2500, 10000, 10000, 15000, 11, 79922, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "Stonecore Flayer - In Combat - Cast 'Flay'"); + +-- Stonecore Earthshaper SAI +UPDATE `creature_template` SET `AIName` = "SmartAI" WHERE `entry` = 43537; +DELETE FROM `smart_scripts` WHERE `entryorguid` = 43537 AND `source_type` = 0; +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(43537, 0, 0, 1, 25, 0, 100, 0, 0, 0, 0, 0, 22, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "Stonecore Earthshaper - On Reset - Set Phase 1"), +(43537, 0, 1, 0, 61, 0, 100, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "Stonecore Earthshaper - Linked - Demorph"), +(43537, 0, 2, 0, 0, 1, 100, 0, 3000, 3000, 10000, 15000, 11, 81576, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, "Stonecore Earthshaper - In Combat (Phase 1) - Cast 'Lava Burst'"), +(43537, 0, 3, 4, 0, 1, 100, 0, 9000, 9000, 12000, 12000, 11, 81459, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "Stonecore Earthshaper - In Combat (Phase 1) - Cast 'Force of Earth'"), +(43537, 0, 4, 0, 61, 1, 100, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "Stonecore Earthshaper - Linked - Say Text 0"), +(43537, 0, 5, 0, 0, 1, 100, 0, 15000, 15000, 10000, 15000, 11, 81530, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "Stonecore Earthshaper - In Combat (Phase 1) - Cast 'Ground Shock'"), +(43537, 0, 6, 7, 8, 1, 100, 1, 81459, 0, 0, 0, 22, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "Stonecore Earthshaper - Hit by 'Force of Earth' (Phase 1) - Set Phase 2"), +(43537, 0, 7, 0, 61, 1, 100, 1, 81459, 0, 0, 0, 3, 26693, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "Stonecore Earthshaper - Linked - Morph"), +(43537, 0, 8, 0, 0, 2, 100, 0, 5000, 5000, 15000, 15000, 11, 81463, 64, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "Stonecore Earthshaper - In Combat (Phase 2) - Cast 'Dust Storm'"), +(43537, 0, 9, 0, 6, 0, 100, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "Stonecore Earthshaper - On Death - Demorph"); +-- TODO: Demorph 3 seconds after death. Need more sniffs for Force of Earth's dummy. + +DELETE FROM `creature_text` WHERE `entry` = 43537 AND `groupid` = 0; +INSERT INTO `creature_text` (`entry`, `groupid`, `id`, `text`, `type`, `language`, `probability`, `emote`, `duration`, `sound`, `BroadcastTextID`, `comment`) VALUES +(43537, 0, 0, '%s begins to transform into a Force of Earth!', 16, 0, 100, 0, 0, 0, 46680, 'Stonecore Earthshaper'); + +-- Stonecore Warbringer SAI +UPDATE `creature_template` SET `AIName` = "SmartAI" WHERE `entry` = 42696; +DELETE FROM `smart_scripts` WHERE `entryorguid` = 42696 AND `source_type` = 0; +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(42696, 0, 0, 0, 0, 0, 100, 0, 4000, 4000, 12000, 12000, 11, 80158, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, "Stonecore Warbringer - In Combat - Cast 'Rage'"), +(42696, 0, 1, 0, 0, 0, 100, 0, 8000, 8000, 8000, 12000, 11, 15496, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, "Stonecore Warbringer - In Combat - Cast 'Cleave'"); + +-- Stonecore Berserker SAI +UPDATE `creature_template` SET `AIName` = "SmartAI" WHERE `entry` = 43430; +DELETE FROM `smart_scripts` WHERE `entryorguid` = 43430 AND `source_type` = 0; +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(43430, 0, 0, 0, 0, 0, 100, 0, 0, 0, 10000, 10000, 11, 81574, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, "Stonecore Warbringer - In Combat - Cast 'Charge'"), +(43430, 0, 1, 0, 0, 0, 100, 0, 10000, 15000, 10000, 20000, 11, 81568, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "Stonecore Warbringer - In Combat - Cast 'Spinning Slash'"); + +-- Heroic template of Corborus, Flags on creation (from sniffs) +UPDATE `creature_template` SET `difficulty_entry_1` = 49642, `unit_flags` = 33088 WHERE `entry` = 43438; +DELETE FROM `creature_template` WHERE `entry` = 49642; +INSERT INTO `creature_template` (`entry`, `difficulty_entry_1`, `difficulty_entry_2`, `difficulty_entry_3`, `KillCredit1`, `KillCredit2`, `modelid1`, `modelid2`, `modelid3`, `modelid4`, `name`, `femaleName`, `subname`, `IconName`, `gossip_menu_id`, `minlevel`, `maxlevel`, `exp`, `exp_unk`, `faction`, `npcflag`, `speed_walk`, `speed_run`, `scale`, `rank`, `dmgschool`, `BaseAttackTime`, `RangeAttackTime`, `BaseVariance`, `RangeVariance`, `unit_class`, `unit_flags`, `unit_flags2`, `dynamicflags`, `family`, `trainer_type`, `trainer_class`, `trainer_race`, `type`, `type_flags`, `type_flags2`, `lootid`, `pickpocketloot`, `skinloot`, `resistance1`, `resistance2`, `resistance3`, `resistance4`, `resistance5`, `resistance6`, `spell1`, `spell2`, `spell3`, `spell4`, `spell5`, `spell6`, `spell7`, `spell8`, `PetSpellDataId`, `VehicleId`, `mingold`, `maxgold`, `AIName`, `MovementType`, `InhabitType`, `HoverHeight`, `HealthModifier`, `HealthModifierExtra`, `ManaModifier`, `ManaModifierExtra`, `ArmorModifier`, `DamageModifier`, `ExperienceModifier`, `RacialLeader`, `questItem1`, `questItem2`, `questItem3`, `questItem4`, `questItem5`, `questItem6`, `movementId`, `RegenHealth`, `mechanic_immune_mask`, `flags_extra`, `ScriptName`, `VerifiedBuild`) VALUES +(49642, 0, 0, 0, 0, 0, 33477, 0, 0, 0, 'Corborus (1)', '', '', '', 0, 87, 87, 3, 0, 14, 0, 2.8, 1.14286, 1, 1, 0, 2000, 2000, 1, 1, 1, 33088, 2048, 0, 0, 0, 0, 0, 4, 584, 0, 49642, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '', 0, 3, 1, 35, 1, 1, 1, 1, 1, 1, 0, 52506, 0, 0, 0, 0, 0, 154, 1, 617299839, 1, '', 15595); + +-- Corborus loot +UPDATE `creature_template` SET `lootid` = 43438 WHERE `entry` = 43438; +UPDATE `creature_template` SET `lootid` = 49642 WHERE `entry` = 49642; + +DELETE FROM `creature_loot_template` WHERE `Entry` IN (43438, 49642); +INSERT INTO `creature_loot_template` (`Entry`, `Item`, `Reference`, `Chance`, `QuestRequired`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES +(43438, 1, 43400, 100, 0, 1, 0, 1, 1, NULL), +(49642, 1, 43401, 100, 0, 1, 0, 1, 1, NULL); + +DELETE FROM `reference_loot_template` WHERE `Entry` IN (43400, 43401); +INSERT INTO `reference_loot_template` (`Entry`, `Item`, `Reference`, `Chance`, `QuestRequired`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES +(43400, 55792, 0, 0, 0, 1, 1, 1, 1, NULL), +(43400, 55793, 0, 0, 0, 1, 1, 1, 1, NULL), +(43400, 55794, 0, 0, 0, 1, 1, 1, 1, NULL), +(43400, 55795, 0, 0, 0, 1, 1, 1, 1, NULL), +(43400, 55796, 0, 0, 0, 1, 1, 1, 1, NULL), +(43401, 56328, 0, 0, 0, 1, 1, 1, 1, NULL), +(43401, 56329, 0, 0, 0, 1, 1, 1, 1, NULL), +(43401, 56330, 0, 0, 0, 1, 1, 1, 1, NULL), +(43401, 56331, 0, 0, 0, 1, 1, 1, 1, NULL), +(43401, 56332, 0, 0, 0, 1, 1, 1, 1, NULL); + +-- Set UNIT_FLAG_NOT_SELECTABLE to Trashing Charge. +UPDATE `creature_template` SET `unit_flags` = 33554432 WHERE `entry` = 43743; + +-- Crystalspawn Giant SAI +UPDATE `creature_template` SET `AIName` = "SmartAI" WHERE `entry` = 42810; +DELETE FROM `smart_scripts` WHERE `entryorguid` = 42810 AND `source_type` = 0; +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(42810, 0, 0, 0, 0, 0, 100, 0, 5000, 5000, 12000, 12000, 11, 81008, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "Crystalspawn Giant - In Combat - Cast 'Quake'"); +-- (42810, 0, 1, 0, 0, 0, 100, 0, 10000, 10000, 12000, 12000, 11, ?????, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "Crystalspawn Giant - In Combat - Cast 'Crystal Shard'"); +-- need Stonecore HC sniffs for this spell + +-- Remove one Slabhide spawn, only the flying one is needed +DELETE FROM `creature` WHERE `id` = 43214; +INSERT INTO `creature` (`guid`, `id`, `map`, `zoneId`, `areaId`, `spawnMask`, `phaseMask`, `PhaseId`, `PhaseGroup`, `modelid`, `equipment_id`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `spawndist`, `currentwaypoint`, `curhealth`, `curmana`, `MovementType`, `npcflag`, `unit_flags`, `dynamicflags`, `VerifiedBuild`) VALUES +(340550, 43214, 725, 0, 0, 3, 1, 0, 0, 0, 0, 1191.1, 1154.01, 270.759, 4.69494, 7200, 0, 0, 1, 0, 0, 0, 0, 0, 0); + +-- Heroic template of Slabhide, InhabitType correction +UPDATE `creature_template` SET `difficulty_entry_1` = 49538, `InhabitType` = 7 WHERE `entry` = 43214; +DELETE FROM `creature_template` WHERE `entry` = 49538; +INSERT INTO `creature_template` (`entry`, `difficulty_entry_1`, `difficulty_entry_2`, `difficulty_entry_3`, `KillCredit1`, `KillCredit2`, `modelid1`, `modelid2`, `modelid3`, `modelid4`, `name`, `femaleName`, `subname`, `IconName`, `gossip_menu_id`, `minlevel`, `maxlevel`, `exp`, `exp_unk`, `faction`, `npcflag`, `speed_walk`, `speed_run`, `scale`, `rank`, `dmgschool`, `BaseAttackTime`, `RangeAttackTime`, `BaseVariance`, `RangeVariance`, `unit_class`, `unit_flags`, `unit_flags2`, `dynamicflags`, `family`, `trainer_type`, `trainer_class`, `trainer_race`, `type`, `type_flags`, `type_flags2`, `lootid`, `pickpocketloot`, `skinloot`, `resistance1`, `resistance2`, `resistance3`, `resistance4`, `resistance5`, `resistance6`, `spell1`, `spell2`, `spell3`, `spell4`, `spell5`, `spell6`, `spell7`, `spell8`, `PetSpellDataId`, `VehicleId`, `mingold`, `maxgold`, `AIName`, `MovementType`, `InhabitType`, `HoverHeight`, `HealthModifier`, `HealthModifierExtra`, `ManaModifier`, `ManaModifierExtra`, `ArmorModifier`, `DamageModifier`, `ExperienceModifier`, `RacialLeader`, `questItem1`, `questItem2`, `questItem3`, `questItem4`, `questItem5`, `questItem6`, `movementId`, `RegenHealth`, `mechanic_immune_mask`, `flags_extra`, `ScriptName`, `VerifiedBuild`) VALUES +(49538, 0, 0, 0, 0, 0, 36476, 0, 0, 0, 'Slabhide (1)', '', '', '', 0, 87, 87, 3, 0, 16, 0, 2.8, 1.42857, 1, 1, 0, 2000, 2000, 1, 1, 1, 33587264, 2048, 0, 0, 0, 0, 0, 2, 72, 0, 49538, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '', 0, 7, 1.25, 50, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 154, 1, 0, 1, '', 15595); + +-- Slabhide loot +UPDATE `creature_template` SET `lootid` = 43214 WHERE `entry` = 43214; +UPDATE `creature_template` SET `lootid` = 49538 WHERE `entry` = 49538; + +DELETE FROM `creature_loot_template` WHERE `Entry` IN (43214, 49538); +INSERT INTO `creature_loot_template` (`Entry`, `Item`, `Reference`, `Chance`, `QuestRequired`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES +(43214, 1, 43402, 100, 0, 1, 0, 1, 1, 'Slabhide N - Reference Loot'), +(49538, 1, 43403, 100, 0, 1, 0, 1, 1, 'Slabhide H - Reference Loot'), +(43214, 63043, 0, 1, 0, 1, 0, 1, 1, 'Slabhide N - Mount Drop'), +(49538, 63043, 0, 1, 0, 1, 0, 1, 1, 'Slabhide H - Mount Drop'); + +DELETE FROM `reference_loot_template` WHERE `Entry` IN (43402, 43403); +INSERT INTO `reference_loot_template` (`Entry`, `Item`, `Reference`, `Chance`, `QuestRequired`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES +(43402, 55797, 0, 0, 0, 1, 1, 1, 1, NULL), +(43402, 55798, 0, 0, 0, 1, 1, 1, 1, NULL), +(43402, 55799, 0, 0, 0, 1, 1, 1, 1, NULL), +(43402, 55800, 0, 0, 0, 1, 1, 1, 1, NULL), +(43402, 55801, 0, 0, 0, 1, 1, 1, 1, NULL), +(43403, 56333, 0, 0, 0, 1, 1, 1, 1, NULL), +(43403, 56334, 0, 0, 0, 1, 1, 1, 1, NULL), +(43403, 56335, 0, 0, 0, 1, 1, 1, 1, NULL), +(43403, 56336, 0, 0, 0, 1, 1, 1, 1, NULL), +(43403, 56337, 0, 0, 0, 1, 1, 1, 1, NULL); + +-- Set UNIT_FLAG_NOT_SELECTABLE to Stalactite Trigger - Boss, Lava Fissure, . +UPDATE `creature_template` SET `unit_flags` = 33554432 WHERE `entry` IN (43159, 43242); + +-- "Stalactite Trigger - Boss": InhabitType correction +UPDATE `creature_template` SET `InhabitType` = 7 WHERE `entry` = 43159; + +-- Stonecore Magmalord SAI +UPDATE `creature_template` SET `AIName` = "SmartAI" WHERE `entry` = 42789; +DELETE FROM `smart_scripts` WHERE `entryorguid` = 42789 AND `source_type` = 0; +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(42789, 0, 0, 0, 0, 0, 100, 0, 4000, 8000, 10000, 20000, 11, 80151, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, "Stonecore Magmalord - In Combat - Cast '80151'"), +(42789, 0, 1, 0, 0, 0, 100, 0, 8000, 10000, 10000, 20000, 11, 80038, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "Stonecore Magmalord - In Combat - Cast 'Eruption'"); + +-- Stonecore Rift Conjurer SAI +UPDATE `creature_template` SET `AIName` = "SmartAI" WHERE `entry` = 42691; +DELETE FROM `smart_scripts` WHERE `entryorguid` = 42691 AND `source_type` = 0; +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(42691, 0, 0, 0, 0, 0, 100, 0, 0, 0, 2000, 2000, 11, 80279, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, "Stonecore Rift Conjurer - In Combat - Cast 'Shadow Bolt'"), +(42691, 0, 1, 0, 0, 0, 100, 0, 10000, 20000, 20000, 30000, 11, 80308, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "Stonecore Rift Conjurer - In Combat - Cast 'Demon Portal'"); + +-- Imp SAI +UPDATE `creature_template` SET `AIName` = "SmartAI" WHERE `entry` = 43014; +DELETE FROM `smart_scripts` WHERE `entryorguid` = 43014 AND `source_type` = 0; +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(43014, 0, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 11, 80344, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, "Imp - In Combat - Cast 'Fel Firebolt'"); + +-- Stonecore Bruiser SAI +UPDATE `creature_template` SET `AIName` = "SmartAI" WHERE `entry` = 42692; +DELETE FROM `smart_scripts` WHERE `entryorguid` = 42692 AND `source_type` = 0 OR `entryorguid` = 4269200 AND `source_type` = 9; +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(42692, 0, 0, 0, 0, 0, 100, 0, 8000, 10000, 13000, 15000, 80, 4269200, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "Stonecore Bruiser - In Combat - Start Actionlist"), +(4269200, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 11, 80180, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, "Stonecore Bruiser - Actionlist- Cast 'Body Slam'"), +(4269200, 9, 1, 0, 0, 0, 100, 0, 2400, 2400, 0, 0, 11, 80180, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, "Stonecore Bruiser - Actionlist - Cast 'Body Slam' again"), +(4269200, 9, 2, 0, 0, 0, 100, 0, 2400, 2400, 0, 0, 11, 80180, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, "Stonecore Bruiser - Actionlist - Cast 'Body Slam' again"), +(42692, 0, 1, 0, 0, 0, 100, 0, 14000, 18000, 14000, 18000, 11, 80195, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, "Stonecore Bruiser - In Combat - Cast 'Shockwave'"); + +-- Heroic template of Ozruk +UPDATE `creature_template` SET `difficulty_entry_1` = 49654 WHERE `entry` = 42188; +DELETE FROM `creature_template` WHERE `entry` = 49654; +INSERT INTO `creature_template` (`entry`, `difficulty_entry_1`, `difficulty_entry_2`, `difficulty_entry_3`, `KillCredit1`, `KillCredit2`, `modelid1`, `modelid2`, `modelid3`, `modelid4`, `name`, `femaleName`, `subname`, `IconName`, `gossip_menu_id`, `minlevel`, `maxlevel`, `exp`, `exp_unk`, `faction`, `npcflag`, `speed_walk`, `speed_run`, `scale`, `rank`, `dmgschool`, `BaseAttackTime`, `RangeAttackTime`, `BaseVariance`, `RangeVariance`, `unit_class`, `unit_flags`, `unit_flags2`, `dynamicflags`, `family`, `trainer_type`, `trainer_class`, `trainer_race`, `type`, `type_flags`, `type_flags2`, `lootid`, `pickpocketloot`, `skinloot`, `resistance1`, `resistance2`, `resistance3`, `resistance4`, `resistance5`, `resistance6`, `spell1`, `spell2`, `spell3`, `spell4`, `spell5`, `spell6`, `spell7`, `spell8`, `PetSpellDataId`, `VehicleId`, `mingold`, `maxgold`, `AIName`, `MovementType`, `InhabitType`, `HoverHeight`, `HealthModifier`, `HealthModifierExtra`, `ManaModifier`, `ManaModifierExtra`, `ArmorModifier`, `DamageModifier`, `ExperienceModifier`, `RacialLeader`, `questItem1`, `questItem2`, `questItem3`, `questItem4`, `questItem5`, `questItem6`, `movementId`, `RegenHealth`, `mechanic_immune_mask`, `flags_extra`, `ScriptName`, `VerifiedBuild`) VALUES +(49654, 0, 0, 0, 0, 0, 36475, 0, 0, 0, 'Ozruk (1)', '', '', '', 0, 87, 87, 3, 0, 14, 0, 1, 1.5873, 1, 1, 0, 2000, 2000, 1, 1, 1, 32832, 134219776, 0, 0, 0, 0, 0, 5, 584, 0, 49654, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 867, 0, 0, '', 0, 3, 1, 40, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 617299839, 1, '', 15595); + +-- Ozruk texts +DELETE FROM `creature_text` WHERE `entry` = 42188; +INSERT INTO `creature_text` (`entry`, `groupid`, `id`, `text`, `type`, `language`, `probability`, `emote`, `duration`, `sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES +(42188, 0, 0, 'None may pass into the World''s Heart!', 14, 0, 100, 0, 0, 21919, 0, 0, 'Ozruk to Player'), +(42188, 1, 0, '|TInterface\\Icons\\ability_warrior_shieldreflection.blp:20|tOzruk casts |cFFFF0000|Hspell:78939|h[Elementium Bulwark]|h|r!', 41, 0, 100, 0, 0, 0, 0, 0, 'Ozruk'), +(42188, 2, 0, 'Break yourselves upon my body. Feel the strength of the earth!', 14, 0, 100, 0, 0, 21921, 0, 0, 'Ozruk'), +(42188, 3, 0, '%s becomes enraged!', 41, 0, 100, 0, 0, 0, 0, 0, 'Ozruk'), +(42188, 4, 0, 'A protector has fallen. The World''s Heart lies exposed!', 14, 0, 100, 0, 0, 21922, 0, 0, 'Ozruk to Player'); + +-- Ozruk loot +UPDATE `creature_template` SET `lootid` = 42188 WHERE `entry` = 42188; +UPDATE `creature_template` SET `lootid` = 49654 WHERE `entry` = 49654; + +DELETE FROM `creature_loot_template` WHERE `Entry` IN (42188, 49654); +INSERT INTO `creature_loot_template` (`Entry`, `Item`, `Reference`, `Chance`, `QuestRequired`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES +(42188, 1, 43404, 100, 0, 1, 0, 1, 1, 'Ozruk N - Reference Loot'), +(49654, 1, 43405, 100, 0, 1, 0, 1, 1, 'Ozruk H - Reference Loot'); + +DELETE FROM `reference_loot_template` WHERE `Entry` IN (43404, 43405); +INSERT INTO `reference_loot_template` (`Entry`, `Item`, `Reference`, `Chance`, `QuestRequired`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES +(43404, 55802, 0, 0, 0, 1, 1, 1, 1, NULL), +(43404, 55803, 0, 0, 0, 1, 1, 1, 1, NULL), +(43404, 55804, 0, 0, 0, 1, 1, 1, 1, NULL), +(43404, 55810, 0, 0, 0, 1, 1, 1, 1, NULL), +(43404, 55811, 0, 0, 0, 1, 1, 1, 1, NULL), +(43405, 56338, 0, 0, 0, 1, 1, 1, 1, NULL), +(43405, 56339, 0, 0, 0, 1, 1, 1, 1, NULL), +(43405, 56340, 0, 0, 0, 1, 1, 1, 1, NULL), +(43405, 56341, 0, 0, 0, 1, 1, 1, 1, NULL), +(43405, 56342, 0, 0, 0, 1, 1, 1, 1, NULL); + +-- Set UNIT_FLAG_NOT_SELECTABLE to Rupture Controller and Rupture. +UPDATE `creature_template` SET `unit_flags` = 33554432 WHERE `entry` IN (49597, 49576); + +-- Heroic template of High Priestess Azil +UPDATE `creature_template` SET `difficulty_entry_1` = 49624 WHERE `entry` = 42333; +DELETE FROM `creature_template` WHERE `entry` = 49624; +INSERT INTO `creature_template` (`entry`, `difficulty_entry_1`, `difficulty_entry_2`, `difficulty_entry_3`, `KillCredit1`, `KillCredit2`, `modelid1`, `modelid2`, `modelid3`, `modelid4`, `name`, `femaleName`, `subname`, `IconName`, `gossip_menu_id`, `minlevel`, `maxlevel`, `exp`, `exp_unk`, `faction`, `npcflag`, `speed_walk`, `speed_run`, `scale`, `rank`, `dmgschool`, `BaseAttackTime`, `RangeAttackTime`, `BaseVariance`, `RangeVariance`, `unit_class`, `unit_flags`, `unit_flags2`, `dynamicflags`, `family`, `trainer_type`, `trainer_class`, `trainer_race`, `type`, `type_flags`, `type_flags2`, `lootid`, `pickpocketloot`, `skinloot`, `resistance1`, `resistance2`, `resistance3`, `resistance4`, `resistance5`, `resistance6`, `spell1`, `spell2`, `spell3`, `spell4`, `spell5`, `spell6`, `spell7`, `spell8`, `PetSpellDataId`, `VehicleId`, `mingold`, `maxgold`, `AIName`, `MovementType`, `InhabitType`, `HoverHeight`, `HealthModifier`, `HealthModifierExtra`, `ManaModifier`, `ManaModifierExtra`, `ArmorModifier`, `DamageModifier`, `ExperienceModifier`, `RacialLeader`, `questItem1`, `questItem2`, `questItem3`, `questItem4`, `questItem5`, `questItem6`, `movementId`, `RegenHealth`, `mechanic_immune_mask`, `flags_extra`, `ScriptName`, `VerifiedBuild`) VALUES +(49624, 0, 0, 0, 0, 0, 26448, 0, 0, 0, 'High Priestess Azil (1)', '', '', '', 0, 84, 84, 3, 0, 14, 2, 1.2, 1.42857, 1, 1, 0, 2000, 2000, 1, 1, 1, 32832, 2048, 0, 0, 0, 0, 0, 7, 72, 0, 49624, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 903, 0, 0, '', 0, 3, 1, 30, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 721, 1, 617299839, 1, '', 15595); + +-- "Stalactite Trigger - Boss": InhabitType correction +UPDATE `creature_template` SET `InhabitType` = 7 WHERE `entry` IN (42333, 49624); + +-- High Priestess Azil texts +DELETE FROM `creature_text` WHERE `entry` = 42333; +INSERT INTO `creature_text` (`entry`, `groupid`, `id`, `text`, `type`, `language`, `probability`, `emote`, `duration`, `sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES +(42333, 0, 0, 'The world will be reborn in flames!', 14, 0, 100, 0, 0, 21634, 0, 0, 'High Priestess Azil to Player'), +(42333, 1, 0, 'Witness the power bestowed upon me by Deathwing! Feel the fury of earth!', 14, 0, 100, 0, 0, 21628, 0, 0, 'High Priestess Azil to High Priestess Azil'), +(42333, 2, 0, 'For my death, countless more will fall. The burden is now yours to bear.', 14, 0, 100, 0, 0, 21633, 0, 0, 'High Priestess Azil to Player'); + +-- High Priestess Azil loot +UPDATE `creature_template` SET `lootid` = 42333 WHERE `entry` = 42333; +UPDATE `creature_template` SET `lootid` = 49624 WHERE `entry` = 49624; + +DELETE FROM `creature_loot_template` WHERE `Entry` IN (42333, 49624); +INSERT INTO `creature_loot_template` (`Entry`, `Item`, `Reference`, `Chance`, `QuestRequired`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES +(42333, 1, 43406, 100, 0, 1, 0, 1, 1, 'High Priestess Azil N - Reference Loot'), +(49624, 1, 43407, 100, 0, 1, 0, 1, 1, 'High Priestess Azil H - Reference Loot'), +(49624, 52078, 0, 100, 0, 1, 0, 1, 1, 'High Priestess Azil H - Chaos Orb'); + +DELETE FROM `reference_loot_template` WHERE `Entry` IN (43406, 43407); +INSERT INTO `reference_loot_template` (`Entry`, `Item`, `Reference`, `Chance`, `QuestRequired`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES +(43406, 55812, 0, 0, 0, 1, 1, 1, 1, NULL), +(43406, 55813, 0, 0, 0, 1, 1, 1, 1, NULL), +(43406, 55814, 0, 0, 0, 1, 1, 1, 1, NULL), +(43406, 55815, 0, 0, 0, 1, 1, 1, 1, NULL), +(43406, 55816, 0, 0, 0, 1, 1, 1, 1, NULL), +(43406, 55817, 0, 0, 0, 1, 1, 1, 1, NULL), +(43406, 55818, 0, 0, 0, 1, 1, 1, 1, NULL), +(43406, 55819, 0, 0, 0, 1, 1, 1, 1, NULL), +(43406, 55820, 0, 0, 0, 1, 1, 1, 1, NULL), +(43406, 55821, 0, 0, 0, 1, 1, 1, 1, NULL), +(43407, 56343, 0, 0, 0, 1, 1, 1, 1, NULL), +(43407, 56344, 0, 0, 0, 1, 1, 1, 1, NULL), +(43407, 56345, 0, 0, 0, 1, 1, 1, 1, NULL), +(43407, 56346, 0, 0, 0, 1, 1, 1, 1, NULL), +(43407, 56347, 0, 0, 0, 1, 1, 1, 1, NULL), +(43407, 56348, 0, 0, 0, 1, 1, 1, 1, NULL), +(43407, 56349, 0, 0, 0, 1, 1, 1, 1, NULL), +(43407, 56350, 0, 0, 0, 1, 1, 1, 1, NULL), +(43407, 56351, 0, 0, 0, 1, 1, 1, 1, NULL), +(43407, 56352, 0, 0, 0, 1, 1, 1, 1, NULL); + +DELETE FROM `spell_target_position` WHERE `id` IN (79193, 79199, 86860, 86858, 86856); +INSERT INTO `spell_target_position` (`id`, `effIndex`, `target_map`, `target_position_x`, `target_position_y`, `target_position_z`, `target_orientation`, `VerifiedBuild`) VALUES +(79193, 0, 725, 1260, 960, 205.443756, 0, 0), +(79199, 0, 725, 1280, 1050, 210.383057, 0, 0), +(86860, 0, 725, 1350.75, 919.133, 194.769, 0, 0), +(86858, 0, 725, 1341.19, 913.399, 197.092, 0, 0), +(86856, 0, 725, 1361.89, 920.219, 196.308, 0, 0); + +-- Set UNIT_FLAG_NOT_SELECTABLE to Gravity Well and Seismic Shard. +UPDATE `creature_template` SET `unit_flags` = 33554432 WHERE `entry` IN (42499, 42355); diff --git a/sql/updates/world/2014_11_08_01_world.sql b/sql/updates/world/2014_11_08_01_world.sql new file mode 100644 index 00000000000..e6969ee08ab --- /dev/null +++ b/sql/updates/world/2014_11_08_01_world.sql @@ -0,0 +1,58 @@ +DELETE FROM `disables` WHERE `entry` IN (10042, 10340, 10341, 10342, 10347, 10348, 10349, 10350, 10351, 10352, 10353, 10354, 10355, 10357, 10361, 10362, 10363, 10364, 10403, 10404, 10439, 10582, 10583, 10598, 10599, 10719) AND `sourceType` = 4; + +DELETE FROM `achievement_criteria_data` WHERE `criteria_id` IN (10042, 10340, 10341, 10342, 10347, 10348, 10349, 10350, 10351, 10352, 10353, 10354, 10355, 10357, 10361, 10362, 10363, 10364, 10403, 10404, 10439, 10582, 10583, 10598, 10599, 10719); +INSERT INTO `achievement_criteria_data` (`criteria_id`, `type`, `value1`) VALUES +-- 10 +(10042, 18, 0), +(10042, 12, 0), +(10342, 18, 0), +(10342, 12, 0), +(10340, 18, 0), +(10340, 12, 0), +(10341, 18, 0), +(10341, 12, 0), +(10598, 18, 0), +(10598, 12, 0), +(10348, 18, 0), +(10348, 12, 0), +(10351, 18, 0), +(10351, 12, 0), +(10439, 18, 0), +(10439, 12, 0), +(10403, 18, 0), +(10403, 12, 0), +(10582, 18, 0), +(10582, 12, 0), +(10347, 18, 0), +(10347, 12, 0), +(10349, 18, 0), +(10349, 12, 0), +(10350, 18, 0), +(10350, 12, 0), +-- 25 +(10352, 18, 0), +(10352, 12, 1), +(10355, 18, 0), +(10355, 12, 1), +(10353, 18, 0), +(10353, 12, 1), +(10354, 18, 0), +(10354, 12, 1), +(10599, 18, 0), +(10599, 12, 1), +(10357, 18, 0), +(10357, 12, 1), +(10363, 18, 0), +(10363, 12, 1), +(10719, 18, 0), +(10719, 12, 1), +(10404, 18, 0), +(10404, 12, 1), +(10583, 18, 0), +(10583, 12, 1), +(10361, 18, 0), +(10361, 12, 1), +(10362, 18, 0), +(10362, 12, 1), +(10364, 18, 0), +(10364, 12, 1); diff --git a/sql/updates/world/2014_11_08_02_world.sql b/sql/updates/world/2014_11_08_02_world.sql new file mode 100644 index 00000000000..08f64d64bd3 --- /dev/null +++ b/sql/updates/world/2014_11_08_02_world.sql @@ -0,0 +1,56 @@ +UPDATE `creature_template` SET `InhabitType`=4 WHERE `entry` IN(37098,38418,38258); +UPDATE `creature_template` SET `InhabitType`=5 WHERE `entry`=38058; + +-- Skybreaker Protector SAI +SET @ENTRY := 36998; +UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=@ENTRY; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=0; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@ENTRY,0,0,0,0,0,100,0,4000,4000,8000,10000,11,69965,0,0,0,0,0,1,0,0,0,0,0,0,0,"Skybreaker Protector - In Combat - Cast 'Thunderclap'"), +(@ENTRY,0,1,0,0,0,100,0,7000,7000,21000,23000,11,69902,0,0,0,0,0,2,0,0,0,0,0,0,0,"Skybreaker Protector - In Combat - Cast 'Devastate'"), +(@ENTRY,0,2,0,0,0,100,0,16000,16000,30000,30000,11,69903,0,0,0,0,0,2,0,0,0,0,0,0,0,"Skybreaker Protector - In Combat - Cast 'Shield Slam'"), +(@ENTRY,0,3,0,0,0,100,0,5000,5000,17000,26000,11,69901,0,0,0,0,0,2,0,0,0,0,0,0,0,"Skybreaker Protector - In Combat - Cast 'Spell Reflect'"), +(@ENTRY,0,4,0,0,0,100,0,7000,7000,44000,45000,11,57807,0,0,0,0,0,2,0,0,0,0,0,0,0,"Skybreaker Protector - In Combat - Cast 'Sunder Armor'"); + +-- Kor'kron Defender SAI +SET @ENTRY := 37032; +UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=@ENTRY; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=0; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@ENTRY,0,0,0,0,0,100,0,4000,4000,8000,10000,11,69965,0,0,0,0,0,1,0,0,0,0,0,0,0,"Kor'kron Defender - In Combat - Cast 'Thunderclap'"), +(@ENTRY,0,1,0,0,0,100,0,7000,7000,21000,23000,11,69902,0,0,0,0,0,2,0,0,0,0,0,0,0,"Kor'kron Defender - In Combat - Cast 'Devastate'"), +(@ENTRY,0,2,0,0,0,100,0,16000,16000,30000,30000,11,69903,0,0,0,0,0,2,0,0,0,0,0,0,0,"Kor'kron Defender - In Combat - Cast 'Shield Slam'"), +(@ENTRY,0,3,0,0,0,100,0,5000,5000,17000,26000,11,69901,0,0,0,0,0,2,0,0,0,0,0,0,0,"Kor'kron Defender - In Combat - Cast 'Spell Reflect'"), +(@ENTRY,0,4,0,0,0,100,0,7000,7000,44000,45000,11,57807,0,0,0,0,0,2,0,0,0,0,0,0,0,"Kor'kron Defender - In Combat - Cast 'Sunder Armor'"); + +-- Blighted Abomination SAI +SET @ENTRY := 37022; +UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=@ENTRY; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=0; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@ENTRY,0,0,0,0,0,100,0,4000,4000,6000,6000,11,71140,0,0,0,0,0,2,0,0,0,0,0,0,0,"Blighted Abomination - In Combat - Cast 'Scourge Hook'"), +(@ENTRY,0,1,0,0,0,100,0,10000,11000,10000,11000,11,71150,0,0,0,0,0,1,0,0,0,0,0,0,0,"Blighted Abomination - In Combat - Cast 'Plague Cloud'"), +(@ENTRY,0,2,0,0,0,100,0,14000,15000,14000,15000,11,40504,0,0,0,0,0,2,0,0,0,0,0,0,0,"Blighted Abomination - In Combat - Cast 'Cleave'"); + +-- Decaying Colossus SAI +SET @ENTRY := 36880; +UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=@ENTRY; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=0; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@ENTRY,0,0,0,0,0,100,0,15000,17000,15000,17000,11,71114,0,0,0,0,0,1,0,0,0,0,0,0,0,"Decaying Colossus - In Combat - Cast 'Massive Stomp'"); + +-- Darkfallen Lieutenant SAI +SET @ENTRY := 37665; +UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=@ENTRY; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=0; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@ENTRY,0,0,0,0,0,100,0,9000,9000,8000,9000,11,70435,0,0,0,0,0,2,0,0,0,0,0,0,0,"Darkfallen Lieutenant - In Combat - Cast 'Rend Flesh'"), +(@ENTRY,0,1,0,0,0,100,0,5000,5000,20000,20000,11,70423,0,0,0,0,0,2,0,0,0,0,0,0,0,"Darkfallen Lieutenant - In Combat - Cast 'Vampiric Curse'"); + +-- Darkfallen Commander SAI +SET @ENTRY := 37662; +UPDATE `creature_template` SET `AIName`="SmartAI" WHERE `entry`=@ENTRY; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=0; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@ENTRY,0,0,0,0,0,100,0,5000,5000,15000,16000,11,70449,0,0,0,0,0,18,45,0,0,0,0,0,0,"Darkfallen Commander - In Combat - Cast 'Vampire Rush'"), +(@ENTRY,0,1,0,0,0,100,0,5000,5000,25000,25000,11,70750,0,0,0,0,0,1,0,0,0,0,0,0,0,"Darkfallen Commander - In Combat - Cast 'Battle Shout'"); diff --git a/sql/updates/world/2014_11_10_00_world.sql b/sql/updates/world/2014_11_10_00_world.sql new file mode 100644 index 00000000000..f085114a035 --- /dev/null +++ b/sql/updates/world/2014_11_10_00_world.sql @@ -0,0 +1,21 @@ +DELETE FROM `command` WHERE `name` LIKE '%battlenetaccount%'; +DELETE FROM `command` WHERE `name` LIKE '%bnetaccount%'; +INSERT INTO `command` (`name`, `permission`, `help`) VALUES +('bnetaccount', 207, 'Syntax: .bnetaccount $subcommand\nType .bnetaccount to see the list of possible subcommands or .help account set $subcommand to see info on subcommands.'), +('bnetaccount create', 208, 'Syntax: .bnetaccount create $account $password\nCreate battle.net account and set password to it. Account must contain the @ symbol.'), +('bnetaccount lock country', 209, 'Syntax: .bnetaccount lock country [on|off]\nAllow login to account only from current used Country or remove this requirement.'), +('bnetaccount lock ip', 210, 'Syntax: .bnetaccount lock ip [on|off]\nAllow login to account only from current used IP or remove this requirement.'), +('bnetaccount password', 211, 'Syntax: .bnetaccount password $old_password $new_password $new_password\nChange your account password.'), +('bnetaccount set', 212, 'Syntax: .bnetaccount set $subcommand\nType .bnetaccount set to see the list of possible subcommands or .help bnetaccount set $subcommand to see info on subcommands.'), +('bnetaccount set password', 213, 'Syntax: .bnetaccount set password $account $password $password\nSet password for account.'), +('bnetaccount link', 214, 'Syntax: .bnetaccount link $email $login\nLinks battle.net account ($email) to an existing game account ($login).'), +('bnetaccount unlink', 215, 'Syntax: .bnetaccount unlink $gameaccount $password\nRemoves battle.net account link from $gameaccount'), +('bnetaccount gameaccountcreate', 216, 'Syntax: .bnetaccount gameaccountcreate $account\nCreate additional game account for specified battle.net account.'); + +DELETE FROM `trinity_string` WHERE `entry` BETWEEN 1185 AND 1189; +INSERT INTO `trinity_string` (`entry`, `content_default`) VALUES +(1185, 'Battle.net account %s was linked with game account %s.'), +(1186, 'Battle.net account %s or game account %s does not exist.'), +(1187, 'Game account %s is already linked with a battle.net account.'), +(1188, 'Game account %s had its battle.net account link removed.'), +(1189, 'Game account %s is not linked to any battle.net account.'); diff --git a/sql/updates/world/2014_11_10_01_world.sql b/sql/updates/world/2014_11_10_01_world.sql new file mode 100644 index 00000000000..e0d9be1f568 --- /dev/null +++ b/sql/updates/world/2014_11_10_01_world.sql @@ -0,0 +1,2 @@ +UPDATE `creature_template` SET `faction`=35 WHERE `faction`=0; +UPDATE `creature_template` SET `unit_class`=1 WHERE `unit_class`=0; diff --git a/src/server/authserver/Server/AuthSession.cpp b/src/server/authserver/Server/AuthSession.cpp index 0ba832af483..248010ef112 100644 --- a/src/server/authserver/Server/AuthSession.cpp +++ b/src/server/authserver/Server/AuthSession.cpp @@ -433,7 +433,7 @@ bool AuthSession::HandleLogonProof() A.SetBinary(logonProof->A, 32); // SRP safeguard: abort if A == 0 - if (A.isZero()) + if (A.IsZero()) { return false; } diff --git a/src/server/bnetserver/CMakeLists.txt b/src/server/bnetserver/CMakeLists.txt index 5b854018d47..5d1edef5b81 100644 --- a/src/server/bnetserver/CMakeLists.txt +++ b/src/server/bnetserver/CMakeLists.txt @@ -55,6 +55,7 @@ include_directories( ${CMAKE_SOURCE_DIR}/src/server/shared/Cryptography/Authentication ${CMAKE_SOURCE_DIR}/src/server/shared/Logging ${CMAKE_SOURCE_DIR}/src/server/shared/Networking + ${CMAKE_SOURCE_DIR}/src/server/shared/Realm ${CMAKE_SOURCE_DIR}/src/server/shared/Threading ${CMAKE_SOURCE_DIR}/src/server/shared/Utilities ${CMAKE_SOURCE_DIR}/src/server/ipc diff --git a/src/server/bnetserver/Packets/PacketManager.cpp b/src/server/bnetserver/Packets/PacketManager.cpp index cbfd0c8b2b6..faf38e8a5bc 100644 --- a/src/server/bnetserver/Packets/PacketManager.cpp +++ b/src/server/bnetserver/Packets/PacketManager.cpp @@ -79,7 +79,7 @@ Battlenet::PacketManager::PacketManager() void Battlenet::PacketManager::RegisterAuthenticationPackets() { - REGISTER_CLIENT_PACKET_NAME(PacketHeader(Authentication::CMSG_LOGON_REQUEST, AUTHENTICATION), "Authentication::LogonRequest3"); + REGISTER_CLIENT_PACKET_NAME(PacketHeader(Authentication::CMSG_LOGON_REQUEST, AUTHENTICATION), "Authentication::LogonRequest"); REGISTER_CLIENT_PACKET(PacketHeader(Authentication::CMSG_RESUME_REQUEST, AUTHENTICATION), Authentication::ResumeRequest); REGISTER_CLIENT_PACKET(PacketHeader(Authentication::CMSG_PROOF_RESPONSE, AUTHENTICATION), Authentication::ProofResponse); REGISTER_CLIENT_PACKET(PacketHeader(Authentication::CMSG_LOGON_REQUEST_3, AUTHENTICATION), Authentication::LogonRequest3); diff --git a/src/server/bnetserver/Realms/RealmList.cpp b/src/server/bnetserver/Realms/RealmList.cpp index cc7e1d492a8..a876aa93a07 100644 --- a/src/server/bnetserver/Realms/RealmList.cpp +++ b/src/server/bnetserver/Realms/RealmList.cpp @@ -24,49 +24,6 @@ #include "RealmList.h" #include <boost/asio/ip/tcp.hpp> -Battlenet::RealmId& Battlenet::RealmId::operator=(Battlenet::RealmHandle const& handle) -{ - Region = handle.Region; - Battlegroup = handle.Battlegroup; - Index = handle.Index; - return *this; -} - -ip::tcp::endpoint Realm::GetAddressForClient(ip::address const& clientAddr) const -{ - ip::address realmIp; - - // Attempt to send best address for client - if (clientAddr.is_loopback()) - { - // Try guessing if realm is also connected locally - if (LocalAddress.is_loopback() || ExternalAddress.is_loopback()) - realmIp = clientAddr; - else - { - // Assume that user connecting from the machine that bnetserver is located on - // has all realms available in his local network - realmIp = LocalAddress; - } - } - else - { - if (clientAddr.is_v4() && - (clientAddr.to_v4().to_ulong() & LocalSubnetMask.to_v4().to_ulong()) == - (LocalAddress.to_v4().to_ulong() & LocalSubnetMask.to_v4().to_ulong())) - { - realmIp = LocalAddress; - } - else - realmIp = ExternalAddress; - } - - ip::tcp::endpoint endpoint(realmIp, Port); - - // Return external IP - return endpoint; -} - RealmList::RealmList() : _updateInterval(0), _updateTimer(nullptr), _resolver(nullptr), _worldListener(nullptr) { } diff --git a/src/server/bnetserver/Realms/RealmList.h b/src/server/bnetserver/Realms/RealmList.h index dc78a00dfdd..718e26d2564 100644 --- a/src/server/bnetserver/Realms/RealmList.h +++ b/src/server/bnetserver/Realms/RealmList.h @@ -20,6 +20,7 @@ #define _REALMLIST_H #include "Common.h" +#include "Realm.h" #include "WorldListener.h" #include <boost/asio/ip/address.hpp> #include <boost/asio/ip/tcp.hpp> @@ -28,67 +29,6 @@ using namespace boost::asio; -enum RealmFlags -{ - REALM_FLAG_NONE = 0x00, - REALM_FLAG_INVALID = 0x01, - REALM_FLAG_OFFLINE = 0x02, - REALM_FLAG_SPECIFYBUILD = 0x04, - REALM_FLAG_UNK1 = 0x08, - REALM_FLAG_UNK2 = 0x10, - REALM_FLAG_RECOMMENDED = 0x20, - REALM_FLAG_NEW = 0x40, - REALM_FLAG_FULL = 0x80 -}; - -#pragma pack(push, 1) - -namespace Battlenet -{ - struct RealmHandle; - - struct RealmId - { - RealmId() : Region(0), Battlegroup(0), Index(0), Build(0) { } - RealmId(uint8 region, uint8 battlegroup, uint32 index, uint32 build) - : Region(region), Battlegroup(battlegroup), Index(index), Build(build) { } - - uint8 Region; - uint8 Battlegroup; - uint32 Index; - uint32 Build; - - bool operator<(RealmId const& r) const - { - return memcmp(this, &r, sizeof(RealmId) - sizeof(Build)) < 0; - } - - RealmId& operator=(RealmHandle const& handle); - }; -} - -#pragma pack(pop) - -// Storage object for a realm -struct Realm -{ - Battlenet::RealmId Id; - ip::address ExternalAddress; - ip::address LocalAddress; - ip::address LocalSubnetMask; - uint16 Port; - std::string Name; - uint8 Type; - RealmFlags Flags; - uint8 Timezone; - AccountTypes AllowedSecurityLevel; - float PopulationLevel; - bool Updated; - bool Keep; - - ip::tcp::endpoint GetAddressForClient(ip::address const& clientAddr) const; -}; - /// Storage object for the list of realms on the server class RealmList { diff --git a/src/server/bnetserver/Realms/WorldListener.cpp b/src/server/bnetserver/Realms/WorldListener.cpp index 30886a67310..9c9f1029e87 100644 --- a/src/server/bnetserver/Realms/WorldListener.cpp +++ b/src/server/bnetserver/Realms/WorldListener.cpp @@ -98,7 +98,9 @@ void WorldListener::HandleToonOnlineStatusChange(Battlenet::RealmHandle const& r if (online) { Battlenet::WoWRealm::ToonReady* toonReady = new Battlenet::WoWRealm::ToonReady(); - toonReady->Realm = realm; + toonReady->Realm.Battlegroup = realm.Battlegroup; + toonReady->Realm.Index = realm.Index; + toonReady->Realm.Region = realm.Region; toonReady->Guid = toonHandle.Guid; toonReady->Name = toonHandle.Name; session->AsyncWrite(toonReady); diff --git a/src/server/bnetserver/Server/Session.cpp b/src/server/bnetserver/Server/Session.cpp index e6e861a1671..0a5a2de499a 100644 --- a/src/server/bnetserver/Server/Session.cpp +++ b/src/server/bnetserver/Server/Session.cpp @@ -115,6 +115,7 @@ void Battlenet::Session::HandleLogonRequest(Authentication::LogonRequest3 const& Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse(); logonResponse->SetAuthResult(AUTH_INVALID_PROGRAM); AsyncWrite(logonResponse); + TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] %s attempted to log in with game other than WoW (using %s)!", GetClientInfo().c_str(), logonRequest.Program.c_str()); return; } @@ -123,6 +124,7 @@ void Battlenet::Session::HandleLogonRequest(Authentication::LogonRequest3 const& Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse(); logonResponse->SetAuthResult(AUTH_INVALID_OS); AsyncWrite(logonResponse); + TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] %s attempted to log in from an unsupported platform (using %s)!", GetClientInfo().c_str(), logonRequest.Platform.c_str()); return; } @@ -131,6 +133,7 @@ void Battlenet::Session::HandleLogonRequest(Authentication::LogonRequest3 const& Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse(); logonResponse->SetAuthResult(AUTH_UNSUPPORTED_LANGUAGE); AsyncWrite(logonResponse); + TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] %s attempted to log in with unsupported locale (using %s)!", GetClientInfo().c_str(), logonRequest.Locale.c_str()); return; } @@ -140,15 +143,23 @@ void Battlenet::Session::HandleLogonRequest(Authentication::LogonRequest3 const& { Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse(); if (!sComponentMgr->HasProgram(component.Program)) + { logonResponse->SetAuthResult(AUTH_INVALID_PROGRAM); + TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] %s is using unsupported component program %s!", GetClientInfo().c_str(), component.Program.c_str()); + } else if (!sComponentMgr->HasPlatform(component.Platform)) + { logonResponse->SetAuthResult(AUTH_INVALID_OS); + TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] %s is using unsupported component platform %s!", GetClientInfo().c_str(), component.Platform.c_str()); + } else { if (component.Program != "WoW" || AuthHelper::IsBuildSupportingBattlenet(component.Build)) logonResponse->SetAuthResult(AUTH_REGION_BAD_VERSION); else logonResponse->SetAuthResult(AUTH_USE_GRUNT_LOGON); + + TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] %s is using unsupported component version %u!", GetClientInfo().c_str(), component.Build); } AsyncWrite(logonResponse); @@ -173,6 +184,7 @@ void Battlenet::Session::HandleLogonRequest(Authentication::LogonRequest3 const& Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse(); logonResponse->SetAuthResult(AUTH_UNKNOWN_ACCOUNT); AsyncWrite(logonResponse); + TC_LOG_DEBUG("session", "[Battlenet::LogonRequest] %s is trying to log in from unknown account!", GetClientInfo().c_str()); return; } @@ -619,7 +631,7 @@ bool Battlenet::Session::HandlePasswordModule(BitStream* dataStream, ServerPacke clientM1.SetBinary(dataStream->ReadBytes(32).get(), 32); clientChallenge.SetBinary(dataStream->ReadBytes(128).get(), 128); - if (A.isZero()) + if (A.IsZero()) { Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse(); logonResponse->SetAuthResult(AUTH_CORRUPTED_MODULE); @@ -700,6 +712,7 @@ bool Battlenet::Session::HandlePasswordModule(BitStream* dataStream, ServerPacke Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse(); logonResponse->SetAuthResult(AUTH_UNKNOWN_ACCOUNT); ReplaceResponse(response, logonResponse); + TC_LOG_DEBUG("session", "[Battlenet::Password] %s attempted to log in with invalid password!", GetClientInfo().c_str()); return false; } @@ -715,6 +728,7 @@ bool Battlenet::Session::HandlePasswordModule(BitStream* dataStream, ServerPacke Authentication::LogonResponse* logonResponse = new Authentication::LogonResponse(); logonResponse->SetAuthResult(LOGIN_NO_GAME_ACCOUNT); ReplaceResponse(response, logonResponse); + TC_LOG_DEBUG("session", "[Battlenet::Password] %s does not have any linked game accounts!", GetClientInfo().c_str()); return false; } @@ -757,8 +771,9 @@ bool Battlenet::Session::HandlePasswordModule(BitStream* dataStream, ServerPacke fields = result->Fetch(); std::ostringstream name; std::string originalName = fields[1].GetString(); - if (originalName.find('#') != std::string::npos) - name << "WoW" << uint32(fields[0].GetUInt8()); + std::size_t hashPos = originalName.find('#'); + if (hashPos != std::string::npos) + name << "WoW" << originalName.substr(hashPos + 1); else name << originalName; @@ -845,6 +860,7 @@ bool Battlenet::Session::HandleSelectGameAccountModule(BitStream* dataStream, Se Authentication::LogonResponse* complete = new Authentication::LogonResponse(); complete->SetAuthResult(LOGIN_NO_GAME_ACCOUNT); ReplaceResponse(response, complete); + TC_LOG_DEBUG("session", "[Battlenet::SelectGameAccount] %s attempted to log in with invalid game account name %s!", GetClientInfo().c_str(), account.c_str()); return false; } @@ -966,7 +982,7 @@ bool Battlenet::Session::HandleResumeModule(BitStream* dataStream, ServerPacket* stmt->setString(0, _accountName); LoginDatabase.Execute(stmt); - TC_LOG_DEBUG("session", "[Battlenet::Resume] Invalid proof!"); + TC_LOG_DEBUG("session", "[Battlenet::Resume] %s attempted to reconnect with invalid password!", GetClientInfo().c_str()); Authentication::ResumeResponse* resumeResponse = new Authentication::ResumeResponse(); resumeResponse->SetAuthResult(AUTH_UNKNOWN_ACCOUNT); ReplaceResponse(response, resumeResponse); diff --git a/src/server/game/Accounts/AccountMgr.cpp b/src/server/game/Accounts/AccountMgr.cpp index d6985e2a1ad..55f19d1612e 100644 --- a/src/server/game/Accounts/AccountMgr.cpp +++ b/src/server/game/Accounts/AccountMgr.cpp @@ -33,7 +33,7 @@ AccountMgr::~AccountMgr() ClearRBAC(); } -AccountOpResult AccountMgr::CreateAccount(std::string username, std::string password, std::string email /*= ""*/) +AccountOpResult AccountMgr::CreateAccount(std::string username, std::string password, std::string email /*= ""*/, uint32 bnetAccountId /*= 0*/, uint8 bnetIndex /*= 0*/) { if (utf8length(username) > MAX_ACCOUNT_STR) return AccountOpResult::AOR_NAME_TOO_LONG; // username's too long @@ -51,6 +51,16 @@ AccountOpResult AccountMgr::CreateAccount(std::string username, std::string pass stmt->setString(1, CalculateShaPassHash(username, password)); stmt->setString(2, email); stmt->setString(3, email); + if (bnetAccountId && bnetIndex) + { + stmt->setUInt32(4, bnetAccountId); + stmt->setUInt8(5, bnetIndex); + } + else + { + stmt->setNull(4); + stmt->setNull(5); + } LoginDatabase.DirectExecute(stmt); // Enforce saving, otherwise AddGroup can fail @@ -144,7 +154,7 @@ AccountOpResult AccountMgr::ChangeUsername(uint32 accountId, std::string newUser if (utf8length(newUsername) > MAX_ACCOUNT_STR) return AccountOpResult::AOR_NAME_TOO_LONG; - if (utf8length(newPassword) > MAX_ACCOUNT_STR) + if (utf8length(newPassword) > MAX_PASS_STR) return AccountOpResult::AOR_PASS_TOO_LONG; Utf8ToUpperOnlyLatin(newUsername); @@ -171,7 +181,7 @@ AccountOpResult AccountMgr::ChangePassword(uint32 accountId, std::string newPass return AccountOpResult::AOR_NAME_NOT_EXIST; // account doesn't exist } - if (utf8length(newPassword) > MAX_ACCOUNT_STR) + if (utf8length(newPassword) > MAX_PASS_STR) { sScriptMgr->OnFailedPasswordChange(accountId); return AccountOpResult::AOR_PASS_TOO_LONG; diff --git a/src/server/game/Accounts/AccountMgr.h b/src/server/game/Accounts/AccountMgr.h index add00ec7feb..a3956ad8633 100644 --- a/src/server/game/Accounts/AccountMgr.h +++ b/src/server/game/Accounts/AccountMgr.h @@ -29,7 +29,8 @@ enum class AccountOpResult : uint8 AOR_EMAIL_TOO_LONG, AOR_NAME_ALREADY_EXIST, AOR_NAME_NOT_EXIST, - AOR_DB_INTERNAL_ERROR + AOR_DB_INTERNAL_ERROR, + AOR_ACCOUNT_BAD_LINK }; enum PasswordChangeSecurity @@ -62,7 +63,7 @@ class AccountMgr return &instance; } - AccountOpResult CreateAccount(std::string username, std::string password, std::string email = ""); + AccountOpResult CreateAccount(std::string username, std::string password, std::string email = "", uint32 bnetAccountId = 0, uint8 bnetIndex = 0); static AccountOpResult DeleteAccount(uint32 accountId); static AccountOpResult ChangeUsername(uint32 accountId, std::string newUsername, std::string newPassword); static AccountOpResult ChangePassword(uint32 accountId, std::string newPassword); diff --git a/src/server/game/Accounts/BattlenetAccountMgr.cpp b/src/server/game/Accounts/BattlenetAccountMgr.cpp index da71f02d7d2..8144f28c3e5 100644 --- a/src/server/game/Accounts/BattlenetAccountMgr.cpp +++ b/src/server/game/Accounts/BattlenetAccountMgr.cpp @@ -21,6 +21,8 @@ #include "Util.h" #include "SHA256.h" +using GameAccountMgr = AccountMgr; + AccountOpResult Battlenet::AccountMgr::CreateBattlenetAccount(std::string email, std::string password) { if (utf8length(email) > MAX_BNET_EMAIL_STR) @@ -38,8 +40,12 @@ AccountOpResult Battlenet::AccountMgr::CreateBattlenetAccount(std::string email, PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_BNET_ACCOUNT); stmt->setString(0, email); stmt->setString(1, CalculateShaPassHash(email, password)); - LoginDatabase.Execute(stmt); + LoginDatabase.DirectExecute(stmt); + uint32 newAccountId = GetId(email); + ASSERT(newAccountId); + + GameAccountMgr::instance()->CreateAccount(std::to_string(newAccountId) + "#1", password, email, newAccountId, 1); return AccountOpResult::AOR_OK; } @@ -62,20 +68,65 @@ AccountOpResult Battlenet::AccountMgr::ChangePassword(uint32 accountId, std::str return AccountOpResult::AOR_OK; } -uint32 Battlenet::AccountMgr::GetId(std::string const& username) +bool Battlenet::AccountMgr::CheckPassword(uint32 accountId, std::string password) { - PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_ACCOUNT_ID_BY_EMAIL); - stmt->setString(0, username); - if (PreparedQueryResult result = LoginDatabase.Query(stmt)) - return (*result)[0].GetUInt32(); + std::string username; - return 0; + if (!GetName(accountId, username)) + return false; + + Utf8ToUpperOnlyLatin(username); + Utf8ToUpperOnlyLatin(password); + + PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_CHECK_PASSWORD); + stmt->setUInt32(0, accountId); + stmt->setString(1, CalculateShaPassHash(username, password)); + + return LoginDatabase.Query(stmt) != nullptr; } -uint32 Battlenet::AccountMgr::GetIdByGameAccount(uint32 gameAccountId) +AccountOpResult Battlenet::AccountMgr::LinkWithGameAccount(std::string const& email, std::string const& gameAccountName) { - PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_ACCOUNT_ID_BY_GAME_ACCOUNT); - stmt->setUInt32(0, gameAccountId); + uint32 bnetAccountId = GetId(email); + if (!bnetAccountId) + return AccountOpResult::AOR_NAME_NOT_EXIST; + + uint32 gameAccountId = GameAccountMgr::GetId(gameAccountName); + if (!gameAccountId) + return AccountOpResult::AOR_NAME_NOT_EXIST; + + if (GetIdByGameAccount(gameAccountId)) + return AccountOpResult::AOR_ACCOUNT_BAD_LINK; + + PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_BNET_GAME_ACCOUNT_LINK); + stmt->setUInt32(0, bnetAccountId); + stmt->setUInt8(1, GetMaxIndex(bnetAccountId) + 1); + stmt->setUInt32(2, gameAccountId); + LoginDatabase.Execute(stmt); + return AccountOpResult::AOR_OK; +} + +AccountOpResult Battlenet::AccountMgr::UnlinkGameAccount(std::string const& gameAccountName) +{ + uint32 gameAccountId = GameAccountMgr::GetId(gameAccountName); + if (!gameAccountId) + return AccountOpResult::AOR_NAME_NOT_EXIST; + + if (!GetIdByGameAccount(gameAccountId)) + return AccountOpResult::AOR_ACCOUNT_BAD_LINK; + + PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_BNET_GAME_ACCOUNT_LINK); + stmt->setNull(0); + stmt->setNull(1); + stmt->setUInt32(2, gameAccountId); + LoginDatabase.Execute(stmt); + return AccountOpResult::AOR_OK; +} + +uint32 Battlenet::AccountMgr::GetId(std::string const& username) +{ + PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_ACCOUNT_ID_BY_EMAIL); + stmt->setString(0, username); if (PreparedQueryResult result = LoginDatabase.Query(stmt)) return (*result)[0].GetUInt32(); @@ -95,21 +146,25 @@ bool Battlenet::AccountMgr::GetName(uint32 accountId, std::string& name) return false; } -bool Battlenet::AccountMgr::CheckPassword(uint32 accountId, std::string password) +uint32 Battlenet::AccountMgr::GetIdByGameAccount(uint32 gameAccountId) { - std::string username; - - if (!GetName(accountId, username)) - return false; + PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_ACCOUNT_ID_BY_GAME_ACCOUNT); + stmt->setUInt32(0, gameAccountId); + if (PreparedQueryResult result = LoginDatabase.Query(stmt)) + return (*result)[0].GetUInt32(); - Utf8ToUpperOnlyLatin(username); - Utf8ToUpperOnlyLatin(password); + return 0; +} - PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_CHECK_PASSWORD); +uint8 Battlenet::AccountMgr::GetMaxIndex(uint32 accountId) +{ + PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_MAX_ACCOUNT_INDEX); stmt->setUInt32(0, accountId); - stmt->setString(1, CalculateShaPassHash(username, password)); + PreparedQueryResult result = LoginDatabase.Query(stmt); + if (result) + return (*result)[0].GetUInt8(); - return LoginDatabase.Query(stmt) != nullptr; + return 0; } std::string Battlenet::AccountMgr::CalculateShaPassHash(std::string const& name, std::string const& password) diff --git a/src/server/game/Accounts/BattlenetAccountMgr.h b/src/server/game/Accounts/BattlenetAccountMgr.h index 1e0b7b78a99..07e9f684874 100644 --- a/src/server/game/Accounts/BattlenetAccountMgr.h +++ b/src/server/game/Accounts/BattlenetAccountMgr.h @@ -32,10 +32,13 @@ namespace Battlenet AccountOpResult CreateBattlenetAccount(std::string email, std::string password); AccountOpResult ChangePassword(uint32 accountId, std::string newPassword); bool CheckPassword(uint32 accountId, std::string password); + AccountOpResult LinkWithGameAccount(std::string const& email, std::string const& gameAccountName); + AccountOpResult UnlinkGameAccount(std::string const& gameAccountName); uint32 GetId(std::string const& username); bool GetName(uint32 accountId, std::string& name); uint32 GetIdByGameAccount(uint32 gameAccountId); + uint8 GetMaxIndex(uint32 accountId); std::string CalculateShaPassHash(std::string const& name, std::string const& password); } diff --git a/src/server/game/Accounts/RBAC.h b/src/server/game/Accounts/RBAC.h index e0c22f297ea..17c34a9b42a 100644 --- a/src/server/game/Accounts/RBAC.h +++ b/src/server/game/Accounts/RBAC.h @@ -117,9 +117,9 @@ enum RBACPermissions RBAC_PERM_COMMAND_BNET_ACCOUNT_PASSWORD = 211, RBAC_PERM_COMMAND_BNET_ACCOUNT_SET = 212, RBAC_PERM_COMMAND_BNET_ACCOUNT_SET_PASSWORD = 213, - // 214 - reuse - // 215 - reuse - // 216 - reuse + RBAC_PERM_COMMAND_BNET_ACCOUNT_LINK = 214, + RBAC_PERM_COMMAND_BNET_ACCOUNT_UNLINK = 215, + RBAC_PERM_COMMAND_BNET_ACCOUNT_CREATE_GAME = 216, RBAC_PERM_COMMAND_ACCOUNT = 217, RBAC_PERM_COMMAND_ACCOUNT_ADDON = 218, RBAC_PERM_COMMAND_ACCOUNT_CREATE = 219, diff --git a/src/server/game/Battlefield/Battlefield.cpp b/src/server/game/Battlefield/Battlefield.cpp index c06ade69f01..401844b6151 100644 --- a/src/server/game/Battlefield/Battlefield.cpp +++ b/src/server/game/Battlefield/Battlefield.cpp @@ -29,6 +29,7 @@ #include "ObjectAccessor.h" #include "ObjectMgr.h" #include "WorldPacket.h" +#include "WorldStatePackets.h" Battlefield::Battlefield() { @@ -351,7 +352,7 @@ void Battlefield::DoPlaySoundToAll(uint32 SoundID) data << uint32(SoundID); data << uint64(0); - BroadcastPacketToWar(data); + BroadcastPacketToWar(&data); } bool Battlefield::HasPlayer(Player* player) const @@ -410,28 +411,28 @@ void Battlefield::TeamCastSpell(TeamId team, int32 spellId) } } -void Battlefield::BroadcastPacketToZone(WorldPacket& data) const +void Battlefield::BroadcastPacketToZone(WorldPacket const* data) const { for (uint8 team = 0; team < BG_TEAMS_COUNT; ++team) for (GuidSet::const_iterator itr = m_players[team].begin(); itr != m_players[team].end(); ++itr) if (Player* player = ObjectAccessor::FindPlayer(*itr)) - player->SendDirectMessage(&data); + player->SendDirectMessage(data); } -void Battlefield::BroadcastPacketToQueue(WorldPacket& data) const +void Battlefield::BroadcastPacketToQueue(WorldPacket const* data) const { for (uint8 team = 0; team < BG_TEAMS_COUNT; ++team) for (GuidSet::const_iterator itr = m_PlayersInQueue[team].begin(); itr != m_PlayersInQueue[team].end(); ++itr) if (Player* player = ObjectAccessor::FindConnectedPlayer(*itr)) - player->SendDirectMessage(&data); + player->SendDirectMessage(data); } -void Battlefield::BroadcastPacketToWar(WorldPacket& data) const +void Battlefield::BroadcastPacketToWar(WorldPacket const* data) const { for (uint8 team = 0; team < BG_TEAMS_COUNT; ++team) for (GuidSet::const_iterator itr = m_PlayersInWar[team].begin(); itr != m_PlayersInWar[team].end(); ++itr) if (Player* player = ObjectAccessor::FindPlayer(*itr)) - player->SendDirectMessage(&data); + player->SendDirectMessage(data); } void Battlefield::SendWarning(uint8 id, WorldObject const* target /*= nullptr*/) @@ -440,12 +441,13 @@ void Battlefield::SendWarning(uint8 id, WorldObject const* target /*= nullptr*/) sCreatureTextMgr->SendChat(stalker, id, target); } -void Battlefield::SendUpdateWorldState(uint32 field, uint32 value) +void Battlefield::SendUpdateWorldState(uint32 variable, uint32 value, bool hidden /*= false*/) { - for (uint8 i = 0; i < BG_TEAMS_COUNT; ++i) - for (GuidSet::iterator itr = m_players[i].begin(); itr != m_players[i].end(); ++itr) - if (Player* player = ObjectAccessor::FindPlayer(*itr)) - player->SendUpdateWorldState(field, value); + WorldPackets::WorldState::UpdateWorldState worldstate; + worldstate.VariableID = variable; + worldstate.Value = value; + worldstate.Hidden = hidden; + BroadcastPacketToZone(worldstate.Write()); } void Battlefield::RegisterZone(uint32 zoneId) diff --git a/src/server/game/Battlefield/Battlefield.h b/src/server/game/Battlefield/Battlefield.h index 29b8f4a5126..03557779ab1 100644 --- a/src/server/game/Battlefield/Battlefield.h +++ b/src/server/game/Battlefield/Battlefield.h @@ -200,7 +200,7 @@ class Battlefield : public ZoneScript virtual bool SetupBattlefield() { return true; } /// Update data of a worldstate to all players present in zone - void SendUpdateWorldState(uint32 field, uint32 value); + void SendUpdateWorldState(uint32 variable, uint32 value, bool hidden = false); /** * \brief Called every time for update bf data and time @@ -397,9 +397,9 @@ class Battlefield : public ZoneScript virtual void SendRemoveWorldStates(Player* /*player*/) { } // use for send a packet for all player list - void BroadcastPacketToZone(WorldPacket& data) const; - void BroadcastPacketToQueue(WorldPacket& data) const; - void BroadcastPacketToWar(WorldPacket& data) const; + void BroadcastPacketToZone(WorldPacket const* data) const; + void BroadcastPacketToQueue(WorldPacket const* data) const; + void BroadcastPacketToWar(WorldPacket const* data) const; // CapturePoint system void AddCapturePoint(BfCapturePoint* cp) { m_capturePoints[cp->GetCapturePointEntry()] = cp; } diff --git a/src/server/game/Battlegrounds/Battleground.cpp b/src/server/game/Battlegrounds/Battleground.cpp index ee3cb147b9f..c021b731714 100644 --- a/src/server/game/Battlegrounds/Battleground.cpp +++ b/src/server/game/Battlegrounds/Battleground.cpp @@ -37,6 +37,7 @@ #include "SpellAuras.h" #include "Util.h" #include "WorldPacket.h" +#include "WorldStatePackets.h" #include "Transport.h" namespace Trinity @@ -634,14 +635,14 @@ Position const* Battleground::GetTeamStartPosition(TeamId teamId) const return &StartPosition[teamId]; } -void Battleground::SendPacketToAll(WorldPacket* packet) +void Battleground::SendPacketToAll(WorldPacket const* packet) const { for (BattlegroundPlayerMap::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) if (Player* player = _GetPlayer(itr, "SendPacketToAll")) player->SendDirectMessage(packet); } -void Battleground::SendPacketToTeam(uint32 TeamID, WorldPacket* packet, Player* sender, bool self) +void Battleground::SendPacketToTeam(uint32 TeamID, WorldPacket const* packet, Player* sender, bool self) const { for (BattlegroundPlayerMap::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) { @@ -716,18 +717,13 @@ void Battleground::RewardReputationToTeam(uint32 faction_id, uint32 Reputation, } } -void Battleground::UpdateWorldState(uint32 Field, uint32 Value) +void Battleground::UpdateWorldState(uint32 variable, uint32 value, bool hidden /*= false*/) { - WorldPacket data; - sBattlegroundMgr->BuildUpdateWorldStatePacket(&data, Field, Value); - SendPacketToAll(&data); -} - -void Battleground::UpdateWorldStateForPlayer(uint32 field, uint32 value, Player* player) -{ - WorldPacket data; - sBattlegroundMgr->BuildUpdateWorldStatePacket(&data, field, value); - player->SendDirectMessage(&data); + WorldPackets::WorldState::UpdateWorldState worldstate; + worldstate.VariableID = variable; + worldstate.Value = value; + worldstate.Hidden = hidden; + SendPacketToAll(worldstate.Write()); } void Battleground::EndBattleground(uint32 winner) diff --git a/src/server/game/Battlegrounds/Battleground.h b/src/server/game/Battlegrounds/Battleground.h index fc52178c52d..aa0bb6fbb4c 100644 --- a/src/server/game/Battlegrounds/Battleground.h +++ b/src/server/game/Battlegrounds/Battleground.h @@ -347,8 +347,8 @@ class Battleground // Packet Transfer // method that should fill worldpacket with actual world states (not yet implemented for all battlegrounds!) virtual void FillInitialWorldStates(WorldPacket& /*data*/) { } - void SendPacketToTeam(uint32 TeamID, WorldPacket* packet, Player* sender = NULL, bool self = true); - void SendPacketToAll(WorldPacket* packet); + void SendPacketToTeam(uint32 TeamID, WorldPacket const* packet, Player* sender = NULL, bool self = true) const; + void SendPacketToAll(WorldPacket const* packet) const; void SendChatMessage(Creature* source, uint8 textId, WorldObject* target = NULL); @@ -361,8 +361,7 @@ class Battleground void RemoveAuraOnTeam(uint32 SpellID, uint32 TeamID); void RewardHonorToTeam(uint32 Honor, uint32 TeamID); void RewardReputationToTeam(uint32 faction_id, uint32 Reputation, uint32 TeamID); - void UpdateWorldState(uint32 Field, uint32 Value); - void UpdateWorldStateForPlayer(uint32 Field, uint32 Value, Player* player); + void UpdateWorldState(uint32 variable, uint32 value, bool hidden = false); virtual void EndBattleground(uint32 winner); void BlockMovement(Player* player); diff --git a/src/server/game/Battlegrounds/BattlegroundMgr.cpp b/src/server/game/Battlegrounds/BattlegroundMgr.cpp index 663530cd8ff..0e9dcfacd62 100644 --- a/src/server/game/Battlegrounds/BattlegroundMgr.cpp +++ b/src/server/game/Battlegrounds/BattlegroundMgr.cpp @@ -426,13 +426,6 @@ void BattlegroundMgr::BuildStatusFailedPacket(WorldPacket* data, Battleground* b data->WriteByteSeq(unkGuid3[5]); } -void BattlegroundMgr::BuildUpdateWorldStatePacket(WorldPacket* data, uint32 field, uint32 value) -{ - data->Initialize(SMSG_UPDATE_WORLD_STATE, 4+4); - *data << uint32(field); - *data << uint32(value); -} - void BattlegroundMgr::BuildPlaySoundPacket(WorldPacket* data, uint32 soundid) { data->Initialize(SMSG_PLAY_SOUND, 4 + 8); diff --git a/src/server/game/Battlegrounds/BattlegroundMgr.h b/src/server/game/Battlegrounds/BattlegroundMgr.h index 0be6092eb4b..c98502945f7 100644 --- a/src/server/game/Battlegrounds/BattlegroundMgr.h +++ b/src/server/game/Battlegrounds/BattlegroundMgr.h @@ -74,7 +74,6 @@ class BattlegroundMgr void BuildPlayerLeftBattlegroundPacket(WorldPacket* data, ObjectGuid guid); void BuildBattlegroundListPacket(WorldPacket* data, ObjectGuid guid, Player* player, BattlegroundTypeId bgTypeId); void BuildStatusFailedPacket(WorldPacket* data, Battleground* bg, Player* pPlayer, uint8 QueueSlot, GroupJoinBattlegroundResult result); - void BuildUpdateWorldStatePacket(WorldPacket* data, uint32 field, uint32 value); void BuildBattlegroundStatusPacket(WorldPacket* data, Battleground* bg, Player* player, uint8 queueSlot, uint8 statusId, uint32 time1, uint32 time2, uint8 arenaType); void BuildPlaySoundPacket(WorldPacket* data, uint32 soundId); void SendAreaSpiritHealerQueryOpcode(Player* player, Battleground* bg, ObjectGuid guid); diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp index a9647c5d384..dfecab6a5d4 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp @@ -179,9 +179,9 @@ void BattlegroundEY::CheckSomeoneJoinedPoint() { //player joined point! //show progress bar - UpdateWorldStateForPlayer(PROGRESS_BAR_PERCENT_GREY, BG_EY_PROGRESS_BAR_PERCENT_GREY, player); - UpdateWorldStateForPlayer(PROGRESS_BAR_STATUS, m_PointBarStatus[i], player); - UpdateWorldStateForPlayer(PROGRESS_BAR_SHOW, BG_EY_PROGRESS_BAR_SHOW, player); + player->SendUpdateWorldState(PROGRESS_BAR_PERCENT_GREY, BG_EY_PROGRESS_BAR_PERCENT_GREY); + player->SendUpdateWorldState(PROGRESS_BAR_STATUS, m_PointBarStatus[i]); + player->SendUpdateWorldState(PROGRESS_BAR_SHOW, BG_EY_PROGRESS_BAR_SHOW); //add player to point m_PlayersNearPoint[i].push_back(m_PlayersNearPoint[EY_POINTS_MAX][j]); //remove player from "free space" @@ -222,7 +222,7 @@ void BattlegroundEY::CheckSomeoneLeftPoint() { m_PlayersNearPoint[EY_POINTS_MAX].push_back(m_PlayersNearPoint[i][j]); m_PlayersNearPoint[i].erase(m_PlayersNearPoint[i].begin() + j); - this->UpdateWorldStateForPlayer(PROGRESS_BAR_SHOW, BG_EY_PROGRESS_BAR_DONT_SHOW, player); + player->SendUpdateWorldState(PROGRESS_BAR_SHOW, BG_EY_PROGRESS_BAR_DONT_SHOW); } else { @@ -265,7 +265,7 @@ void BattlegroundEY::UpdatePointStatuses() Player* player = ObjectAccessor::FindPlayer(m_PlayersNearPoint[point][i]); if (player) { - this->UpdateWorldStateForPlayer(PROGRESS_BAR_STATUS, m_PointBarStatus[point], player); + player->SendUpdateWorldState(PROGRESS_BAR_STATUS, m_PointBarStatus[point]); //if point owner changed we must evoke event! if (pointOwnerTeamId != m_PointOwnedByTeam[point]) { diff --git a/src/server/game/CMakeLists.txt b/src/server/game/CMakeLists.txt index bcf1a33a626..d18fce9b829 100644 --- a/src/server/game/CMakeLists.txt +++ b/src/server/game/CMakeLists.txt @@ -128,6 +128,7 @@ include_directories( ${CMAKE_SOURCE_DIR}/src/server/shared/Logging ${CMAKE_SOURCE_DIR}/src/server/shared/Networking ${CMAKE_SOURCE_DIR}/src/server/shared/Packets + ${CMAKE_SOURCE_DIR}/src/server/shared/Realm ${CMAKE_SOURCE_DIR}/src/server/shared/Threading ${CMAKE_SOURCE_DIR}/src/server/shared/Utilities ${CMAKE_SOURCE_DIR}/src/server/ipc diff --git a/src/server/game/DataStores/DBCStores.cpp b/src/server/game/DataStores/DBCStores.cpp index c48bf907d53..2e54b797934 100644 --- a/src/server/game/DataStores/DBCStores.cpp +++ b/src/server/game/DataStores/DBCStores.cpp @@ -17,6 +17,7 @@ */ #include "DBCStores.h" +#include "Containers.h" #include "Log.h" #include "SharedDefines.h" #include "SpellMgr.h" @@ -165,7 +166,7 @@ DBCStorage <MountCapabilityEntry> sMountCapabilityStore(MountCapabilityfmt); DBCStorage <MountTypeEntry> sMountTypeStore(MountTypefmt); DBCStorage <NameGenEntry> sNameGenStore(NameGenfmt); -NameGenVectorArraysMap sGenNameVectoArraysMap; +NameGenContainer sGenerateNamesMap; DBCStorage <OverrideSpellDataEntry> sOverrideSpellDataStore(OverrideSpellDatafmt); @@ -485,7 +486,7 @@ void LoadDBCStores(const std::string& dataPath) LoadDBC(availableDbcLocales, bad_dbc_files, sMountCapabilityStore, dbcPath, "MountCapability.dbc");//15595 LoadDBC(availableDbcLocales, bad_dbc_files, sMountTypeStore, dbcPath, "MountType.dbc");//15595 - LoadDBC(availableDbcLocales, bad_dbc_files, sNameGenStore, dbcPath, "NameGen.dbc");//15595 + LoadDBC(availableDbcLocales, bad_dbc_files, sNameGenStore, dbcPath, "NameGen.dbc"); // 19116 for (uint32 i = 0; i < sNameGenStore.GetNumRows(); ++i) if (NameGenEntry const* entry = sNameGenStore.LookupEntry(i)) sGenNameVectoArraysMap[entry->Race].stringVectorArray[entry->Sex].push_back(std::string(entry->Name)); @@ -793,7 +794,7 @@ void LoadDBCStores(const std::string& dataPath) sWMOAreaInfoByTripple.insert(WMOAreaInfoByTripple::value_type(WMOAreaTableTripple(entry->rootId, entry->adtId, entry->groupId), entry)); LoadDBC(availableDbcLocales, bad_dbc_files, sWorldMapAreaStore, dbcPath, "WorldMapArea.dbc");//15595 LoadDBC(availableDbcLocales, bad_dbc_files, sWorldMapOverlayStore, dbcPath, "WorldMapOverlay.dbc");//15595 - LoadDBC(availableDbcLocales, bad_dbc_files, sWorldSafeLocsStore, dbcPath, "WorldSafeLocs.dbc");//15595 + LoadDBC(availableDbcLocales, bad_dbc_files, sWorldSafeLocsStore, dbcPath, "WorldSafeLocs.dbc"); // 19116 // error checks if (bad_dbc_files.size() >= DBCFileCount) @@ -825,12 +826,10 @@ void LoadDBCStores(const std::string& dataPath) TC_LOG_INFO("server.loading", ">> Initialized %d DBC data stores in %u ms", DBCFileCount, GetMSTimeDiffToNow(oldMSTime)); } -const std::string* GetRandomCharacterName(uint8 race, uint8 gender) +std::string const& GetRandomCharacterName(uint8 race, uint8 gender) { - uint32 size = sGenNameVectoArraysMap[race].stringVectorArray[gender].size(); - uint32 randPos = urand(0, size-1); - - return &sGenNameVectoArraysMap[race].stringVectorArray[gender][randPos]; + ASSERT(gender < GENDER_NONE); + return Trinity::Containers::SelectRandomContainerElement(sGenerateNamesMap[race].Contents[gender]); } SimpleFactionsList const* GetFactionTeamList(uint32 faction) diff --git a/src/server/game/DataStores/DBCStores.h b/src/server/game/DataStores/DBCStores.h index 3df92263a86..53be6a0ebb9 100644 --- a/src/server/game/DataStores/DBCStores.h +++ b/src/server/game/DataStores/DBCStores.h @@ -44,7 +44,7 @@ WMOAreaTableEntry const* GetWMOAreaTableEntryByTripple(int32 rootid, int32 adtid uint32 GetVirtualMapForMapAndZone(uint32 mapid, uint32 zoneId); -const std::string* GetRandomCharacterName(uint8 race, uint8 gender); +std::string const& GetRandomCharacterName(uint8 race, uint8 gender); enum ContentLevels { diff --git a/src/server/game/DataStores/DBCStructure.h b/src/server/game/DataStores/DBCStructure.h index e8848fb8eaa..7896a1be533 100644 --- a/src/server/game/DataStores/DBCStructure.h +++ b/src/server/game/DataStores/DBCStructure.h @@ -2455,10 +2455,10 @@ struct WorldStateUI struct VectorArray { - std::vector<std::string> stringVectorArray[2]; + std::vector<std::string> Contents[2]; }; -typedef std::map<uint32, VectorArray> NameGenVectorArraysMap; +typedef std::map<uint32, VectorArray> NameGenContainer; // Structures not used for casting to loaded DBC data and not required then packing struct MapDifficulty diff --git a/src/server/game/DungeonFinding/LFGMgr.cpp b/src/server/game/DungeonFinding/LFGMgr.cpp index 8651b1ff8a5..863324f278c 100644 --- a/src/server/game/DungeonFinding/LFGMgr.cpp +++ b/src/server/game/DungeonFinding/LFGMgr.cpp @@ -33,6 +33,7 @@ #include "GroupMgr.h" #include "GameEventMgr.h" #include "WorldSession.h" +#include "InstanceSaveMgr.h" namespace lfg { @@ -482,7 +483,7 @@ void LFGMgr::JoinLfg(Player* player, uint8 roles, LfgDungeonSet& dungeons, const dungeons = GetDungeonsByRandom(rDungeonId); // if we have lockmap then there are no compatible dungeons - GetCompatibleDungeons(dungeons, players, joinData.lockmap); + GetCompatibleDungeons(dungeons, players, joinData.lockmap, isContinue); if (dungeons.empty()) joinData.result = grp ? LFG_JOIN_INTERNAL_ERROR : LFG_JOIN_NOT_MEET_REQS; } @@ -747,20 +748,48 @@ void LFGMgr::UpdateRoleCheck(ObjectGuid gguid, ObjectGuid guid /* = ObjectGuid:: @param[in] players Set of players to check their dungeon restrictions @param[out] lockMap Map of players Lock status info of given dungeons (Empty if dungeons is not empty) */ -void LFGMgr::GetCompatibleDungeons(LfgDungeonSet& dungeons, GuidSet const& players, LfgLockPartyMap& lockMap) +void LFGMgr::GetCompatibleDungeons(LfgDungeonSet& dungeons, GuidSet const& players, LfgLockPartyMap& lockMap, bool isContinue) { lockMap.clear(); + + std::map<uint32, uint32> lockedDungeons; + for (GuidSet::const_iterator it = players.begin(); it != players.end() && !dungeons.empty(); ++it) { ObjectGuid guid = (*it); LfgLockMap const& cachedLockMap = GetLockedDungeons(guid); + Player* player = ObjectAccessor::FindPlayer(guid); for (LfgLockMap::const_iterator it2 = cachedLockMap.begin(); it2 != cachedLockMap.end() && !dungeons.empty(); ++it2) { uint32 dungeonId = (it2->first & 0x00FFFFFF); // Compare dungeon ids LfgDungeonSet::iterator itDungeon = dungeons.find(dungeonId); if (itDungeon != dungeons.end()) { - dungeons.erase(itDungeon); + bool eraseDungeon = true; + + // Don't remove the dungeon if team members are trying to continue a locked instance + if (it2->second.lockStatus == LFG_LOCKSTATUS_RAID_LOCKED && isContinue) + { + LFGDungeonData const* dungeon = GetLFGDungeon(dungeonId); + ASSERT(dungeon); + ASSERT(player); + if (InstancePlayerBind* playerBind = player->GetBoundInstance(dungeon->map, Difficulty(dungeon->difficulty))) + { + if (InstanceSave* playerSave = playerBind->save) + { + uint32 dungeonInstanceId = playerSave->GetInstanceId(); + auto itLockedDungeon = lockedDungeons.find(dungeonId); + if (itLockedDungeon == lockedDungeons.end() || itLockedDungeon->second == dungeonInstanceId) + eraseDungeon = false; + + lockedDungeons[dungeonId] = dungeonInstanceId; + } + } + } + + if (eraseDungeon) + dungeons.erase(itDungeon); + lockMap[guid][dungeonId] = it2->second; } } diff --git a/src/server/game/DungeonFinding/LFGMgr.h b/src/server/game/DungeonFinding/LFGMgr.h index 03452caeabd..dea8d996c53 100644 --- a/src/server/game/DungeonFinding/LFGMgr.h +++ b/src/server/game/DungeonFinding/LFGMgr.h @@ -436,7 +436,7 @@ class LFGMgr void DecreaseKicksLeft(ObjectGuid guid); void SetState(ObjectGuid guid, LfgState state); void RemovePlayerData(ObjectGuid guid); - void GetCompatibleDungeons(LfgDungeonSet& dungeons, GuidSet const& players, LfgLockPartyMap& lockMap); + void GetCompatibleDungeons(LfgDungeonSet& dungeons, GuidSet const& players, LfgLockPartyMap& lockMap, bool isContinue); void _SaveToDB(ObjectGuid guid, uint32 db_guid); LFGDungeonData const* GetLFGDungeon(uint32 id); diff --git a/src/server/game/Entities/Object/Updates/UpdateData.cpp b/src/server/game/Entities/Object/Updates/UpdateData.cpp index df7f6fdcc77..74f6b62e398 100644 --- a/src/server/game/Entities/Object/Updates/UpdateData.cpp +++ b/src/server/game/Entities/Object/Updates/UpdateData.cpp @@ -45,11 +45,11 @@ void UpdateData::AddUpdateBlock(const ByteBuffer &block) bool UpdateData::BuildPacket(WorldPacket* packet) { ASSERT(packet->empty()); // shouldn't happen - packet->Initialize(SMSG_UPDATE_OBJECT, 2 + 4 + (m_outOfRangeGUIDs.empty() ? 0 : 1 + 4 + 9 * m_outOfRangeGUIDs.size()) + m_data.wpos()); + packet->Initialize(SMSG_UPDATE_OBJECT, 2 + 4 + (m_outOfRangeGUIDs.empty() ? 0 : 1 + 4 + 9 * m_outOfRangeGUIDs.size()) + m_data.wpos(), CONNECTION_TYPE_INSTANCE); *packet << uint32(m_blockCount); *packet << uint16(m_map); - + if (packet->WriteBit(!m_outOfRangeGUIDs.empty())) { *packet << uint16(0); diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 106c8e82ead..6b1e8fc95fa 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -41,6 +41,7 @@ #include "DisableMgr.h" #include "Formulas.h" #include "GameEventMgr.h" +#include "GameObjectAI.h" #include "GossipDef.h" #include "GridNotifiers.h" #include "GridNotifiersImpl.h" @@ -55,6 +56,7 @@ #include "Log.h" #include "MapInstanced.h" #include "MapManager.h" +#include "MovementStructures.h" #include "ObjectAccessor.h" #include "ObjectMgr.h" #include "Opcodes.h" @@ -81,8 +83,7 @@ #include "World.h" #include "WorldPacket.h" #include "WorldSession.h" -#include "MovementStructures.h" -#include "GameObjectAI.h" +#include "WorldStatePackets.h" #define ZONE_UPDATE_INTERVAL (1*IN_MILLISECONDS) @@ -6521,7 +6522,7 @@ void Player::SendMessageToSet(WorldPacket* data, Player const* skipped_rcvr) VisitNearbyWorldObject(GetVisibilityRange(), notifier); } -void Player::SendDirectMessage(WorldPacket* data) +void Player::SendDirectMessage(WorldPacket const* data) { m_session->SendPacket(data); } @@ -9089,13 +9090,13 @@ void Player::SendNotifyLootItemRemoved(uint8 lootSlot) GetSession()->SendPacket(&data); } -void Player::SendUpdateWorldState(uint32 Field, uint32 Value) +void Player::SendUpdateWorldState(uint32 variable, uint32 value, bool hidden /*= false*/) { - WorldPacket data(SMSG_UPDATE_WORLD_STATE, 4+4+1); - data << Field; - data << Value; - data << uint8(0); - GetSession()->SendPacket(&data); + WorldPackets::WorldState::UpdateWorldState worldstate; + worldstate.VariableID = variable; + worldstate.Value = value; + worldstate.Hidden = hidden; + SendDirectMessage(worldstate.Write()); } void Player::SendInitWorldStates(uint32 zoneid, uint32 areaid) @@ -9115,22 +9116,22 @@ void Player::SendInitWorldStates(uint32 zoneid, uint32 areaid) data << uint32(areaid); // area id, new 2.1.0 size_t countPos = data.wpos(); data << uint16(0); // count of uint64 blocks - data << uint32(0x8d8) << uint32(0x0); // 1 - data << uint32(0x8d7) << uint32(0x0); // 2 - data << uint32(0x8d6) << uint32(0x0); // 3 - data << uint32(0x8d5) << uint32(0x0); // 4 - data << uint32(0x8d4) << uint32(0x0); // 5 - data << uint32(0x8d3) << uint32(0x0); // 6 - // 7 1 - Arena season in progress, 0 - end of season - data << uint32(0xC77) << uint32(sWorld->getBoolConfig(CONFIG_ARENA_SEASON_IN_PROGRESS)); - // 8 Arena season id - data << uint32(0xF3D) << uint32(sWorld->getIntConfig(CONFIG_ARENA_SEASON_ID)); + data << uint32(2264) << uint32(0); // 1 + data << uint32(2263) << uint32(0); // 2 + data << uint32(2262) << uint32(0); // 3 + data << uint32(2261) << uint32(0); // 4 + data << uint32(2260) << uint32(0); // 5 + data << uint32(2259) << uint32(0); // 6 + + data << uint32(3191) << uint32(sWorld->getBoolConfig(CONFIG_ARENA_SEASON_IN_PROGRESS) ? sWorld->getIntConfig(CONFIG_ARENA_SEASON_ID) : 0); // 7 Current Season - Arena season in progress + // 0 - End of season + data << uint32(3901) << uint32(sWorld->getIntConfig(CONFIG_ARENA_SEASON_ID) - sWorld->getBoolConfig(CONFIG_ARENA_SEASON_IN_PROGRESS)); // 8 PreviousSeason if (mapid == 530) // Outland { - data << uint32(0x9bf) << uint32(0x0); // 7 - data << uint32(0x9bd) << uint32(0xF); // 8 - data << uint32(0x9bb) << uint32(0xF); // 9 + data << uint32(2495) << uint32(0x0); // 7 + data << uint32(2493) << uint32(0xF); // 8 + data << uint32(2491) << uint32(0xF); // 9 } // insert <field> <value> @@ -24590,7 +24591,7 @@ Player* Player::GetNextRandomRaidMember(float radius) return nearMembers[randTarget]; } -PartyResult Player::CanUninviteFromGroup() const +PartyResult Player::CanUninviteFromGroup(ObjectGuid guidMember) const { Group const* grp = GetGroup(); if (!grp) @@ -24632,6 +24633,9 @@ PartyResult Player::CanUninviteFromGroup() const if (InBattleground()) return ERR_INVITE_RESTRICTED; + + if (grp->IsLeader(guidMember)) + return ERR_NOT_LEADER; } return ERR_PARTY_RESULT_OK; @@ -25926,7 +25930,7 @@ void Player::AddKnownCurrency(uint32 itemId) void Player::UpdateFallInformationIfNeed(MovementInfo const& minfo, uint16 opcode) { - if (m_lastFallTime >= minfo.jump.fallTime || m_lastFallZ <= minfo.pos.GetPositionZ() || opcode == MSG_MOVE_FALL_LAND) + if (m_lastFallTime >= minfo.jump.fallTime || m_lastFallZ <= minfo.pos.GetPositionZ() || opcode == CMSG_MOVE_FALL_LAND) SetFallInformation(minfo.jump.fallTime, minfo.pos.GetPositionZ()); } diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 0ff29a9b053..f01846f5593 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -2248,8 +2248,8 @@ class Player : public Unit, public GridObject<Player> void DeleteEquipmentSet(uint64 setGuid); void SendInitWorldStates(uint32 zone, uint32 area); - void SendUpdateWorldState(uint32 Field, uint32 Value); - void SendDirectMessage(WorldPacket* data); + void SendUpdateWorldState(uint32 variable, uint32 value, bool hidden = false); + void SendDirectMessage(WorldPacket const* data); void SendBGWeekendWorldStates(); void SendBattlefieldWorldStates(); @@ -2484,7 +2484,7 @@ class Player : public Unit, public GridObject<Player> uint64 GetAuraUpdateMaskForRaid() const { return m_auraRaidUpdateMask; } void SetAuraUpdateMaskForRaid(uint8 slot) { m_auraRaidUpdateMask |= (uint64(1) << slot); } Player* GetNextRandomRaidMember(float radius); - PartyResult CanUninviteFromGroup() const; + PartyResult CanUninviteFromGroup(ObjectGuid guidMember = ObjectGuid::Empty) const; // Battleground / Battlefield Group System void SetBattlegroundOrBattlefieldRaid(Group* group, int8 subgroup = -1); diff --git a/src/server/game/Events/GameEventMgr.cpp b/src/server/game/Events/GameEventMgr.cpp index f8bc5e01c7b..cf46272080e 100644 --- a/src/server/game/Events/GameEventMgr.cpp +++ b/src/server/game/Events/GameEventMgr.cpp @@ -19,7 +19,6 @@ #include "GameEventMgr.h" #include "World.h" #include "ObjectMgr.h" -#include "WorldPacket.h" #include "PoolMgr.h" #include "Language.h" #include "Log.h" @@ -29,6 +28,7 @@ #include "BattlegroundMgr.h" #include "UnitAI.h" #include "GameObjectAI.h" +#include "WorldStatePackets.h" bool GameEventMgr::CheckOneGameEvent(uint16 entry) const { @@ -1484,11 +1484,13 @@ void GameEventMgr::UpdateWorldStates(uint16 event_id, bool Activate) if (bgTypeId != BATTLEGROUND_TYPE_NONE) { BattlemasterListEntry const* bl = sBattlemasterListStore.LookupEntry(bgTypeId); - if (bl && bl->HolidayWorldState) + if (bl && bl->HolidayWorldStateId) { - WorldPacket data; - sBattlegroundMgr->BuildUpdateWorldStatePacket(&data, bl->HolidayWorldState, Activate ? 1 : 0); - sWorld->SendGlobalMessage(&data); + WorldPackets::WorldState::UpdateWorldState worldstate; + worldstate.VariableID = bl->HolidayWorldStateId; + worldstate.Value = Activate; + //worldstate.Hidden = false; + sWorld->SendGlobalMessage(worldstate.Write()); } } } diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 97e2a40a02f..49b9c2c45ae 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -2678,7 +2678,7 @@ void ObjectMgr::LoadItemTemplates() itemTemplate.ItemId = itemId; itemTemplate.Class = uint32(fields[1].GetUInt8()); itemTemplate.SubClass = uint32(fields[2].GetUInt8()); - itemTemplate.SoundOverrideSubclass = fields[3].GetInt32(); + itemTemplate.SoundOverrideSubclass = fields[3].GetInt8(); itemTemplate.Name1 = fields[4].GetString(); itemTemplate.DisplayInfoID = fields[5].GetUInt32(); itemTemplate.Quality = uint32(fields[6].GetUInt8()); @@ -6365,11 +6365,11 @@ void ObjectMgr::SetHighestGuids() result = WorldDatabase.Query("SELECT MAX(guid) FROM gameobject"); if (result) - _gameObjectGuidGenerator.Set((*result)[0].GetUInt32() + 1); + _gameObjectGuidGenerator.Set((*result)[0].GetUInt64() + 1); result = WorldDatabase.Query("SELECT MAX(guid) FROM transports"); if (result) - _moTransportGuidGenerator.Set((*result)[0].GetUInt32() + 1); + _moTransportGuidGenerator.Set((*result)[0].GetUInt64() + 1); result = CharacterDatabase.Query("SELECT MAX(id) FROM auctionhouse"); if (result) @@ -8832,8 +8832,8 @@ void ObjectMgr::LoadCreatureClassLevelStats() } } - stats.BaseMana = fields[8].GetUInt16(); - stats.BaseArmor = fields[9].GetUInt16(); + stats.BaseMana = fields[8].GetUInt32(); + stats.BaseArmor = fields[9].GetUInt32(); stats.AttackPower = fields[10].GetUInt16(); stats.RangedAttackPower = fields[11].GetUInt16(); diff --git a/src/server/game/Guilds/Guild.cpp b/src/server/game/Guilds/Guild.cpp index d92716a0fec..7b71c6e826a 100644 --- a/src/server/game/Guilds/Guild.cpp +++ b/src/server/game/Guilds/Guild.cpp @@ -24,6 +24,7 @@ #include "Guild.h" #include "GuildFinderMgr.h" #include "GuildMgr.h" +#include "GuildPackets.h" #include "Language.h" #include "Log.h" #include "ScriptMgr.h" @@ -810,15 +811,6 @@ void EmblemInfo::LoadFromDB(Field* fields) m_backgroundColor = fields[7].GetUInt8(); } -void EmblemInfo::WritePacket(WorldPacket& data) const -{ - data << uint32(m_style); - data << uint32(m_color); - data << uint32(m_borderStyle); - data << uint32(m_borderColor); - data << uint32(m_backgroundColor); -} - void EmblemInfo::SaveToDB(ObjectGuid::LowType guildId) const { PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_GUILD_EMBLEM_INFO); @@ -1483,44 +1475,27 @@ void Guild::HandleRoster(WorldSession* session) session->SendPacket(&data); } -void Guild::HandleQuery(WorldSession* session) +void Guild::SendQueryResponse(WorldSession* session) { - WorldPacket data(SMSG_GUILD_QUERY_RESPONSE, 8 * 32 + 200); // Guess size + WorldPackets::Guild::QueryGuildInfoResponse response; + response.GuildGuid = GetGUID(); + response.Info.HasValue = true; - data << GetGUID(); - data << m_name; + response.Info.value.GuildGUID = GetGUID(); + response.Info.value.VirtualRealmAddress = GetVirtualRealmAddress(); - // Rank name - for (uint8 i = 0; i < GUILD_RANKS_MAX_COUNT; ++i) // Always show 10 ranks - { - if (i < _GetRanksSize()) - data << m_ranks[i].GetName(); - else - data << uint8(0); // Empty string - } + response.Info.value.EmblemStyle = m_emblemInfo.GetStyle(); + response.Info.value.EmblemColor = m_emblemInfo.GetColor(); + response.Info.value.BorderStyle = m_emblemInfo.GetBorderStyle(); + response.Info.value.BorderColor = m_emblemInfo.GetBorderColor(); + response.Info.value.BackgroundColor = m_emblemInfo.GetBackgroundColor(); - // Rank order of creation - for (uint8 i = 0; i < GUILD_RANKS_MAX_COUNT; ++i) - { - if (i < _GetRanksSize()) - data << uint32(i); - else - data << uint32(0); - } + for (uint8 i = 0; i < _GetRanksSize(); ++i) + response.Info.value.Ranks.emplace(m_ranks[i].GetId(), i, m_ranks[i].GetName()); - // Rank order of "importance" (sorting by rights) - for (uint8 i = 0; i < GUILD_RANKS_MAX_COUNT; ++i) - { - if (i < _GetRanksSize()) - data << uint32(m_ranks[i].GetId()); - else - data << uint32(0); - } - - m_emblemInfo.WritePacket(data); - data << uint32(_GetRanksSize()); // Number of ranks used + response.Info.value.GuildName = m_name; - session->SendPacket(&data); + session->SendPacket(response.Write()); TC_LOG_DEBUG("guild", "SMSG_GUILD_QUERY_RESPONSE [%s]", session->GetPlayerInfo().c_str()); } @@ -1645,7 +1620,7 @@ void Guild::HandleSetEmblem(WorldSession* session, const EmblemInfo& emblemInfo) SendSaveEmblemResult(session, ERR_GUILDEMBLEM_SUCCESS); // "Guild Emblem saved." - HandleQuery(session); + SendQueryResponse(session); } } diff --git a/src/server/game/Guilds/Guild.h b/src/server/game/Guilds/Guild.h index 1481ec3b042..4abeb282b0c 100644 --- a/src/server/game/Guilds/Guild.h +++ b/src/server/game/Guilds/Guild.h @@ -285,7 +285,6 @@ public: void LoadFromDB(Field* fields); void SaveToDB(ObjectGuid::LowType guildId) const; void ReadPacket(WorldPacket& recv); - void WritePacket(WorldPacket& data) const; uint32 GetStyle() const { return m_style; } uint32 GetColor() const { return m_color; } @@ -790,7 +789,7 @@ public: // Handle client commands void HandleRoster(WorldSession* session); - void HandleQuery(WorldSession* session); + void SendQueryResponse(WorldSession* session); void HandleSetAchievementTracking(WorldSession* session, std::set<uint32> const& achievementIds); void HandleSetMOTD(WorldSession* session, std::string const& motd); void HandleSetInfo(WorldSession* session, std::string const& info); diff --git a/src/server/game/Handlers/AuctionHouseHandler.cpp b/src/server/game/Handlers/AuctionHouseHandler.cpp index 82b2284bcd5..9197ea15b3d 100644 --- a/src/server/game/Handlers/AuctionHouseHandler.cpp +++ b/src/server/game/Handlers/AuctionHouseHandler.cpp @@ -65,7 +65,7 @@ void WorldSession::SendAuctionHello(ObjectGuid guid, Creature* unit) if (!ahEntry) return; - WorldPacket data(MSG_AUCTION_HELLO, 12); + WorldPacket data(SMSG_AUCTION_HELLO, 12); data << guid; data << uint32(ahEntry->ID); data << uint8(1); // 3.3.3: 1 - AH enabled, 0 - AH disabled @@ -74,7 +74,7 @@ void WorldSession::SendAuctionHello(ObjectGuid guid, Creature* unit) void WorldSession::SendAuctionCommandResult(AuctionEntry* auction, uint32 action, uint32 errorCode, uint32 /*bidError = 0*/) { - WorldPackets::AuctionHousePackets::AuctionCommandResult auctionCommandResult; + WorldPackets::AuctionHouse::AuctionCommandResult auctionCommandResult; auctionCommandResult.InitializeAuction(auction); auctionCommandResult.Action = action; auctionCommandResult.ErrorCode = errorCode; diff --git a/src/server/game/Handlers/AuthHandler.cpp b/src/server/game/Handlers/AuthHandler.cpp index fee7ad2542f..c9e1e6508b9 100644 --- a/src/server/game/Handlers/AuthHandler.cpp +++ b/src/server/game/Handlers/AuthHandler.cpp @@ -15,11 +15,10 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "ObjectMgr.h" -#include "Opcodes.h" #include "WorldSession.h" -#include "WorldPacket.h" +#include "ObjectMgr.h" #include "AuthenticationPackets.h" +#include "ClientConfigPackets.h" #include "SystemPackets.h" void WorldSession::SendAuthResponse(uint8 code, bool queued, uint32 queuePos) @@ -33,12 +32,12 @@ void WorldSession::SendAuthResponse(uint8 code, bool queued, uint32 queuePos) { response.SuccessInfo.value.AccountExpansionLevel = Expansion(); response.SuccessInfo.value.ActiveExpansionLevel = Expansion(); - response.SuccessInfo.value.VirtualRealmAddress = realmHandle.Index; + response.SuccessInfo.value.VirtualRealmAddress = GetVirtualRealmAddress(); std::string realmName = sObjectMgr->GetRealmName(realmHandle.Index); // Send current home realm. Also there is no need to send it later in realm queries. - response.SuccessInfo.value.VirtualRealms.emplace_back(realmHandle.Index, true, false, realmName, realmName); + response.SuccessInfo.value.VirtualRealms.emplace_back(GetVirtualRealmAddress(), true, false, realmName, realmName); response.SuccessInfo.value.AvailableClasses = &sObjectMgr->GetClassExpansionRequirements(); response.SuccessInfo.value.AvailableRaces = &sObjectMgr->GetRaceExpansionRequirements(); @@ -70,9 +69,10 @@ void WorldSession::SendAuthWaitQue(uint32 position) void WorldSession::SendClientCacheVersion(uint32 version) { - WorldPacket data(SMSG_CLIENTCACHE_VERSION, 4); - data << uint32(version); - SendPacket(&data); + WorldPackets::ClientConfig::ClientCacheVersion cache; + cache.CacheVersion = version; + + SendPacket(cache.Write()); } void WorldSession::SendSetTimeZoneInformation() diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index 1aa19063123..f605e138ce3 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -19,7 +19,10 @@ #include "AccountMgr.h" #include "ArenaTeam.h" #include "ArenaTeamMgr.h" +#include "AuthenticationPackets.h" #include "Battleground.h" +#include "BattlegroundPackets.h" +#include "BattlenetServerManager.h" #include "CalendarMgr.h" #include "CharacterPackets.h" #include "Chat.h" @@ -44,12 +47,12 @@ #include "SharedDefines.h" #include "SocialMgr.h" #include "SystemConfig.h" +#include "SystemPackets.h" #include "UpdateMask.h" #include "Util.h" #include "World.h" #include "WorldPacket.h" #include "WorldSession.h" -#include "BattlenetServerManager.h" class LoginQueryHolder : public SQLQueryHolder { @@ -762,7 +765,7 @@ void WorldSession::HandlePlayerLoginOpcode(WorldPackets::Character::PlayerLogin& TC_LOG_DEBUG("network", "WORLD: Recvd Player Logon Message"); - m_playerLoading = true; + m_playerLoading = playerLogin.Guid; TC_LOG_DEBUG("network", "Character %s logging in", playerLogin.Guid.ToString().c_str()); @@ -773,25 +776,40 @@ void WorldSession::HandlePlayerLoginOpcode(WorldPackets::Character::PlayerLogin& return; } - LoginQueryHolder* holder = new LoginQueryHolder(GetAccountId(), playerLogin.Guid); + boost::system::error_code ignored_error; + boost::asio::ip::tcp::endpoint instanceAddress = realm.GetAddressForClient(boost::asio::ip::address::from_string(GetRemoteAddress(), ignored_error)); + instanceAddress.port(sWorld->getIntConfig(CONFIG_PORT_INSTANCE)); + + WorldPackets::Auth::ConnectTo connectTo; + connectTo.Key = MAKE_PAIR64(GetAccountId(), CONNECTION_TYPE_INSTANCE); + connectTo.Serial = 1; + connectTo.Payload.Where = instanceAddress; + connectTo.Con = CONNECTION_TYPE_INSTANCE; + + SendPacket(connectTo.Write()); +} + +void WorldSession::HandleContinuePlayerLogin() +{ + if (!PlayerLoading() || GetPlayer()) + { + KickPlayer(); + return; + } + + LoginQueryHolder* holder = new LoginQueryHolder(GetAccountId(), m_playerLoading); if (!holder->Initialize()) { delete holder; // delete all unprocessed queries - m_playerLoading = false; + m_playerLoading.Clear(); return; } _charLoginCallback = CharacterDatabase.DelayQueryHolder(holder); } -void WorldSession::HandleLoadScreenOpcode(WorldPacket& recvPacket) +void WorldSession::HandleLoadScreenOpcode(WorldPackets::Character::LoadingScreenNotify& /*loadingScreenNotify*/) { - TC_LOG_INFO("misc", "WORLD: Recvd CMSG_LOAD_SCREEN"); - uint32 mapID; - - recvPacket >> mapID; - recvPacket.ReadBit(); - // TODO: Do something with this packet } @@ -810,7 +828,7 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder) KickPlayer(); // disconnect client, player no set to session and it will not deleted or saved at kick delete pCurrChar; // delete it manually delete holder; // delete all unprocessed queries - m_playerLoading = false; + m_playerLoading.Clear(); return; } @@ -865,36 +883,28 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder) // Send MOTD { - data.Initialize(SMSG_MOTD, 50); // new in 2.0.1 - data << (uint32)0; - - uint32 linecount=0; - std::string str_motd = sWorld->GetMotd(); - std::string::size_type pos, nextpos; + WorldPackets::System::MOTD motd; + motd.Text = &sWorld->GetMotd(); + SendPacket(motd.Write()); + TC_LOG_DEBUG("network", "WORLD: Sent motd (SMSG_MOTD)"); + } - pos = 0; - while ((nextpos= str_motd.find('@', pos)) != std::string::npos) - { - if (nextpos != pos) - { - data << str_motd.substr(pos, nextpos-pos); - ++linecount; - } - pos = nextpos+1; - } + SendSetTimeZoneInformation(); - if (pos<str_motd.length()) - { - data << str_motd.substr(pos); - ++linecount; - } + // Send PVPSeason + { + WorldPackets::Battleground::PVPSeason season; + season.PreviousSeason = sWorld->getIntConfig(CONFIG_ARENA_SEASON_ID) - sWorld->getBoolConfig(CONFIG_ARENA_SEASON_IN_PROGRESS); - data.put(0, linecount); + if (sWorld->getBoolConfig(CONFIG_ARENA_SEASON_IN_PROGRESS)) + season.CurrentSeason = sWorld->getIntConfig(CONFIG_ARENA_SEASON_ID); - SendPacket(&data); - TC_LOG_DEBUG("network", "WORLD: Sent motd (SMSG_MOTD)"); + SendPacket(season.Write()); + TC_LOG_DEBUG("network", "WORLD: Sent PVPSeason"); + } - // send server info + // send server info + { if (sWorld->getIntConfig(CONFIG_ENABLE_SINFO_LOGIN) == 1) chH.PSendSysMessage(_FULLVERSION); @@ -1072,7 +1082,7 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder) if (!pCurrChar->IsStandState() && !pCurrChar->HasUnitState(UNIT_STATE_STUNNED)) pCurrChar->SetStandState(UNIT_STAND_STATE_STAND); - m_playerLoading = false; + m_playerLoading.Clear(); // Handle Login-Achievements (should be handled after loading) _player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_ON_LOGIN, 1); @@ -2165,70 +2175,37 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recvData) SendCharFactionChange(RESPONSE_SUCCESS, factionChangeInfo); } -void WorldSession::HandleRandomizeCharNameOpcode(WorldPacket& recvData) +void WorldSession::HandleRandomizeCharNameOpcode(WorldPackets::Character::GenerateRandomCharacterName& packet) { - uint8 gender, race; - - recvData >> race; - recvData >> gender; - - if (!Player::IsValidRace(race)) + if (!Player::IsValidRace(packet.Race)) { - TC_LOG_ERROR("misc", "Invalid race (%u) sent by accountId: %u", race, GetAccountId()); + TC_LOG_ERROR("misc", "Invalid race (%u) sent by accountId: %u", packet.Race, GetAccountId()); return; } - if (!Player::IsValidGender(gender)) + if (!Player::IsValidGender(packet.Sex)) { - TC_LOG_ERROR("misc", "Invalid gender (%u) sent by accountId: %u", gender, GetAccountId()); + TC_LOG_ERROR("misc", "Invalid gender (%u) sent by accountId: %u", packet.Sex, GetAccountId()); return; } - std::string const* name = GetRandomCharacterName(race, gender); - WorldPacket data(SMSG_RANDOMIZE_CHAR_NAME, 10); - data.WriteBit(0); // unk - data.WriteBits(name->size(), 7); - data.WriteString(*name); - SendPacket(&data); + WorldPackets::Character::GenerateRandomCharacterNameResult result; + result.Success = true; + result.Name = GetRandomCharacterName(packet.Race, packet.Sex); + + SendPacket(result.Write()); } -void WorldSession::HandleReorderCharacters(WorldPacket& recvData) +void WorldSession::HandleReorderCharacters(WorldPackets::Character::ReorderCharacters& reorderChars) { - uint32 charactersCount = std::min<uint32>(recvData.ReadBits(10), sWorld->getIntConfig(CONFIG_CHARACTERS_PER_REALM)); - - std::vector<ObjectGuid> guids(charactersCount); - uint8 position; - - for (uint8 i = 0; i < charactersCount; ++i) - { - guids[i][1] = recvData.ReadBit(); - guids[i][4] = recvData.ReadBit(); - guids[i][5] = recvData.ReadBit(); - guids[i][3] = recvData.ReadBit(); - guids[i][0] = recvData.ReadBit(); - guids[i][7] = recvData.ReadBit(); - guids[i][6] = recvData.ReadBit(); - guids[i][2] = recvData.ReadBit(); - } - SQLTransaction trans = CharacterDatabase.BeginTransaction(); - for (uint8 i = 0; i < charactersCount; ++i) - { - recvData.ReadByteSeq(guids[i][6]); - recvData.ReadByteSeq(guids[i][5]); - recvData.ReadByteSeq(guids[i][1]); - recvData.ReadByteSeq(guids[i][4]); - recvData.ReadByteSeq(guids[i][0]); - recvData.ReadByteSeq(guids[i][3]); - - recvData >> position; - - recvData.ReadByteSeq(guids[i][2]); - recvData.ReadByteSeq(guids[i][7]); + for (WorldPackets::Character::ReorderCharacters::ReorderInfo const& reorderInfo : reorderChars.Entries) + { PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_LIST_SLOT); - stmt->setUInt8(0, position); - stmt->setUInt64(1, guids[i].GetCounter()); + stmt->setUInt8(0, reorderInfo.NewPosition); + stmt->setUInt64(1, reorderInfo.PlayerGUID.GetCounter()); + stmt->setUInt32(2, GetAccountId()); trans->Append(stmt); } diff --git a/src/server/game/Handlers/GroupHandler.cpp b/src/server/game/Handlers/GroupHandler.cpp index 32fb9bd1ee4..c5207941301 100644 --- a/src/server/game/Handlers/GroupHandler.cpp +++ b/src/server/game/Handlers/GroupHandler.cpp @@ -416,7 +416,7 @@ void WorldSession::HandleGroupUninviteGuidOpcode(WorldPacket& recvData) return; } - PartyResult res = GetPlayer()->CanUninviteFromGroup(); + PartyResult res = GetPlayer()->CanUninviteFromGroup(guid); if (res != ERR_PARTY_RESULT_OK) { SendPartyResult(PARTY_OP_UNINVITE, "", res); @@ -424,14 +424,8 @@ void WorldSession::HandleGroupUninviteGuidOpcode(WorldPacket& recvData) } Group* grp = GetPlayer()->GetGroup(); - if (!grp) - return; - - if (grp->IsLeader(guid)) - { - SendPartyResult(PARTY_OP_UNINVITE, "", ERR_NOT_LEADER); - return; - } + // grp is checked already above in CanUninviteFromGroup() + ASSERT(grp); if (grp->IsMember(guid)) { diff --git a/src/server/game/Handlers/GuildHandler.cpp b/src/server/game/Handlers/GuildHandler.cpp index dcae8bc35fa..23078ea5fc9 100644 --- a/src/server/game/Handlers/GuildHandler.cpp +++ b/src/server/game/Handlers/GuildHandler.cpp @@ -27,18 +27,25 @@ #include "Guild.h" #include "GossipDef.h" #include "SocialMgr.h" +#include "GuildPackets.h" -void WorldSession::HandleGuildQueryOpcode(WorldPacket& recvPacket) +void WorldSession::HandleGuildQueryOpcode(WorldPackets::Guild::QueryGuildInfo& query) { - ObjectGuid guildGuid, playerGuid; - recvPacket >> guildGuid >> playerGuid; - TC_LOG_DEBUG("guild", "CMSG_GUILD_QUERY [%s]: Guild: %s Target: %s", - GetPlayerInfo().c_str(), guildGuid.ToString().c_str(), playerGuid.ToString().c_str()); + GetPlayerInfo().c_str(), query.GuildGuid.ToString().c_str(), query.PlayerGuid.ToString().c_str()); - if (Guild* guild = sGuildMgr->GetGuildByGuid(guildGuid)) - if (guild->IsMember(playerGuid)) - guild->HandleQuery(this); + if (Guild* guild = sGuildMgr->GetGuildByGuid(query.GuildGuid)) + if (guild->IsMember(query.PlayerGuid)) + { + guild->SendQueryResponse(this); + return; + } + + WorldPackets::Guild::QueryGuildInfoResponse response; + response.GuildGuid = query.GuildGuid; + SendPacket(response.Write()); + + TC_LOG_DEBUG("guild", "SMSG_GUILD_QUERY_RESPONSE [%s]", GetPlayerInfo().c_str()); } void WorldSession::HandleGuildInviteOpcode(WorldPacket& recvPacket) diff --git a/src/server/game/Handlers/LFGHandler.cpp b/src/server/game/Handlers/LFGHandler.cpp index 014e9f7b9d6..39e3edb30ed 100644 --- a/src/server/game/Handlers/LFGHandler.cpp +++ b/src/server/game/Handlers/LFGHandler.cpp @@ -115,7 +115,9 @@ void WorldSession::HandleLfgJoinOpcode(WorldPacket& recvData) { uint32 dungeon; recvData >> dungeon; - newDungeons.insert((dungeon & 0x00FFFFFF)); // remove the type from the dungeon entry + dungeon &= 0x00FFFFFF; // remove the type from the dungeon entry + if (dungeon) + newDungeons.insert(dungeon); } TC_LOG_DEBUG("lfg", "CMSG_LFG_JOIN %s roles: %u, Dungeons: %u, Comment: %s", diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp index 455f003e5df..b28068538ce 100644 --- a/src/server/game/Handlers/MiscHandler.cpp +++ b/src/server/game/Handlers/MiscHandler.cpp @@ -56,6 +56,8 @@ #include "Battlefield.h" #include "BattlefieldMgr.h" #include "DB2Stores.h" +#include "CharacterPackets.h" +#include "MiscPackets.h" void WorldSession::HandleRepopRequestOpcode(WorldPacket& recvData) { @@ -373,7 +375,7 @@ void WorldSession::HandleWhoOpcode(WorldPacket& recvData) TC_LOG_DEBUG("network", "WORLD: Send SMSG_WHO Message"); } -void WorldSession::HandleLogoutRequestOpcode(WorldPacket& /*recvData*/) +void WorldSession::HandleLogoutRequestOpcode(WorldPackets::Character::LogoutRequest& /*logoutRequest*/) { TC_LOG_DEBUG("network", "WORLD: Recvd CMSG_LOGOUT_REQUEST Message, security - %u", GetSecurity()); @@ -395,14 +397,14 @@ void WorldSession::HandleLogoutRequestOpcode(WorldPacket& /*recvData*/) else if (GetPlayer()->duel || GetPlayer()->HasAura(9454)) // is dueling or frozen by GM via freeze command reason = 2; // FIXME - Need the correct value - WorldPacket data(SMSG_LOGOUT_RESPONSE, 1+4); - data << uint32(reason); - data << uint8(instantLogout); - SendPacket(&data); + WorldPackets::Character::LogoutResponse logoutResponse; + logoutResponse.LogoutResult = reason; + logoutResponse.Instant = instantLogout; + SendPacket(logoutResponse.Write()); if (reason) { - LogoutRequest(0); + SetLogoutStartTime(0); return; } @@ -422,15 +424,10 @@ void WorldSession::HandleLogoutRequestOpcode(WorldPacket& /*recvData*/) GetPlayer()->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); } - LogoutRequest(time(NULL)); -} - -void WorldSession::HandlePlayerLogoutOpcode(WorldPacket& /*recvData*/) -{ - TC_LOG_DEBUG("network", "WORLD: Recvd CMSG_PLAYER_LOGOUT Message"); + SetLogoutStartTime(time(NULL)); } -void WorldSession::HandleLogoutCancelOpcode(WorldPacket& /*recvData*/) +void WorldSession::HandleLogoutCancelOpcode(WorldPackets::Character::LogoutCancel& /*logoutCancel*/) { TC_LOG_DEBUG("network", "WORLD: Recvd CMSG_LOGOUT_CANCEL Message"); @@ -438,10 +435,9 @@ void WorldSession::HandleLogoutCancelOpcode(WorldPacket& /*recvData*/) if (!GetPlayer()) return; - LogoutRequest(0); + SetLogoutStartTime(0); - WorldPacket data(SMSG_LOGOUT_CANCEL_ACK, 0); - SendPacket(&data); + SendPacket(WorldPackets::Character::LogoutCancelAck().Write()); // not remove flags if can't free move - its not set in Logout request code. if (GetPlayer()->CanFreeMove()) @@ -2005,16 +2001,13 @@ void WorldSession::HandleUpdateMissileTrajectory(WorldPacket& recvPacket) { uint32 opcode; recvPacket >> opcode; - recvPacket.SetOpcode(MSG_MOVE_STOP); // always set to MSG_MOVE_STOP in client SetOpcode + recvPacket.SetOpcode(CMSG_MOVE_STOP); // always set to CMSG_MOVE_STOP in client SetOpcode HandleMovementOpcodes(recvPacket); } } -void WorldSession::HandleViolenceLevel(WorldPacket& recvPacket) +void WorldSession::HandleViolenceLevel(WorldPackets::Misc::ViolenceLevel& /*violenceLevel*/) { - uint8 violenceLevel; - recvPacket >> violenceLevel; - // do something? } diff --git a/src/server/game/Handlers/MovementHandler.cpp b/src/server/game/Handlers/MovementHandler.cpp index 869e1627eac..21ef1fc6ae0 100644 --- a/src/server/game/Handlers/MovementHandler.cpp +++ b/src/server/game/Handlers/MovementHandler.cpp @@ -348,7 +348,7 @@ void WorldSession::HandleMovementOpcodes(WorldPacket& recvPacket) plrMover->m_transport->RemovePassenger(plrMover); // fall damage generation (ignore in flight case that can be triggered also at lags in moment teleportation to another map). - if (opcode == MSG_MOVE_FALL_LAND && plrMover && !plrMover->IsInFlight()) + if (opcode == CMSG_MOVE_FALL_LAND && plrMover && !plrMover->IsInFlight()) plrMover->HandleFall(movementInfo); if (plrMover && ((movementInfo.flags & MOVEMENTFLAG_SWIMMING) != 0) != plrMover->IsInWater()) diff --git a/src/server/game/Handlers/QueryHandler.cpp b/src/server/game/Handlers/QueryHandler.cpp index 2d7d18858cd..1f88585b5ae 100644 --- a/src/server/game/Handlers/QueryHandler.cpp +++ b/src/server/game/Handlers/QueryHandler.cpp @@ -30,49 +30,48 @@ #include "NPCHandler.h" #include "Pet.h" #include "MapManager.h" +#include "BattlenetAccountMgr.h" +#include "CharacterPackets.h" void WorldSession::SendNameQueryOpcode(ObjectGuid guid) { Player* player = ObjectAccessor::FindConnectedPlayer(guid); CharacterNameData const* nameData = sWorld->GetCharacterNameData(guid); - WorldPacket data(SMSG_NAME_QUERY_RESPONSE, (8+1+1+1+1+1+10)); - data << guid.WriteAsPacked(); - if (!nameData) - { - data << uint8(1); // name unknown - SendPacket(&data); - return; - } - - data << uint8(0); // name known - data << nameData->m_name; // played name - data << uint8(0); // realm name - only set for cross realm interaction (such as Battlegrounds) - data << uint8(nameData->m_race); - data << uint8(nameData->m_gender); - data << uint8(nameData->m_class); + WorldPackets::Character::PlayerNameResponse response; + response.Player = guid; - if (DeclinedName const* names = (player ? player->GetDeclinedNames() : NULL)) + if (nameData) { - data << uint8(1); // Name is declined - for (uint8 i = 0; i < MAX_DECLINED_NAME_CASES; ++i) - data << names->name[i]; + uint32 accountId = player ? player->GetSession()->GetAccountId() : sObjectMgr->GetPlayerAccountIdByGUID(guid); + uint32 bnetAccountId = player ? player->GetSession()->GetBattlenetAccountId() : Battlenet::AccountMgr::GetIdByGameAccount(accountId); + + response.Result = 0; // name known + response.Data.IsDeleted = false; // TODO: send deletes as well + response.Data.AccountID = ObjectGuid::Create<HighGuid::WowAccount>(accountId); + response.Data.BnetAccountID = ObjectGuid::Create<HighGuid::BNetAccount>(bnetAccountId); + response.Data.Name = nameData->m_name; + response.Data.VirtualRealmAddress = GetVirtualRealmAddress(); + response.Data.Race = nameData->m_race; + response.Data.Sex = nameData->m_gender; + response.Data.ClassID = nameData->m_class; + response.Data.Level = nameData->m_level; + + if (DeclinedName const* names = (player ? player->GetDeclinedNames() : nullptr)) + for (int i = 0; i < MAX_DECLINED_NAME_CASES; ++i) + response.Data.DeclinedNames.name[i] = names->name[i]; } else - data << uint8(0); // Name is not declined + { + response.Result = 1; // name unknown + } - SendPacket(&data); + SendPacket(response.Write()); } -void WorldSession::HandleNameQueryOpcode(WorldPacket& recvData) +void WorldSession::HandleNameQueryOpcode(WorldPackets::Character::QueryPlayerName& packet) { - ObjectGuid guid; - recvData >> guid; - - // This is disable by default to prevent lots of console spam - // TC_LOG_INFO("network", "HandleNameQueryOpcode %u", guid); - - SendNameQueryOpcode(guid); + SendNameQueryOpcode(packet.Player); } void WorldSession::HandleQueryTimeOpcode(WorldPacket & /*recvData*/) diff --git a/src/server/game/Handlers/TradeHandler.cpp b/src/server/game/Handlers/TradeHandler.cpp index 3e4e3306e7c..07c6264c808 100644 --- a/src/server/game/Handlers/TradeHandler.cpp +++ b/src/server/game/Handlers/TradeHandler.cpp @@ -29,6 +29,7 @@ #include "SocialMgr.h" #include "Language.h" #include "AccountMgr.h" +#include "TradePackets.h" void WorldSession::SendTradeStatus(TradeStatusInfo const& info) { @@ -655,7 +656,7 @@ void WorldSession::SendCancelTrade() SendTradeStatus(info); } -void WorldSession::HandleCancelTradeOpcode(WorldPacket& /*recvPacket*/) +void WorldSession::HandleCancelTradeOpcode(WorldPackets::Trade::CancelTrade& /*cancelTrade*/) { // sent also after LOGOUT COMPLETE if (_player) // needed because STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT diff --git a/src/server/game/Miscellaneous/Language.h b/src/server/game/Miscellaneous/Language.h index 41654f80dd4..a941dbd31ed 100644 --- a/src/server/game/Miscellaneous/Language.h +++ b/src/server/game/Miscellaneous/Language.h @@ -978,7 +978,12 @@ enum TrinityStrings LANG_GUILD_INFO_MOTD = 1182, LANG_GUILD_INFO_EXTRA_INFO = 1183, LANG_GUILD_INFO_LEVEL = 1184, - // Room for more level 3 1184-1199 not used + LANG_ACCOUNT_BNET_LINKED = 1185, + LANG_ACCOUNT_OR_BNET_DOES_NOT_EXIST = 1186, + LANG_ACCOUNT_ALREADY_LINKED = 1187, + LANG_ACCOUNT_BNET_UNLINKED = 1188, + LANG_ACCOUNT_BNET_NOT_LINKED = 1189, + // Room for more level 3 1190-1199 not used // Debug commands LANG_CINEMATIC_NOT_EXIST = 1200, diff --git a/src/server/game/Scripting/ScriptLoader.cpp b/src/server/game/Scripting/ScriptLoader.cpp index 0e43a63c98e..ad727fc17d2 100644 --- a/src/server/game/Scripting/ScriptLoader.cpp +++ b/src/server/game/Scripting/ScriptLoader.cpp @@ -677,6 +677,12 @@ void AddSC_zangarmarsh(); // Maelstrom void AddSC_kezan(); +void AddSC_instance_stonecore(); // Stonecore +void AddSC_stonecore(); +void AddSC_boss_corborus(); +void AddSC_boss_slabhide(); +void AddSC_boss_ozruk(); +void AddSC_boss_high_priestess_azil(); // Events void AddSC_event_childrens_week(); @@ -1411,6 +1417,12 @@ void AddMaelstromScripts() { #ifdef SCRIPTS AddSC_kezan(); + AddSC_instance_stonecore(); // Stonecore + AddSC_stonecore(); + AddSC_boss_corborus(); + AddSC_boss_slabhide(); + AddSC_boss_ozruk(); + AddSC_boss_high_priestess_azil(); #endif } diff --git a/src/server/game/Server/BattlenetServerManager.cpp b/src/server/game/Server/BattlenetServerManager.cpp index 7f6c1676c1f..048dc2d6402 100644 --- a/src/server/game/Server/BattlenetServerManager.cpp +++ b/src/server/game/Server/BattlenetServerManager.cpp @@ -62,5 +62,13 @@ void Battlenet::ServerManager::SendChangeToonOnlineState(uint32 battlenetAccount msg << toon; msg << online; - _socket->Send(&msg); + Send(&msg); +} + +void Battlenet::ServerManager::Send(zmqpp::message* msg) +{ + if (!_socket) + return; + + _socket->Send(msg); } diff --git a/src/server/game/Server/BattlenetServerManager.h b/src/server/game/Server/BattlenetServerManager.h index fe103a1c981..f2bd6e0ca19 100644 --- a/src/server/game/Server/BattlenetServerManager.h +++ b/src/server/game/Server/BattlenetServerManager.h @@ -24,6 +24,7 @@ namespace zmqpp { class socket; + class message; } namespace Battlenet @@ -45,6 +46,8 @@ namespace Battlenet void SendChangeToonOnlineState(uint32 battlenetAccountId, uint32 gameAccountId, ObjectGuid guid, std::string const& name, bool online); private: + void Send(zmqpp::message* msg); + static Header CreateHeader(BnetCommands command); ZmqMux* _socket; }; diff --git a/src/server/game/Server/Packet.cpp b/src/server/game/Server/Packet.cpp index 10b472bee67..ee805c18610 100644 --- a/src/server/game/Server/Packet.cpp +++ b/src/server/game/Server/Packet.cpp @@ -17,6 +17,164 @@ #include "Packet.h" +inline bool IsInstanceOnlyOpcode(uint32 opcode) +{ + // TODO: Use names when known + switch (opcode) + { + case 0x000F: // Client + case 0x0111: // Client + case 0x03E4: // Client + case 0x0549: // Client + case 0x054C: // Client + case 0x055A: // Client + case 0x056C: // Client + case 0x057A: // Client + case 0x057B: // Client + case 0x05CC: // Client + case 0x05EA: // Client + case 0x05EC: // Client + case 0x05F9: // Client + case 0x05FB: // Client + case 0x074C: // Client + case 0x075B: // Client + case 0x076C: // Client + case 0x077B: // Client + case 0x077C: // Client + case 0x07CC: // Client + case 0x07DB: // Client + case 0x07EC: // Client + case 0x07FB: // Client + case 0x07FC: // Client + case 0x0827: // Client + case 0x0935: // Client + case 0x0F0C: // ClientSpell + case 0x0F10: // ClientSpell + case 0x0F1B: // ClientSpell + case 0x0F1C: // ClientSpell + case 0x0F20: // ClientSpell + case 0x0F2C: // ClientSpell + case 0x0F2F: // ClientSpell + case 0x0F3B: // ClientSpell + case 0x0F8B: // ClientSpell + case 0x0F8C: // ClientSpell + case 0x0F90: // ClientSpell + case 0x0F9F: // ClientSpell + case 0x0FA0: // ClientSpell + case SMSG_ATTACKSTOP: // Client + case 0x14C9: // Client + case 0x154A: // Client + case 0x155A: // Client + case 0x155C: // Client + case SMSG_QUESTGIVER_STATUS: // ClientQuest + case 0x156A: // Client + case 0x156B: // Client + case 0x157A: // Client + case 0x157B: // Client + case 0x15DC: // Client + case 0x15EB: // Client + case 0x15FB: // Client + case 0x170C: // ClientSpell + case 0x171C: // ClientSpell + case 0x171F: // ClientSpell + case 0x172C: // ClientSpell + case 0x172F: // ClientSpell + case 0x173C: // ClientSpell + case 0x173F: // ClientSpell + case 0x1740: // ClientSpell + case 0x1790: // ClientSpell + case 0x179B: // ClientSpell + case 0x179F: // ClientSpell + case SMSG_ATTACKSTART: // Client + case 0x1D82: // ClientQuest + case 0x1D83: // ClientQuest + case 0x1D85: // ClientQuest + case 0x1D87: // ClientQuest + case 0x1D93: // ClientQuest + case 0x1D96: // ClientQuest + case 0x1D97: // ClientQuest + case 0x1DA1: // ClientQuest + case 0x1DA2: // ClientQuest + case 0x1DA3: // ClientQuest + case 0x1DA4: // ClientQuest + case 0x1DA5: // ClientQuest + case 0x1DA7: // ClientQuest + case SMSG_QUERY_TIME_RESPONSE: // Client + case 0x1DC2: // ClientQuest + case 0x1DC6: // ClientQuest + case 0x1DC7: // ClientQuest + case 0x1DD2: // ClientQuest + case 0x1DD3: // ClientQuest + case 0x1DD6: // ClientQuest + case 0x1DD7: // ClientQuest + case 0x1DD8: // ClientQuest + case 0x1DE4: // ClientQuest + case 0x1DE5: // ClientQuest + case 0x1DE7: // ClientQuest + case 0x1F02: // ClientQuest + case 0x1F06: // ClientQuest + case 0x1F07: // ClientQuest + case 0x1F0C: // ClientSpell + case 0x1F12: // ClientQuest + case 0x1F13: // ClientQuest + case 0x1F16: // ClientQuest + case 0x1F17: // ClientQuest + case 0x1F18: // ClientQuest + case 0x1F1C: // ClientSpell + case 0x1F1F: // ClientSpell + case 0x1F24: // ClientQuest + case 0x1F25: // ClientQuest + case 0x1F27: // ClientQuest + case 0x1F2C: // ClientSpell + case 0x1F2F: // ClientSpell + case 0x1F3C: // ClientSpell + case 0x1F3F: // ClientSpell + case 0x1F40: // ClientSpell + case 0x1F44: // ClientQuest + case 0x1F48: // ClientQuest + case 0x1F51: // ClientQuest + case 0x1F55: // ClientQuest + case 0x1F57: // ClientQuest + case 0x1F61: // ClientQuest + case 0x1F63: // ClientQuest + case 0x1F64: // ClientQuest + case 0x1F65: // ClientQuest + case 0x1F67: // ClientQuest + case 0x1F85: // ClientQuest + case 0x1F86: // ClientQuest + case 0x1F87: // ClientQuest + case 0x1F90: // ClientSpell + case 0x1F92: // ClientQuest + case 0x1F94: // ClientQuest + case 0x1F96: // ClientQuest + case 0x1F97: // ClientQuest + case 0x1F9B: // ClientSpell + case 0x1F9F: // ClientSpell + case 0x1FA1: // ClientQuest + case 0x1FA2: // ClientQuest + case 0x1FA3: // ClientQuest + case 0x1FA4: // ClientQuest + case 0x1FA5: // ClientQuest + case 0x1FA7: // ClientQuest + case 0x1FC2: // ClientQuest + case 0x1FC6: // ClientQuest + case 0x1FC7: // ClientQuest + case 0x1FD2: // ClientQuest + case 0x1FD3: // ClientQuest + case 0x1FD6: // ClientQuest + case 0x1FD7: // ClientQuest + case 0x1FD8: // ClientQuest + case 0x1FE4: // ClientQuest + case 0x1FE5: // ClientQuest + case 0x1FE7: // ClientQuest + return true; + default: + return false; + } +} + WorldPackets::ServerPacket::ServerPacket(OpcodeServer opcode, size_t initialSize /*= 200*/) : Packet(WorldPacket(opcode, initialSize)) { + if (IsInstanceOnlyOpcode(opcode)) + _connectionIndex = CONNECTION_TYPE_INSTANCE; } diff --git a/src/server/game/Server/Packet.h b/src/server/game/Server/Packet.h index 66061166ede..6c8216f6812 100644 --- a/src/server/game/Server/Packet.h +++ b/src/server/game/Server/Packet.h @@ -25,7 +25,11 @@ namespace WorldPackets class Packet { public: - Packet(WorldPacket&& worldPacket) : _worldPacket(std::move(worldPacket)) { } + Packet(WorldPacket&& worldPacket) : _worldPacket(std::move(worldPacket)) + { + _connectionIndex = _worldPacket.GetConnection(); + } + virtual ~Packet() = default; Packet(Packet const& right) = delete; @@ -35,9 +39,11 @@ namespace WorldPackets virtual void Read() = 0; size_t GetSize() const { return _worldPacket.size(); } + ConnectionType GetConnection() const { return _connectionIndex; } protected: WorldPacket _worldPacket; + ConnectionType _connectionIndex; }; class ServerPacket : public Packet @@ -53,7 +59,7 @@ namespace WorldPackets class ClientPacket : public Packet { public: - ClientPacket(WorldPacket&& packet) : Packet(std::move(packet)) { } + ClientPacket(OpcodeClient expectedOpcode, WorldPacket&& packet) : Packet(std::move(packet)) { ASSERT(packet.GetOpcode() == expectedOpcode); } WorldPacket const* Write() override final { diff --git a/src/server/game/Server/Packets/AuctionHousePackets.cpp b/src/server/game/Server/Packets/AuctionHousePackets.cpp index 56fa0ed396b..bb1a10be254 100644 --- a/src/server/game/Server/Packets/AuctionHousePackets.cpp +++ b/src/server/game/Server/Packets/AuctionHousePackets.cpp @@ -19,10 +19,10 @@ #include "AuctionHouseMgr.h" #include "ObjectGuid.h" -WorldPackets::AuctionHousePackets::AuctionCommandResult::AuctionCommandResult() +WorldPackets::AuctionHouse::AuctionCommandResult::AuctionCommandResult() : ServerPacket(SMSG_AUCTION_COMMAND_RESULT, 4 + 4 + 4 + 8 + 4 + 8 + 8 + 8) { } -void WorldPackets::AuctionHousePackets::AuctionCommandResult::InitializeAuction(AuctionEntry* auction) +void WorldPackets::AuctionHouse::AuctionCommandResult::InitializeAuction(AuctionEntry* auction) { if (auction) { @@ -33,7 +33,7 @@ void WorldPackets::AuctionHousePackets::AuctionCommandResult::InitializeAuction( } } -WorldPacket const* WorldPackets::AuctionHousePackets::AuctionCommandResult::Write() +WorldPacket const* WorldPackets::AuctionHouse::AuctionCommandResult::Write() { _worldPacket << uint32(AuctionId); _worldPacket << uint32(Action); diff --git a/src/server/game/Server/Packets/AuctionHousePackets.h b/src/server/game/Server/Packets/AuctionHousePackets.h index bf392246a20..4204c5c6afc 100644 --- a/src/server/game/Server/Packets/AuctionHousePackets.h +++ b/src/server/game/Server/Packets/AuctionHousePackets.h @@ -20,13 +20,11 @@ #include "Packet.h" #include "ObjectGuid.h" -class ObjectGuid; - struct AuctionEntry; namespace WorldPackets { - namespace AuctionHousePackets + namespace AuctionHouse { class AuctionCommandResult final : public ServerPacket { @@ -54,4 +52,5 @@ namespace WorldPackets }; } } -#endif + +#endif // AuctionHousePackets_h__ diff --git a/src/server/game/Server/Packets/AuthenticationPackets.cpp b/src/server/game/Server/Packets/AuthenticationPackets.cpp index 2abc68ab90d..2bb1760b31c 100644 --- a/src/server/game/Server/Packets/AuthenticationPackets.cpp +++ b/src/server/game/Server/Packets/AuthenticationPackets.cpp @@ -16,6 +16,7 @@ */ #include "AuthenticationPackets.h" +#include "HmacHash.h" WorldPacket const* WorldPackets::Auth::AuthChallenge::Write() { @@ -138,3 +139,456 @@ WorldPacket const* WorldPackets::Auth::AuthResponse::Write() _worldPacket.FlushBits(); return &_worldPacket; } + +std::string const WorldPackets::Auth::ConnectTo::Haiku("An island of peace\nCorruption is brought ashore\nPandarens will rise\n\0\0", 71); + +uint8 const WorldPackets::Auth::ConnectTo::PiDigits[130] = +{ + 0x31, 0x41, 0x59, 0x26, 0x53, 0x58, 0x97, 0x93, 0x23, 0x84, + 0x62, 0x64, 0x33, 0x83, 0x27, 0x95, 0x02, 0x88, 0x41, 0x97, + 0x16, 0x93, 0x99, 0x37, 0x51, 0x05, 0x82, 0x09, 0x74, 0x94, + 0x45, 0x92, 0x30, 0x78, 0x16, 0x40, 0x62, 0x86, 0x20, 0x89, + 0x98, 0x62, 0x80, 0x34, 0x82, 0x53, 0x42, 0x11, 0x70, 0x67, + 0x98, 0x21, 0x48, 0x08, 0x65, 0x13, 0x28, 0x23, 0x06, 0x64, + 0x70, 0x93, 0x84, 0x46, 0x09, 0x55, 0x05, 0x82, 0x23, 0x17, + 0x25, 0x35, 0x94, 0x08, 0x12, 0x84, 0x81, 0x11, 0x74, 0x50, + 0x28, 0x41, 0x02, 0x70, 0x19, 0x38, 0x52, 0x11, 0x05, 0x55, + 0x96, 0x44, 0x62, 0x29, 0x48, 0x95, 0x49, 0x30, 0x38, 0x19, + 0x64, 0x42, 0x88, 0x10, 0x97, 0x56, 0x65, 0x93, 0x34, 0x46, + 0x12, 0x84, 0x75, 0x64, 0x82, 0x33, 0x78, 0x67, 0x83, 0x16, + 0x52, 0x71, 0x20, 0x19, 0x09, 0x14, 0x56, 0x48, 0x56, 0x69, +}; + +/* +RSA key values + +uint8 const Modulus[] = +{ + 0x5F, 0xD6, 0x80, 0x0B, 0xA7, 0xFF, 0x01, 0x40, 0xC7, 0xBC, 0x8E, 0xF5, 0x6B, 0x27, 0xB0, 0xBF, + 0xF0, 0x1D, 0x1B, 0xFE, 0xDD, 0x0B, 0x1F, 0x3D, 0xB6, 0x6F, 0x1A, 0x48, 0x0D, 0xFB, 0x51, 0x08, + 0x65, 0x58, 0x4F, 0xDB, 0x5C, 0x6E, 0xCF, 0x64, 0xCB, 0xC1, 0x6B, 0x2E, 0xB8, 0x0F, 0x5D, 0x08, + 0x5D, 0x89, 0x06, 0xA9, 0x77, 0x8B, 0x9E, 0xAA, 0x04, 0xB0, 0x83, 0x10, 0xE2, 0x15, 0x4D, 0x08, + 0x77, 0xD4, 0x7A, 0x0E, 0x5A, 0xB0, 0xBB, 0x00, 0x61, 0xD7, 0xA6, 0x75, 0xDF, 0x06, 0x64, 0x88, + 0xBB, 0xB9, 0xCA, 0xB0, 0x18, 0x8B, 0x54, 0x13, 0xE2, 0xCB, 0x33, 0xDF, 0x17, 0xD8, 0xDA, 0xA9, + 0xA5, 0x60, 0xA3, 0x1F, 0x4E, 0x27, 0x05, 0x98, 0x6F, 0xAA, 0xEE, 0x14, 0x3B, 0xF3, 0x97, 0xA8, + 0x12, 0x02, 0x94, 0x0D, 0x84, 0xDC, 0x0E, 0xF1, 0x76, 0x23, 0x95, 0x36, 0x13, 0xF9, 0xA9, 0xC5, + 0x48, 0xDB, 0xDA, 0x86, 0xBE, 0x29, 0x22, 0x54, 0x44, 0x9D, 0x9F, 0x80, 0x7B, 0x07, 0x80, 0x30, + 0xEA, 0xD2, 0x83, 0xCC, 0xCE, 0x37, 0xD1, 0xD1, 0xCF, 0x85, 0xBE, 0x91, 0x25, 0xCE, 0xC0, 0xCC, + 0x55, 0xC8, 0xC0, 0xFB, 0x38, 0xC5, 0x49, 0x03, 0x6A, 0x02, 0xA9, 0x9F, 0x9F, 0x86, 0xFB, 0xC7, + 0xCB, 0xC6, 0xA5, 0x82, 0xA2, 0x30, 0xC2, 0xAC, 0xE6, 0x98, 0xDA, 0x83, 0x64, 0x43, 0x7F, 0x0D, + 0x13, 0x18, 0xEB, 0x90, 0x53, 0x5B, 0x37, 0x6B, 0xE6, 0x0D, 0x80, 0x1E, 0xEF, 0xED, 0xC7, 0xB8, + 0x68, 0x9B, 0x4C, 0x09, 0x7B, 0x60, 0xB2, 0x57, 0xD8, 0x59, 0x8D, 0x7F, 0xEA, 0xCD, 0xEB, 0xC4, + 0x60, 0x9F, 0x45, 0x7A, 0xA9, 0x26, 0x8A, 0x2F, 0x85, 0x0C, 0xF2, 0x19, 0xC6, 0x53, 0x92, 0xF7, + 0xF0, 0xB8, 0x32, 0xCB, 0x5B, 0x66, 0xCE, 0x51, 0x54, 0xB4, 0xC3, 0xD3, 0xD4, 0xDC, 0xB3, 0xEE +}; + +uint8 const Exponent[] = { 0x01, 0x00, 0x01, 0x00 }; + +uint8 const D[] = +{ + 0x79, 0x16, 0xC0, 0xDB, 0xF2, 0x31, 0xCE, 0xA7, 0xEB, 0xFB, 0x91, 0x1F, 0x1E, 0x72, 0x70, 0x25, + 0x0B, 0xF5, 0x7A, 0xE0, 0x88, 0x0B, 0x79, 0xBD, 0xFF, 0xBA, 0x24, 0x62, 0x5A, 0x08, 0x59, 0x2B, + 0x41, 0x7E, 0x4B, 0xF4, 0x9C, 0x3D, 0x4B, 0x5C, 0xEA, 0x6B, 0x21, 0xB8, 0x6E, 0x1C, 0xD1, 0x30, + 0x3E, 0x7C, 0x9C, 0x74, 0xA9, 0x9F, 0x77, 0x31, 0x28, 0xAE, 0x0C, 0x65, 0x18, 0xFF, 0x32, 0x63, + 0x06, 0xD9, 0x33, 0x03, 0xEA, 0x31, 0x26, 0x06, 0x2E, 0xF9, 0x20, 0x81, 0x07, 0xEB, 0x04, 0x42, + 0x22, 0x31, 0x5C, 0x7D, 0x6E, 0x5B, 0x04, 0xF0, 0xBB, 0x4E, 0xF6, 0xB5, 0x9B, 0x96, 0x56, 0xBD, + 0x4C, 0x0E, 0x79, 0xF4, 0x8F, 0x8F, 0xF1, 0xEA, 0x35, 0x5C, 0x98, 0x23, 0x29, 0xA7, 0x7C, 0xAC, + 0xF5, 0xD3, 0x50, 0x2D, 0xDA, 0xB3, 0x5A, 0x34, 0x33, 0x4D, 0x02, 0x9E, 0x39, 0xAD, 0x52, 0x9B, + 0xCE, 0x78, 0xAD, 0x6F, 0x65, 0xD4, 0x81, 0xA3, 0x64, 0x0D, 0x6B, 0x96, 0x29, 0x1C, 0x6C, 0xE3, + 0x1D, 0xDA, 0x4C, 0x5E, 0xAF, 0xD7, 0x14, 0x2A, 0xC9, 0x07, 0x23, 0x04, 0x2F, 0xC4, 0x73, 0x4B, + 0xDC, 0xCC, 0xEE, 0x94, 0xE8, 0xFE, 0xF3, 0x09, 0x88, 0x8E, 0xF6, 0xF4, 0x31, 0x5D, 0xC1, 0xA4, + 0x3B, 0x54, 0x47, 0x6E, 0x03, 0x91, 0x03, 0x12, 0x16, 0x97, 0xC6, 0xF0, 0xAA, 0x38, 0x7D, 0xB3, + 0x9E, 0xC7, 0x7D, 0x9D, 0xEB, 0xCE, 0x8C, 0x56, 0x0C, 0x8A, 0x77, 0x6C, 0x07, 0x17, 0x02, 0xBD, + 0x8F, 0x00, 0x94, 0x1F, 0xB4, 0x96, 0x72, 0x20, 0xBC, 0x51, 0x43, 0x8F, 0xBC, 0xA8, 0xBC, 0xBA, + 0xAF, 0x4F, 0x3C, 0x9A, 0xA2, 0x45, 0x9A, 0x14, 0x5B, 0x96, 0xDF, 0x55, 0x51, 0xC9, 0x5D, 0x68, + 0xB6, 0x5E, 0xC3, 0xFA, 0x00, 0xE2, 0x2B, 0x37, 0x34, 0x66, 0x07, 0xE0, 0xAF, 0xE6, 0x9A, 0x22 +}; +*/ + +uint8 const P[] = +{ + 0x7D, 0xBD, 0xB9, 0xE1, 0x2D, 0xAE, 0x42, 0x56, 0x6E, 0x2B, 0xE2, 0x89, 0xD9, 0xBB, 0x0C, 0x1F, + 0x67, 0x28, 0xC1, 0x4D, 0x91, 0x3C, 0xAD, 0x5F, 0xF0, 0x43, 0x86, 0x5C, 0x27, 0xDC, 0x58, 0xB3, + 0x0E, 0x75, 0x77, 0x78, 0x49, 0x35, 0xE7, 0xE7, 0xDF, 0xFD, 0x74, 0xAB, 0x4E, 0xFE, 0xD3, 0xAB, + 0x6B, 0x96, 0xF7, 0x89, 0xB2, 0x5A, 0x6A, 0x25, 0x03, 0x5A, 0x92, 0x1A, 0xF1, 0xFC, 0x05, 0x4E, + 0xCE, 0xDD, 0x37, 0xA4, 0x02, 0x53, 0x76, 0xCB, 0xC2, 0xD9, 0x63, 0xCB, 0x51, 0x94, 0xEC, 0x5C, + 0x39, 0xCC, 0xB2, 0x17, 0x0C, 0xA3, 0x43, 0x9A, 0xD0, 0x83, 0x27, 0x67, 0x52, 0x64, 0x37, 0x0E, + 0x38, 0xB7, 0x9B, 0xF4, 0x2D, 0xB8, 0x0F, 0x30, 0x72, 0xD3, 0x15, 0xF3, 0x2C, 0x39, 0x55, 0x72, + 0x2C, 0x55, 0x80, 0x63, 0xA0, 0xA1, 0x6F, 0x28, 0xF3, 0xF3, 0x5A, 0x6F, 0x68, 0x59, 0xB3, 0xF3 +}; + +uint8 const Q[] = +{ + 0x0B, 0x1A, 0x13, 0x07, 0x12, 0xEF, 0xDD, 0x97, 0x01, 0x9A, 0x21, 0x7D, 0xFA, 0xA3, 0xB7, 0xE2, + 0x39, 0x2E, 0x04, 0x92, 0x96, 0x45, 0x2A, 0xEB, 0x57, 0x03, 0xAC, 0xB1, 0x83, 0xCD, 0x25, 0x4F, + 0x2C, 0xA9, 0xA1, 0x54, 0x26, 0x54, 0xCF, 0xE6, 0x1B, 0x53, 0x51, 0x3A, 0xC1, 0x15, 0xF4, 0x17, + 0xBB, 0x17, 0x1F, 0x37, 0x66, 0x36, 0x1A, 0xD4, 0xB1, 0x5B, 0x49, 0xA8, 0xF1, 0x02, 0xB0, 0x42, + 0xA9, 0x66, 0xA0, 0xE2, 0x52, 0x2C, 0x8C, 0x89, 0xA2, 0xDD, 0xA6, 0xF1, 0xA3, 0xDF, 0xB6, 0x80, + 0x63, 0xB8, 0x10, 0xDA, 0xDE, 0x84, 0x56, 0xFA, 0xFB, 0x72, 0x65, 0x5E, 0xA3, 0x9C, 0x78, 0x65, + 0xD0, 0x73, 0x07, 0x34, 0x1D, 0xE1, 0x4D, 0x77, 0xE8, 0x00, 0x0F, 0x80, 0x1C, 0x5A, 0x21, 0x55, + 0x0A, 0x8C, 0xF4, 0x93, 0xF5, 0xF8, 0x40, 0xF2, 0x40, 0xEA, 0x52, 0x12, 0x40, 0xF0, 0xBF, 0xFA +}; + +uint8 const DP[] = +{ + 0xE1, 0xA6, 0x22, 0xAB, 0xFF, 0x57, 0x83, 0x45, 0x3F, 0x93, 0x76, 0xC8, 0xFA, 0xD9, 0x17, 0xE1, + 0x49, 0x73, 0xC2, 0x13, 0x28, 0x0B, 0x1F, 0xE2, 0x9A, 0xF4, 0x7F, 0x7C, 0x37, 0x56, 0xA1, 0xDF, + 0x51, 0x97, 0x2F, 0x15, 0x10, 0x97, 0xCD, 0x2A, 0x40, 0x09, 0xFC, 0x0A, 0xC3, 0x3F, 0x88, 0x86, + 0xA9, 0x51, 0x13, 0xE1, 0x76, 0xCF, 0xA8, 0x37, 0x9A, 0x91, 0x3B, 0xD0, 0x70, 0xA1, 0xD7, 0x03, + 0x71, 0x59, 0x6C, 0xB3, 0x41, 0xB8, 0x32, 0x68, 0x56, 0xC8, 0xB8, 0xD1, 0xF9, 0x1D, 0x04, 0xC5, + 0x13, 0xB5, 0x8E, 0x57, 0x73, 0x02, 0x97, 0x7B, 0x33, 0x60, 0x68, 0xA9, 0xC2, 0x40, 0x96, 0x3C, + 0x57, 0x4E, 0x4F, 0xC0, 0xAB, 0x21, 0x5C, 0xBA, 0x7D, 0x65, 0xAA, 0x1B, 0xD6, 0x43, 0x06, 0xCE, + 0x3E, 0x0C, 0xB9, 0xB2, 0x82, 0xB0, 0xC9, 0x54, 0x59, 0x32, 0xC5, 0x88, 0x08, 0x9C, 0x9B, 0xBF +}; + +uint8 const DQ[] = +{ + 0xE3, 0xB1, 0xED, 0x52, 0xEF, 0xE6, 0x88, 0x40, 0x50, 0x89, 0x4C, 0x99, 0xE5, 0xF7, 0xED, 0x03, + 0x1C, 0x54, 0x11, 0x24, 0x2F, 0x9D, 0xE8, 0xE6, 0x39, 0xFA, 0x19, 0xF4, 0x06, 0x55, 0x0B, 0x8B, + 0x95, 0xC8, 0xB1, 0xE2, 0x7C, 0x75, 0x3B, 0x2A, 0x40, 0xC3, 0xE7, 0xE0, 0x25, 0x18, 0xBF, 0xB5, + 0x03, 0x1B, 0x5A, 0x57, 0x92, 0x3C, 0x85, 0x7D, 0x7F, 0x43, 0x56, 0x1F, 0x1E, 0x80, 0xC3, 0xBA, + 0xF0, 0x53, 0xD7, 0x6A, 0xD0, 0xF2, 0xDD, 0x9C, 0xC6, 0x53, 0xE7, 0xB4, 0xD3, 0x9D, 0xAB, 0xBF, + 0xE0, 0x97, 0x50, 0x92, 0x23, 0xB9, 0xB7, 0xDC, 0xAA, 0xC4, 0x20, 0x93, 0x5A, 0xF5, 0xDE, 0x76, + 0x28, 0x93, 0x91, 0x44, 0x1E, 0x4C, 0x15, 0x2F, 0x7F, 0x45, 0x3C, 0x3B, 0x7D, 0x36, 0x3B, 0x24, + 0xC7, 0x8C, 0x65, 0x43, 0xAE, 0x65, 0x84, 0xBC, 0xF9, 0x76, 0x4E, 0x3C, 0x44, 0x05, 0xBC, 0xFA +}; + +uint8 const InverseQ[] = +{ + 0x63, 0xC1, 0x14, 0x2B, 0x57, 0x0B, 0x8A, 0x3C, 0x27, 0xDB, 0x96, 0x82, 0x27, 0xEB, 0xF6, 0x45, + 0x6D, 0x07, 0x50, 0xE8, 0x4A, 0xD4, 0xB6, 0x7A, 0x3C, 0x8B, 0x4D, 0x65, 0xF0, 0x50, 0x70, 0x84, + 0x71, 0x2B, 0xC6, 0x6D, 0x28, 0x2D, 0x76, 0x38, 0x73, 0x93, 0xDB, 0x44, 0xD7, 0xC0, 0x7F, 0xD9, + 0x57, 0x18, 0x28, 0x57, 0xF1, 0x13, 0x38, 0xA4, 0x91, 0x67, 0x1E, 0x13, 0x73, 0x55, 0xFC, 0x7B, + 0xAF, 0x50, 0xFA, 0xFD, 0x16, 0x12, 0x6F, 0xA4, 0x95, 0x15, 0x9C, 0x07, 0x18, 0xA6, 0x46, 0xFD, + 0xB3, 0xCF, 0xA5, 0x0E, 0x05, 0x30, 0xEC, 0x2C, 0xCD, 0x62, 0xDD, 0x6F, 0xB1, 0xFE, 0x6C, 0x05, + 0x2F, 0x11, 0xA6, 0xA0, 0x98, 0xAC, 0x9B, 0x15, 0xF0, 0x04, 0xC4, 0x7B, 0x79, 0xAA, 0x51, 0x25, + 0x2A, 0x84, 0x73, 0xE6, 0x77, 0x47, 0xA3, 0xEB, 0xCF, 0x6D, 0xC8, 0x96, 0x3A, 0x1B, 0x02, 0x52 +}; + +uint8 const WherePacketHmac[] = +{ + 0x2C, 0x1F, 0x1D, 0x80, 0xC3, 0x8C, 0x23, 0x64, 0xDA, 0x90, 0xCA, 0x8E, 0x2C, 0xFC, 0x0C, 0xCE, + 0x09, 0xD3, 0x62, 0xF9, 0xF3, 0x8B, 0xBE, 0x9F, 0x19, 0xEF, 0x58, 0xA1, 0x1C, 0x34, 0x14, 0x41, + 0x3F, 0x23, 0xFD, 0xD3, 0xE8, 0x14, 0xEC, 0x2A, 0xFD, 0x4F, 0x95, 0xBA, 0x30, 0x7E, 0x56, 0x5D, + 0x83, 0x95, 0x81, 0x69, 0xB0, 0x5A, 0xB4, 0x9D, 0xA8, 0x55, 0xFF, 0xFC, 0xEE, 0x58, 0x0A, 0x2F +}; + +WorldPackets::Auth::ConnectTo::ConnectTo() : ServerPacket(SMSG_REDIRECT_CLIENT, 8 + 4 + 256 + 1) +{ + HexStrToByteArray("F41DCB2D728CF3337A4FF338FA89DB01BBBE9C3B65E9DA96268687353E48B94C", Payload.PanamaKey); + Payload.Adler32 = 0xA0A66C10; + + p.SetBinary(P, 128); + q.SetBinary(Q, 128); + dmp1.SetBinary(DP, 128); + dmq1.SetBinary(DQ, 128); + iqmp.SetBinary(InverseQ, 128); +} + +WorldPacket const* WorldPackets::Auth::ConnectTo::Write() +{ + ByteBuffer payload; + uint16 port = Payload.Where.port(); + uint8 address[16] = { 0 }; + uint32 addressType = 3; + if (Payload.Where.address().is_v4()) + { + memcpy(address, Payload.Where.address().to_v4().to_bytes().data(), 4); + addressType = 1; + } + else + { + memcpy(address, Payload.Where.address().to_v6().to_bytes().data(), 16); + addressType = 2; + } + + HmacSha1 hmacHash(64, WherePacketHmac); + hmacHash.UpdateData(address, 16); + hmacHash.UpdateData((uint8* const)&addressType, 4); + hmacHash.UpdateData((uint8* const)&port, 2); + hmacHash.UpdateData((uint8* const)Haiku.c_str(), 71); + hmacHash.UpdateData(Payload.PanamaKey, 32); + hmacHash.UpdateData(PiDigits, 108); + hmacHash.UpdateData(&Payload.XorMagic, 1); + hmacHash.Finalize(); + + uint8* hmac = hmacHash.GetDigest(); + + payload << uint8(PiDigits[10]); + payload << uint8(Haiku[66]); + payload << uint8(Haiku[12]); + payload << uint8(PiDigits[89]); + payload << uint8(PiDigits[50]); + payload << uint8(Haiku[48]); + payload << uint8(PiDigits[32]); + payload << uint8(PiDigits[0]); + payload << uint8(Payload.PanamaKey[22]); + payload << uint8(PiDigits[90]); + payload << uint8(Payload.PanamaKey[16]); + payload << uint8(PiDigits[69]); + payload << uint8(Haiku[39]); + payload << uint8(PiDigits[107]); + payload << uint8(address[7]); + payload << uint8(hmac[2]); + payload << uint8(PiDigits[55]); + payload << uint8(Haiku[13]); + payload << uint8(PiDigits[34]); + payload << uint8(Haiku[51]); + payload << uint8(PiDigits[37]); + payload << uint8(hmac[11]); + payload << uint8(address[8]); + payload << uint8(Haiku[10]); + payload << uint8(Haiku[47]); + payload << uint8(Haiku[29]); + payload << uint8(PiDigits[93]); + payload << uint8(hmac[5]); + payload << uint8(hmac[14]); + payload << uint8(PiDigits[71]); + payload << uint8(PiDigits[3]); + payload << uint8(PiDigits[103]); + payload << uint8(PiDigits[80]); + payload << uint8(Haiku[59]); + payload << uint8(Haiku[61]); + payload << uint8(PiDigits[1]); + payload << uint8(Haiku[69]); + payload << uint8(Payload.PanamaKey[11]); + payload << uint8(Haiku[45]); + payload << uint8(PiDigits[52]); + payload << uint8(PiDigits[43]); + payload << uint8(PiDigits[81]); + payload << uint8(Payload.PanamaKey[4]); + payload << uint8(Payload.PanamaKey[10]); + payload << uint8(Haiku[37]); + payload << uint8(Haiku[56]); + payload << uint8(hmac[12]); + payload << uint8(PiDigits[97]); + payload << uint8(Haiku[32]); + payload << uint8(PiDigits[17]); + payload << uint8(Payload.XorMagic); + payload << uint8(PiDigits[26]); + payload << uint8(PiDigits[47]); + payload << uint8(Haiku[60]); + payload << uint8(Haiku[2]); + payload << uint8(Haiku[1]); + payload << uint8(hmac[3]); + payload << uint8(PiDigits[64]); + payload << uint8(PiDigits[18]); + payload << uint8(Haiku[53]); + payload << uint8(PiDigits[79]); + payload << uint8(Payload.PanamaKey[29]); + payload << uint8(Haiku[43]); + payload << uint8(PiDigits[104]); + payload << uint8(PiDigits[56]); + payload << uint8(Payload.PanamaKey[31]); + payload << uint8(hmac[10]); + payload << uint8(PiDigits[94]); + payload << uint8(PiDigits[22]); + payload << uint8(hmac[8]); + payload << uint8(PiDigits[77]); + payload << uint8(address[13]); + payload << uint8(PiDigits[36]); + payload << uint8(PiDigits[101]); + payload << uint8(PiDigits[6]); + payload << uint8(PiDigits[78]); + payload << uint8(hmac[15]); + payload << uint8(PiDigits[88]); + payload << uint8(PiDigits[59]); + payload << uint8(PiDigits[67]); + payload << uint8(Payload.PanamaKey[1]); + payload << uint8(Payload.PanamaKey[30]); + payload << uint8(PiDigits[95]); + payload << uint8(PiDigits[4]); + payload << uint8(Payload.PanamaKey[15]); + payload << uint8(Haiku[64]); + payload << uint8(PiDigits[86]); + payload << uint8(Haiku[35]); + payload << uint8(address[10]); + payload << uint8(Payload.PanamaKey[5]); + payload << uint8(PiDigits[74]); + payload << uint8(PiDigits[60]); + payload << uint8(Haiku[40]); + payload << uint8(PiDigits[105]); + payload << uint8(Payload.PanamaKey[25]); + payload << uint8(Haiku[57]); + payload << uint8(PiDigits[84]); + payload << uint8(PiDigits[70]); + payload << uint8(PiDigits[23]); + payload << uint8(Haiku[11]); + payload << uint8(hmac[16]); + payload << uint8(PiDigits[57]); + payload << uint8(Haiku[6]); + payload << uint8(Haiku[8]); + payload << uint8(Haiku[65]); + payload << uint8(Haiku[28]); + payload << uint8(Payload.PanamaKey[13]); + payload << uint8(PiDigits[91]); + payload << uint8(PiDigits[62]); + payload << uint8(PiDigits[7]); + payload << uint8(PiDigits[40]); + payload << uint8(Haiku[23]); + payload << uint8(PiDigits[41]); + payload << uint8(Payload.PanamaKey[28]); + payload << uint8(PiDigits[25]); + payload << uint8(PiDigits[38]); + payload << uint32(Payload.Adler32); + payload << uint8(Haiku[30]); + payload << uint8(PiDigits[15]); + payload << uint8(hmac[18]); + payload << uint8(PiDigits[13]); + payload << uint8(PiDigits[27]); + payload << uint8(Haiku[52]); + payload << uint8(PiDigits[68]); + payload << uint8(Haiku[58]); + payload << uint8(Haiku[34]); + payload << uint8(PiDigits[87]); + payload << uint8(PiDigits[72]); + payload << uint8(Haiku[42]); + payload << uint8(PiDigits[24]); + payload << uint8(hmac[1]); + payload << uint8(Haiku[18]); + payload << uint8(Haiku[25]); + payload << uint8(Payload.PanamaKey[24]); + payload << uint8(Haiku[27]); + payload << uint8(hmac[9]); + payload << uint8(hmac[4]); + payload << uint8(Haiku[26]); + payload << uint8(PiDigits[45]); + payload << uint8(Haiku[9]); + payload << uint8(address[6]); + payload << uint8(PiDigits[73]); + payload << uint8(Haiku[20]); + payload << uint8(Haiku[67]); + payload << uint8(Payload.PanamaKey[27]); + payload << uint8(address[1]); + payload << uint8(PiDigits[33]); + payload << uint8(hmac[0]); + payload << uint8(Haiku[3]); + payload << uint8(PiDigits[54]); + payload << uint8(hmac[17]); + payload << uint8(PiDigits[35]); + payload << uint8(address[4]); + payload << uint8(Haiku[46]); + payload << uint8(Payload.PanamaKey[2]); + payload << uint8(address[12]); + payload << uint8(Haiku[68]); + payload << uint8(Haiku[24]); + payload << uint8(PiDigits[48]); + payload << uint8(port & 0xFF); + payload << uint8(Haiku[14]); + payload << uint8(Payload.PanamaKey[12]); + payload << uint8(Haiku[38]); + payload << uint8(PiDigits[53]); + payload << uint8(PiDigits[49]); + payload << uint8(Haiku[4]); + payload << uint8(PiDigits[63]); + payload << uint8((port >> 8) & 0xFF); + payload << uint8(Haiku[0]); + payload << uint8(PiDigits[76]); + payload << uint8(PiDigits[100]); + payload << uint8(Payload.PanamaKey[14]); + payload << uint8(Payload.PanamaKey[6]); + payload << uint8(Haiku[16]); + payload << uint8(PiDigits[65]); + payload << uint8(PiDigits[14]); + payload << uint8(Haiku[19]); + payload << uint8(PiDigits[66]); + payload << uint8(PiDigits[28]); + payload << uint8(Payload.PanamaKey[18]); + payload << uint8(PiDigits[102]); + payload << uint8(PiDigits[51]); + payload << uint8(Haiku[63]); + payload << uint8(address[2]); + payload << uint8(hmac[6]); + payload << uint8(Haiku[21]); + payload << uint8(Haiku[15]); + payload << uint8(Payload.PanamaKey[21]); + payload << uint8(Haiku[41]); + payload << uint8(Haiku[5]); + payload << uint8(Payload.PanamaKey[7]); + payload << uint8(Payload.PanamaKey[20]); + payload << uint8(PiDigits[46]); + payload << uint8(PiDigits[44]); + payload << uint8(PiDigits[96]); + payload << uint8(PiDigits[99]); + payload << uint8(hmac[13]); + payload << uint8(Haiku[70]); + payload << uint8(addressType); + payload << uint8(Payload.PanamaKey[17]); + payload << uint8(Payload.PanamaKey[23]); + payload << uint8(PiDigits[58]); + payload << uint8(PiDigits[2]); + payload << uint8(PiDigits[61]); + payload << uint8(PiDigits[19]); + payload << uint8(PiDigits[83]); + payload << uint8(PiDigits[42]); + payload << uint8(PiDigits[29]); + payload << uint8(Payload.PanamaKey[26]); + payload << uint8(PiDigits[5]); + payload << uint8(PiDigits[85]); + payload << uint8(Haiku[50]); + payload << uint8(hmac[19]); + payload << uint8(Haiku[31]); + payload << uint8(address[14]); + payload << uint8(Payload.PanamaKey[0]); + payload << uint8(PiDigits[98]); + payload << uint8(Haiku[17]); + payload << uint8(Haiku[55]); + payload << uint8(Haiku[54]); + payload << uint8(PiDigits[20]); + payload << uint8(PiDigits[21]); + payload << uint8(Payload.PanamaKey[3]); + payload << uint8(Payload.PanamaKey[19]); + payload << uint8(address[15]); + payload << uint8(PiDigits[12]); + payload << uint8(Haiku[49]); + payload << uint8(PiDigits[9]); + payload << uint8(hmac[7]); + payload << uint8(Payload.PanamaKey[9]); + payload << uint8(PiDigits[8]); + payload << uint8(PiDigits[11]); + payload << uint8(address[9]); + payload << uint8(Haiku[44]); + payload << uint8(address[3]); + payload << uint8(Haiku[33]); + payload << uint8(address[11]); + payload << uint8(Haiku[22]); + payload << uint8(address[5]); + payload << uint8(Haiku[36]); + payload << uint8(PiDigits[82]); + payload << uint8(PiDigits[16]); + payload << uint8(PiDigits[75]); + payload << uint8(Haiku[7]); + payload << uint8(PiDigits[92]); + payload << uint8(Payload.PanamaKey[8]); + payload << uint8(Haiku[62]); + payload << uint8(PiDigits[106]); + payload << uint8(address[0]); + payload << uint8(PiDigits[31]); + payload << uint8(PiDigits[39]); + payload << uint8(PiDigits[30]); + + BigNumber bnData; + bnData.SetBinary(payload.contents(), payload.size()); + + BigNumber m1 = (bnData % p).ModExp(dmp1, p); + BigNumber m2 = (bnData % q).ModExp(dmq1, q); + BigNumber h = (iqmp * (m1 - m2)) % p; + // Be sure to use the positive remainder + if (h.IsNegative()) + h += p; + + BigNumber m = m2 + h * q; + + _worldPacket << uint64(Key); + _worldPacket << uint32(Serial); + _worldPacket.append(m.AsByteArray(256).get(), 256); + _worldPacket << uint8(Con); + return &_worldPacket; +} + +void WorldPackets::Auth::AuthContinuedSession::Read() +{ + _worldPacket >> DosResponse; + _worldPacket >> Key; + _worldPacket.read(Digest, SHA_DIGEST_LENGTH); +} diff --git a/src/server/game/Server/Packets/AuthenticationPackets.h b/src/server/game/Server/Packets/AuthenticationPackets.h index eff055f7d1d..e24c06396e0 100644 --- a/src/server/game/Server/Packets/AuthenticationPackets.h +++ b/src/server/game/Server/Packets/AuthenticationPackets.h @@ -21,7 +21,11 @@ #include "Packet.h" #include "ObjectMgr.h" #include "Util.h" -#include <SHA1.h> +#include "BigNumber.h" +#include "SHA1.h" +#include <boost/asio/ip/tcp.hpp> + +using boost::asio::ip::tcp; namespace WorldPackets { @@ -42,7 +46,7 @@ namespace WorldPackets class AuthSession final : public ClientPacket { public: - AuthSession(WorldPacket&& packet) : ClientPacket(std::move(packet)) + AuthSession(WorldPacket&& packet) : ClientPacket(CMSG_AUTH_SESSION, std::move(packet)) { memset(Digest, 0, SHA_DIGEST_LENGTH); } @@ -101,7 +105,7 @@ namespace WorldPackets uint32 TimeRested = 0; ///< affects the return value of the GetBillingTimeRested() client API call, it is the number of seconds you have left until the experience points and loot you receive from creatures and quests is reduced. It is only used in the Asia region in retail, it's not implemented in TC and will probably never be. uint8 TimeOptions = 0; ///< controls the behavior of the client regarding billing, used in Asia realms, as they don't have monthly subscriptions, possible values are in @ref BillingPlanFlags. It is not currently implemented and will probably never be. - uint32 VirtualRealmAddress = 0; ///< a special identifier made from the Index, BattleGroup and Region. @todo implement + uint32 VirtualRealmAddress = 0; ///< a special identifier made from the Index, BattleGroup and Region. uint32 RealmNamesCount = 0; ///< the number of realms connected to this one (inclusive). @todo implement uint32 TimeSecondsUntilPCKick = 0; ///< @todo research uint32 CurrencyID = 0; ///< this is probably used for the ingame shop. @todo implement @@ -133,6 +137,60 @@ namespace WorldPackets Optional<AuthWaitInfo> WaitInfo; ///< contains the queue wait information in case the account is in the login queue. uint8 Result = 0; ///< the result of the authentication process, it is AUTH_OK if it succeeded and the account is ready to log in. It can also be AUTH_WAIT_QUEUE if the account entered the login queue (Queued, QueuePos), possible values are @ref ResponseCodes }; + + class ConnectTo final : public ServerPacket + { + static std::string const Haiku; + static uint8 const PiDigits[130]; + + struct ConnectPayload + { + tcp::endpoint Where; + uint32 Adler32 = 0; + uint8 XorMagic = 0x2A; + uint8 PanamaKey[32]; + }; + + public: + ConnectTo(); + + WorldPacket const* Write() override; + + uint64 Key = 0; + uint32 Serial = 0; + ConnectPayload Payload; + uint8 Con = 0; + + private: + BigNumber p; + BigNumber q; + BigNumber dmp1; + BigNumber dmq1; + BigNumber iqmp; + }; + + class AuthContinuedSession final : public ClientPacket + { + public: + AuthContinuedSession(WorldPacket&& packet) : ClientPacket(CMSG_AUTH_CONTINUED_SESSION, std::move(packet)) + { + memset(Digest, 0, SHA_DIGEST_LENGTH); + } + + void Read() override; + + uint64 DosResponse = 0; + uint64 Key = 0; + uint8 Digest[SHA_DIGEST_LENGTH]; + }; + + class ResumeComms final : public ServerPacket + { + public: + ResumeComms() : ServerPacket(SMSG_RESUME_COMMS, 0) { } + + WorldPacket const* Write() override { return &_worldPacket; } + }; } } diff --git a/src/server/game/Server/Packets/BattlegroundPackets.cpp b/src/server/game/Server/Packets/BattlegroundPackets.cpp new file mode 100644 index 00000000000..8a1bec1173b --- /dev/null +++ b/src/server/game/Server/Packets/BattlegroundPackets.cpp @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2008-2014 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 "BattlegroundPackets.h" + +WorldPacket const* WorldPackets::Battleground::PVPSeason::Write() +{ + _worldPacket << uint32(CurrentSeason); + _worldPacket << uint32(PreviousSeason); + + return &_worldPacket; +} diff --git a/src/server/game/Server/Packets/BattlegroundPackets.h b/src/server/game/Server/Packets/BattlegroundPackets.h new file mode 100644 index 00000000000..77dc8238438 --- /dev/null +++ b/src/server/game/Server/Packets/BattlegroundPackets.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2008-2014 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 BattlegroundPackets_h__ +#define BattlegroundPackets_h__ + +#include "Packet.h" + +namespace WorldPackets +{ + namespace Battleground + { + class PVPSeason final : public ServerPacket + { + public: + PVPSeason() : ServerPacket(SMSG_PVP_SEASON, 8) { } + + WorldPacket const* Write() override; + + uint32 PreviousSeason = 0; + uint32 CurrentSeason = 0; + }; + } +} + +#endif // BattlegroundPackets_h__ diff --git a/src/server/game/Server/Packets/CharacterPackets.cpp b/src/server/game/Server/Packets/CharacterPackets.cpp index 17ccf4f4316..7f6fefbf058 100644 --- a/src/server/game/Server/Packets/CharacterPackets.cpp +++ b/src/server/game/Server/Packets/CharacterPackets.cpp @@ -17,6 +17,7 @@ #include "CharacterPackets.h" #include "ObjectMgr.h" +#include "World.h" WorldPackets::Character::CharEnumResult::CharacterInfo::CharacterInfo(Field* fields) { @@ -123,9 +124,6 @@ WorldPackets::Character::CharEnumResult::CharacterInfo::CharacterInfo(Field* fie } } -WorldPackets::Character::CharEnumResult::CharEnumResult() - : ServerPacket(SMSG_CHAR_ENUM) { } - WorldPacket const* WorldPackets::Character::CharEnumResult::Write() { _worldPacket.reserve(9 + Characters.size() * sizeof(CharacterInfo) + FactionChangeRestrictions.size() * sizeof(RestrictedFactionChangeRuleInfo)); @@ -186,12 +184,6 @@ WorldPacket const* WorldPackets::Character::CharEnumResult::Write() return &_worldPacket; } -WorldPackets::Character::CharacterCreate::CharacterCreate(WorldPacket&& packet) - : ClientPacket(std::move(packet)) -{ - ASSERT(_worldPacket.GetOpcode() == CMSG_CHAR_CREATE); -} - void WorldPackets::Character::CharacterCreate::Read() { CreateInfo.reset(new CharacterCreateInfo()); @@ -211,39 +203,47 @@ void WorldPackets::Character::CharacterCreate::Read() _worldPacket >> CreateInfo->TemplateSet.value; } -WorldPackets::Character::CharacterCreateResponse::CharacterCreateResponse() - : ServerPacket(SMSG_CHAR_CREATE, 1) { } - WorldPacket const* WorldPackets::Character::CharacterCreateResponse::Write() { _worldPacket << uint8(Code); return &_worldPacket; } -WorldPackets::Character::CharacterDelete::CharacterDelete(WorldPacket&& packet) - : ClientPacket(std::move(packet)) -{ - ASSERT(_worldPacket.GetOpcode() == CMSG_CHAR_DELETE); -} - void WorldPackets::Character::CharacterDelete::Read() { _worldPacket >> Guid; } -WorldPackets::Character::CharacterDeleteResponse::CharacterDeleteResponse() - : ServerPacket(SMSG_CHAR_DELETE, 1) { } - WorldPacket const* WorldPackets::Character::CharacterDeleteResponse::Write() { _worldPacket << uint8(Code); return &_worldPacket; } -WorldPackets::Character::UndeleteCharacter::UndeleteCharacter(WorldPacket&& packet) - : ClientPacket(std::move(packet)) +void WorldPackets::Character::GenerateRandomCharacterName::Read() { - ASSERT(_worldPacket.GetOpcode() == CMSG_UNDELETE_CHARACTER); + _worldPacket >> Race; + _worldPacket >> Sex; +} + +WorldPacket const* WorldPackets::Character::GenerateRandomCharacterNameResult::Write() +{ + _worldPacket.WriteBit(Success); + _worldPacket.WriteBits(Name.length(), 6); + _worldPacket.WriteString(Name); + return &_worldPacket; +} + +void WorldPackets::Character::ReorderCharacters::Read() +{ + uint32 count = std::min<uint32>(_worldPacket.ReadBits(9), sWorld->getIntConfig(CONFIG_CHARACTERS_PER_REALM)); + while (count--) + { + ReorderInfo reorderInfo; + _worldPacket >> reorderInfo.PlayerGUID; + _worldPacket >> reorderInfo.NewPosition; + Entries.emplace_back(reorderInfo); + } } void WorldPackets::Character::UndeleteCharacter::Read() @@ -253,9 +253,6 @@ void WorldPackets::Character::UndeleteCharacter::Read() _worldPacket >> UndeleteInfo->CharacterGuid; } -WorldPackets::Character::UndeleteCharacterResponse::UndeleteCharacterResponse() - : ServerPacket(SMSG_UNDELETE_CHARACTER_RESPONSE, 26) { } - WorldPacket const* WorldPackets::Character::UndeleteCharacterResponse::Write() { ASSERT(UndeleteInfo); @@ -265,9 +262,6 @@ WorldPacket const* WorldPackets::Character::UndeleteCharacterResponse::Write() return &_worldPacket; } -WorldPackets::Character::UndeleteCooldownStatusResponse::UndeleteCooldownStatusResponse() - : ServerPacket(SMSG_UNDELETE_COOLDOWN_STATUS_RESPONSE, 9) { } - WorldPacket const* WorldPackets::Character::UndeleteCooldownStatusResponse::Write() { _worldPacket.WriteBit(OnCooldown); @@ -276,12 +270,6 @@ WorldPacket const* WorldPackets::Character::UndeleteCooldownStatusResponse::Writ return &_worldPacket; } -WorldPackets::Character::PlayerLogin::PlayerLogin(WorldPacket&& packet) - : ClientPacket(std::move(packet)) -{ - ASSERT(_worldPacket.GetOpcode() == CMSG_PLAYER_LOGIN); -} - void WorldPackets::Character::PlayerLogin::Read() { _worldPacket >> Guid; @@ -295,3 +283,66 @@ WorldPacket const* WorldPackets::Character::LoginVerifyWorld::Write() _worldPacket << uint32(Reason); return &_worldPacket; } + +WorldPacket const* WorldPackets::Character::LogoutResponse::Write() +{ + _worldPacket << int32(LogoutResult); + _worldPacket.WriteBit(Instant); + _worldPacket.FlushBits(); + return &_worldPacket; +} + +WorldPacket const* WorldPackets::Character::LogoutComplete::Write() +{ + _worldPacket << SwitchToCharacter; + return &_worldPacket; +} + +void WorldPackets::Character::LoadingScreenNotify::Read() +{ + _worldPacket >> MapID; + Showing = _worldPacket.ReadBit(); +} + +void WorldPackets::Character::QueryPlayerName::Read() +{ + _worldPacket >> Player; + + Hint.VirtualRealmAddress.HasValue = _worldPacket.ReadBit(); + Hint.NativeRealmAddress.HasValue = _worldPacket.ReadBit(); + + if (Hint.VirtualRealmAddress.HasValue) + _worldPacket >> Hint.VirtualRealmAddress.value; + + if (Hint.NativeRealmAddress.HasValue) + _worldPacket >> Hint.NativeRealmAddress.value; +} + +WorldPacket const* WorldPackets::Character::PlayerNameResponse::Write() +{ + _worldPacket << Result; + _worldPacket << Player; + + if (Result == 0) + { + _worldPacket.WriteBits(Data.Name.length(), 7); + + for (int i = 0; i < MAX_DECLINED_NAME_CASES; ++i) + _worldPacket.WriteBits(Data.DeclinedNames.name[i].length(), 7); + + for (int i = 0; i < MAX_DECLINED_NAME_CASES; ++i) + _worldPacket.WriteString(Data.DeclinedNames.name[i]); + + _worldPacket << Data.AccountID; + _worldPacket << Data.BnetAccountID; + _worldPacket << Data.GuidActual; + _worldPacket << Data.VirtualRealmAddress; + _worldPacket << Data.Race; + _worldPacket << Data.Sex; + _worldPacket << Data.ClassID; + _worldPacket << Data.Level; + _worldPacket.WriteString(Data.Name); + } + + return &_worldPacket; +} diff --git a/src/server/game/Server/Packets/CharacterPackets.h b/src/server/game/Server/Packets/CharacterPackets.h index 465b1ee8ffb..f2bec8e2510 100644 --- a/src/server/game/Server/Packets/CharacterPackets.h +++ b/src/server/game/Server/Packets/CharacterPackets.h @@ -28,9 +28,9 @@ namespace WorldPackets struct CharacterCreateInfo { /// User specified variables - uint8 Race = 0; - uint8 Class = 0; - uint8 Sex = GENDER_NONE; + uint8 Race = RACE_NONE; + uint8 Class = CLASS_NONE; + uint8 Sex = GENDER_NONE; uint8 Skin = 0; uint8 Face = 0; uint8 HairStyle = 0; @@ -62,7 +62,7 @@ namespace WorldPackets struct CharacterFactionChangeInfo : public CharacterCustomizeInfo { - uint8 Race = 0; + uint8 Race = RACE_NONE; }; struct CharacterUndeleteInfo @@ -139,7 +139,7 @@ namespace WorldPackets uint8 Race = 0; }; - CharEnumResult(); + CharEnumResult() : ServerPacket(SMSG_CHAR_ENUM) { } WorldPacket const* Write() override; @@ -153,7 +153,7 @@ namespace WorldPackets class CharacterCreate final : public ClientPacket { public: - CharacterCreate(WorldPacket&& packet); + CharacterCreate(WorldPacket&& packet) : ClientPacket(CMSG_CHAR_CREATE, std::move(packet)) { } void Read() override; @@ -176,7 +176,7 @@ namespace WorldPackets class CharacterCreateResponse final : public ServerPacket { public: - CharacterCreateResponse(); + CharacterCreateResponse() : ServerPacket(SMSG_CHAR_CREATE, 1) { } WorldPacket const* Write() override; @@ -186,7 +186,7 @@ namespace WorldPackets class CharacterDelete final : public ClientPacket { public: - CharacterDelete(WorldPacket&& packet); + CharacterDelete(WorldPacket&& packet): ClientPacket(CMSG_CHAR_DELETE, std::move(packet)) { } void Read() override; @@ -196,17 +196,55 @@ namespace WorldPackets class CharacterDeleteResponse final : public ServerPacket { public: - CharacterDeleteResponse(); + CharacterDeleteResponse(): ServerPacket(SMSG_CHAR_DELETE, 1) { } WorldPacket const* Write() override; uint8 Code = 0; ///< Result code @see enum ResponseCodes }; + class GenerateRandomCharacterName final : public ClientPacket + { + public: + GenerateRandomCharacterName(WorldPacket&& packet) : ClientPacket(CMSG_RANDOMIZE_CHAR_NAME, std::move(packet)) { } + + void Read() override; + + uint8 Sex = 0; + uint8 Race = 0; + }; + + class GenerateRandomCharacterNameResult final : public ServerPacket + { + public: + GenerateRandomCharacterNameResult(): ServerPacket(SMSG_RANDOMIZE_CHAR_NAME, 20) { } + + WorldPacket const* Write() override; + + std::string Name; + bool Success = false; + }; + + class ReorderCharacters final : public ClientPacket + { + public: + struct ReorderInfo + { + ObjectGuid PlayerGUID; + uint8 NewPosition = 0; + }; + + ReorderCharacters(WorldPacket&& packet) : ClientPacket(CMSG_REORDER_CHARACTERS, std::move(packet)) { } + + void Read() override; + + std::list<ReorderInfo> Entries; + }; + class UndeleteCharacter final : public ClientPacket { public: - UndeleteCharacter(WorldPacket&& packet); + UndeleteCharacter(WorldPacket&& packet) : ClientPacket(CMSG_UNDELETE_CHARACTER, std::move(packet)) { } void Read() override; @@ -220,7 +258,7 @@ namespace WorldPackets class UndeleteCharacterResponse final : public ServerPacket { public: - UndeleteCharacterResponse(); + UndeleteCharacterResponse() : ServerPacket(SMSG_UNDELETE_CHARACTER_RESPONSE, 26) { } WorldPacket const* Write() override; @@ -235,7 +273,7 @@ namespace WorldPackets class UndeleteCooldownStatusResponse final : public ServerPacket { public: - UndeleteCooldownStatusResponse(); + UndeleteCooldownStatusResponse() : ServerPacket(SMSG_UNDELETE_COOLDOWN_STATUS_RESPONSE, 9) { } WorldPacket const* Write() override; @@ -247,7 +285,7 @@ namespace WorldPackets class PlayerLogin final : public ClientPacket { public: - PlayerLogin(WorldPacket&& packet); + PlayerLogin(WorldPacket&& packet) : ClientPacket(CMSG_PLAYER_LOGIN, std::move(packet)) { } void Read() override; @@ -266,6 +304,106 @@ namespace WorldPackets Position Pos; uint32 Reason = 0; }; + + class LogoutRequest final : public ClientPacket + { + public: + LogoutRequest(WorldPacket&& packet) : ClientPacket(CMSG_LOGOUT_REQUEST, std::move(packet)) { } + + void Read() override { } + }; + + class LogoutResponse final : public ServerPacket + { + public: + LogoutResponse() : ServerPacket(SMSG_LOGOUT_RESPONSE, 4 + 1) { } + + WorldPacket const* Write() override; + + int32 LogoutResult = 0; + bool Instant = false; + }; + + class LogoutComplete final : public ServerPacket + { + public: + LogoutComplete() : ServerPacket(SMSG_LOGOUT_COMPLETE, 2) { } + + WorldPacket const* Write() override; + + ObjectGuid SwitchToCharacter; + }; + + class LogoutCancel final : public ClientPacket + { + public: + LogoutCancel(WorldPacket&& packet) : ClientPacket(CMSG_LOGOUT_CANCEL, std::move(packet)) { } + + void Read() override { } + }; + + class LogoutCancelAck final : public ServerPacket + { + public: + LogoutCancelAck() : ServerPacket(SMSG_LOGOUT_CANCEL_ACK, 0) { } + + WorldPacket const* Write() override { return &_worldPacket; } + }; + + class LoadingScreenNotify final : public ClientPacket + { + public: + LoadingScreenNotify(WorldPacket&& packet) : ClientPacket(CMSG_LOAD_SCREEN, std::move(packet)) { } + + void Read() override; + + int32 MapID = -1; + bool Showing = false; + }; + + struct PlayerGuidLookupHint + { + Optional<uint32> VirtualRealmAddress; ///< current realm (?) (identifier made from the Index, BattleGroup and Region) + Optional<uint32> NativeRealmAddress; ///< original realm (?) (identifier made from the Index, BattleGroup and Region) + }; + + struct PlayerGuidLookupData + { + bool IsDeleted = false; + ObjectGuid AccountID; + ObjectGuid BnetAccountID; + ObjectGuid GuidActual; + std::string Name; + uint32 VirtualRealmAddress = 0; + uint8 Race = RACE_NONE; + uint8 Sex = GENDER_NONE; + uint8 ClassID = CLASS_NONE; + uint8 Level = 0; + DeclinedName DeclinedNames; + }; + + class QueryPlayerName final : public ClientPacket + { + public: + QueryPlayerName(WorldPacket&& packet) : ClientPacket(CMSG_NAME_QUERY, std::move(packet)) { } + + void Read() override; + + ObjectGuid Player; + PlayerGuidLookupHint Hint; + }; + + class PlayerNameResponse final : public ServerPacket + { + public: + PlayerNameResponse() : ServerPacket(SMSG_NAME_QUERY_RESPONSE, 60) { } + + WorldPacket const* Write() override; + + ObjectGuid Player; + uint8 Result = 0; // 0 - full packet, != 0 - only guid + PlayerGuidLookupData Data; + }; } } diff --git a/src/server/game/Server/Packets/ClientConfigPackets.cpp b/src/server/game/Server/Packets/ClientConfigPackets.cpp index a2807b1b755..b46288f86cb 100644 --- a/src/server/game/Server/Packets/ClientConfigPackets.cpp +++ b/src/server/game/Server/Packets/ClientConfigPackets.cpp @@ -87,3 +87,10 @@ WorldPacket const* WorldPackets::ClientConfig::AccountDataTimes::Write() return &_worldPacket; } + +WorldPacket const* WorldPackets::ClientConfig::ClientCacheVersion::Write() +{ + _worldPacket << uint32(CacheVersion); + + return &_worldPacket; +} diff --git a/src/server/game/Server/Packets/ClientConfigPackets.h b/src/server/game/Server/Packets/ClientConfigPackets.h index 3b891f828f2..0dbcfd7d577 100644 --- a/src/server/game/Server/Packets/ClientConfigPackets.h +++ b/src/server/game/Server/Packets/ClientConfigPackets.h @@ -50,6 +50,16 @@ namespace WorldPackets uint32 ServerTime = 0; uint32 AccountTimes[NUM_ACCOUNT_DATA_TYPES]; }; + + class ClientCacheVersion final : public ServerPacket + { + public: + ClientCacheVersion() : ServerPacket(SMSG_CLIENTCACHE_VERSION, 4) { } + + WorldPacket const* Write() override; + + uint32 CacheVersion = 0; + }; } } diff --git a/src/server/game/Server/Packets/GuildPackets.cpp b/src/server/game/Server/Packets/GuildPackets.cpp new file mode 100644 index 00000000000..c853cf4cc19 --- /dev/null +++ b/src/server/game/Server/Packets/GuildPackets.cpp @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2008-2014 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 "GuildPackets.h" + +void WorldPackets::Guild::QueryGuildInfo::Read() +{ + _worldPacket >> GuildGuid; + _worldPacket >> PlayerGuid; +} + +WorldPackets::Guild::QueryGuildInfoResponse::QueryGuildInfoResponse() + : ServerPacket(SMSG_GUILD_QUERY_RESPONSE) { } + +WorldPacket const* WorldPackets::Guild::QueryGuildInfoResponse::Write() +{ + _worldPacket << GuildGuid; + _worldPacket.WriteBit(Info.HasValue); + + if (Info.HasValue) + { + _worldPacket << Info.value.GuildGUID; + _worldPacket << uint32(Info.value.VirtualRealmAddress); + _worldPacket << uint32(Info.value.Ranks.size()); + _worldPacket << uint32(Info.value.EmblemStyle); + _worldPacket << uint32(Info.value.EmblemColor); + _worldPacket << uint32(Info.value.BorderStyle); + _worldPacket << uint32(Info.value.BorderColor); + _worldPacket << uint32(Info.value.BackgroundColor); + + for (GuildInfo::GuildInfoRank const& rank : Info.value.Ranks) + { + _worldPacket << uint32(rank.RankID); + _worldPacket << uint32(rank.RankOrder); + + _worldPacket.WriteBits(rank.RankName.size(), 7); + _worldPacket.WriteString(rank.RankName); + } + + _worldPacket.WriteBits(Info.value.GuildName.size(), 7); + _worldPacket.WriteString(Info.value.GuildName); + } + _worldPacket.FlushBits(); + + return &_worldPacket; +} diff --git a/src/server/game/Server/Packets/GuildPackets.h b/src/server/game/Server/Packets/GuildPackets.h new file mode 100644 index 00000000000..ea308aa9a88 --- /dev/null +++ b/src/server/game/Server/Packets/GuildPackets.h @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2008-2014 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 GuildPackets_h__ +#define GuildPackets_h__ + +#include "Packet.h" +#include "ObjectGuid.h" + +namespace WorldPackets +{ + namespace Guild + { + class QueryGuildInfo final : public ClientPacket + { + public: + QueryGuildInfo(WorldPacket&& packet) : ClientPacket(CMSG_GUILD_QUERY, std::move(packet)) { } + + void Read() override; + + ObjectGuid PlayerGuid; + ObjectGuid GuildGuid; + }; + + class QueryGuildInfoResponse final : public ServerPacket + { + public: + struct GuildInfo + { + ObjectGuid GuildGUID; + + uint32 VirtualRealmAddress = 0; ///< a special identifier made from the Index, BattleGroup and Region. + + std::string GuildName; + + struct GuildInfoRank + { + GuildInfoRank(uint32 id, uint32 order, std::string const& name) + : RankID(id), RankOrder(order), RankName(name) { } + + uint32 RankID; + uint32 RankOrder; + std::string RankName; + + bool operator<(GuildInfoRank const& right) const + { + return RankID < right.RankID; + } + }; + + std::set<GuildInfoRank> Ranks; + + uint32 EmblemStyle = 0; + uint32 EmblemColor = 0; + uint32 BorderStyle = 0; + uint32 BorderColor = 0; + uint32 BackgroundColor = 0; + }; + + QueryGuildInfoResponse(); + + WorldPacket const* Write() override; + + ObjectGuid GuildGuid; + Optional<GuildInfo> Info; + }; + } +} + +#endif // GuildPackets_h__ diff --git a/src/server/game/Server/Packets/MiscPackets.cpp b/src/server/game/Server/Packets/MiscPackets.cpp new file mode 100644 index 00000000000..66128354884 --- /dev/null +++ b/src/server/game/Server/Packets/MiscPackets.cpp @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2008-2014 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 "MiscPackets.h" + +void WorldPackets::Misc::ViolenceLevel::Read() +{ + _worldPacket >> ViolenceLvl; +} diff --git a/src/server/game/Server/Packets/MiscPackets.h b/src/server/game/Server/Packets/MiscPackets.h new file mode 100644 index 00000000000..d185b4dc10f --- /dev/null +++ b/src/server/game/Server/Packets/MiscPackets.h @@ -0,0 +1,39 @@ +/* +* Copyright (C) 2008-2014 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 MiscPackets_h__ +#define MiscPackets_h__ + +#include "Packet.h" + +namespace WorldPackets +{ + namespace Misc + { + class ViolenceLevel final : public ClientPacket + { + public: + ViolenceLevel(WorldPacket&& packet) : ClientPacket(CMSG_VIOLENCE_LEVEL, std::move(packet)) { } + + void Read() override; + + int8 ViolenceLvl = -1; ///< 0 - no combat effects, 1 - display some combat effects, 2 - blood, 3 - bloody, 4 - bloodier, 5 - bloodiest + }; + } +} + +#endif // MiscPackets_h__ diff --git a/src/server/game/Server/Packets/SystemPackets.cpp b/src/server/game/Server/Packets/SystemPackets.cpp index e6e6fbe9aa2..8181558cae7 100644 --- a/src/server/game/Server/Packets/SystemPackets.cpp +++ b/src/server/game/Server/Packets/SystemPackets.cpp @@ -17,9 +17,6 @@ #include "SystemPackets.h" -WorldPackets::System::FeatureSystemStatusGlueScreen::FeatureSystemStatusGlueScreen() - : ServerPacket(SMSG_FEATURE_SYSTEM_STATUS_GLUE_SCREEN, 1) { } - WorldPacket const* WorldPackets::System::FeatureSystemStatusGlueScreen::Write() { _worldPacket.WriteBit(BpayStoreEnabled); @@ -31,8 +28,21 @@ WorldPacket const* WorldPackets::System::FeatureSystemStatusGlueScreen::Write() return &_worldPacket; } -WorldPackets::System::SetTimeZoneInformation::SetTimeZoneInformation() - : ServerPacket(SMSG_SET_TIME_ZONE_INFORMATION) { } +WorldPacket const* WorldPackets::System::MOTD::Write() +{ + ASSERT(Text); + _worldPacket.WriteBits(Text->size(), 4); + _worldPacket.FlushBits(); + + for (std::string const& line : *Text) + { + _worldPacket.WriteBits(line.length(), 7); + _worldPacket.FlushBits(); + _worldPacket.WriteString(line); + } + + return &_worldPacket; +} WorldPacket const* WorldPackets::System::SetTimeZoneInformation::Write() { diff --git a/src/server/game/Server/Packets/SystemPackets.h b/src/server/game/Server/Packets/SystemPackets.h index 0cf075c6317..a2c988ac114 100644 --- a/src/server/game/Server/Packets/SystemPackets.h +++ b/src/server/game/Server/Packets/SystemPackets.h @@ -27,7 +27,7 @@ namespace WorldPackets class FeatureSystemStatusGlueScreen final : public ServerPacket { public: - FeatureSystemStatusGlueScreen(); + FeatureSystemStatusGlueScreen() : ServerPacket(SMSG_FEATURE_SYSTEM_STATUS_GLUE_SCREEN, 1) { } WorldPacket const* Write() override; @@ -37,10 +37,20 @@ namespace WorldPackets bool BpayStoreEnabled = false; // NYI }; + class MOTD final : public ServerPacket + { + public: + MOTD() : ServerPacket(SMSG_MOTD) { } + + WorldPacket const* Write() override; + + std::vector<std::string> const* Text = nullptr; + }; + class SetTimeZoneInformation final : public ServerPacket { public: - SetTimeZoneInformation(); + SetTimeZoneInformation() : ServerPacket(SMSG_SET_TIME_ZONE_INFORMATION) { } WorldPacket const* Write() override; diff --git a/src/server/game/Server/Packets/TradePackets.h b/src/server/game/Server/Packets/TradePackets.h new file mode 100644 index 00000000000..aff21ff32dc --- /dev/null +++ b/src/server/game/Server/Packets/TradePackets.h @@ -0,0 +1,37 @@ +/* +* Copyright (C) 2008-2014 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 TradePackets_h__ +#define TradePackets_h__ + +#include "Packet.h" + +namespace WorldPackets +{ + namespace Trade + { + class CancelTrade final : public ClientPacket + { + public: + CancelTrade(WorldPacket&& packet) : ClientPacket(CMSG_CANCEL_TRADE, std::move(packet)) { } + + void Read() override { } + }; + } +} + +#endif // TradePackets_h__ diff --git a/src/server/game/Server/Packets/WorldStatePackets.cpp b/src/server/game/Server/Packets/WorldStatePackets.cpp new file mode 100644 index 00000000000..7d062841003 --- /dev/null +++ b/src/server/game/Server/Packets/WorldStatePackets.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2008-2014 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 "WorldStatePackets.h" + +WorldPackets::WorldState::InitWorldStates::InitWorldStates() + : ServerPacket(SMSG_INIT_WORLD_STATES, 16) { } + +WorldPacket const* WorldPackets::WorldState::InitWorldStates::Write() +{ + _worldPacket.reserve(16 + Worldstates.size() * 8); + + _worldPacket << uint32(AreaID); + _worldPacket << uint32(SubareaID); + _worldPacket << uint32(MapID); + + _worldPacket << uint32(Worldstates.size()); + for (WorldStateInfo const& wsi : Worldstates) + { + _worldPacket << uint32(wsi.VariableID); + _worldPacket << uint32(wsi.Value); + } + + return &_worldPacket; +} + +WorldPackets::WorldState::UpdateWorldState::UpdateWorldState() + : ServerPacket(SMSG_UPDATE_WORLD_STATE, 9) { } + +WorldPacket const* WorldPackets::WorldState::UpdateWorldState::Write() +{ + _worldPacket << uint32(VariableID); + _worldPacket << int32(Value); + _worldPacket.WriteBit(Hidden); + _worldPacket.FlushBits(); + + return &_worldPacket; +} diff --git a/src/server/game/Server/Packets/WorldStatePackets.h b/src/server/game/Server/Packets/WorldStatePackets.h new file mode 100644 index 00000000000..7f9cdfe80de --- /dev/null +++ b/src/server/game/Server/Packets/WorldStatePackets.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2008-2014 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 WorldStatePackets_h__ +#define WorldStatePackets_h__ + +#include "Packet.h" + +namespace WorldPackets +{ + namespace WorldState + { + class InitWorldStates final : public ServerPacket + { + public: + struct WorldStateInfo + { + WorldStateInfo(uint32 variableID, int32 value) + : VariableID(variableID), Value(value) { } + + uint32 VariableID; + int32 Value; + }; + + InitWorldStates(); + + WorldPacket const* Write() override; + + uint32 AreaID = 0; ///< ZoneId + uint32 SubareaID = 0; ///< AreaId + uint32 MapID = 0; ///< MapId + + std::list<WorldStateInfo> Worldstates; + }; + + class UpdateWorldState final : public ServerPacket + { + public: + UpdateWorldState(); + + WorldPacket const* Write() override; + + int32 Value = 0; + bool Hidden = false; ///< @todo: research + uint32 VariableID = 0; + }; + } +} + +#endif // WorldStatePackets_h__ diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp index 30d9b657a5f..b9611e361e8 100644 --- a/src/server/game/Server/Protocol/Opcodes.cpp +++ b/src/server/game/Server/Protocol/Opcodes.cpp @@ -19,6 +19,9 @@ #include "Opcodes.h" #include "WorldSession.h" #include "Packets/CharacterPackets.h" +#include "Packets/GuildPackets.h" +#include "Packets/TradePackets.h" +#include "Packets/MiscPackets.h" template<class PacketClass, void(WorldSession::*HandlerFunction)(PacketClass&)> class PacketHandler : public OpcodeHandler @@ -111,6 +114,7 @@ void OpcodeTable::Initialize() DEFINE_OPCODE_HANDLER_OLD(CMSG_ADDON_REGISTERED_PREFIXES, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleAddonRegisteredPrefixesOpcode); DEFINE_OPCODE_HANDLER_OLD(CMSG_ADD_FRIEND, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleAddFriendOpcode ); DEFINE_OPCODE_HANDLER_OLD(CMSG_ADD_IGNORE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleAddIgnoreOpcode ); + DEFINE_OPCODE_HANDLER_OLD(CMSG_ADD_MUTE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); DEFINE_OPCODE_HANDLER_OLD(CMSG_ADD_VOICE_IGNORE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); DEFINE_OPCODE_HANDLER_OLD(CMSG_ALTER_APPEARANCE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleAlterAppearance ); DEFINE_OPCODE_HANDLER_OLD(CMSG_AREATRIGGER, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleAreaTriggerOpcode ); @@ -128,6 +132,7 @@ void OpcodeTable::Initialize() DEFINE_OPCODE_HANDLER_OLD(CMSG_ARENA_TEAM_ROSTER, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleArenaTeamRosterOpcode ); DEFINE_OPCODE_HANDLER_OLD(CMSG_ATTACKSTOP, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::HandleAttackStopOpcode ); DEFINE_OPCODE_HANDLER_OLD(CMSG_ATTACKSWING, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::HandleAttackSwingOpcode ); + DEFINE_OPCODE_HANDLER_OLD(CMSG_AUCTION_HELLO, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleAuctionHelloOpcode ); DEFINE_OPCODE_HANDLER_OLD(CMSG_AUCTION_LIST_BIDDER_ITEMS, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleAuctionListBidderItems ); DEFINE_OPCODE_HANDLER_OLD(CMSG_AUCTION_LIST_ITEMS, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleAuctionListItems ); DEFINE_OPCODE_HANDLER_OLD(CMSG_AUCTION_LIST_OWNER_ITEMS, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleAuctionListOwnerItems ); @@ -135,6 +140,7 @@ void OpcodeTable::Initialize() DEFINE_OPCODE_HANDLER_OLD(CMSG_AUCTION_PLACE_BID, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleAuctionPlaceBid ); DEFINE_OPCODE_HANDLER_OLD(CMSG_AUCTION_REMOVE_ITEM, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleAuctionRemoveItem ); DEFINE_OPCODE_HANDLER_OLD(CMSG_AUCTION_SELL_ITEM, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleAuctionSellItem ); + DEFINE_OPCODE_HANDLER_OLD(CMSG_AUTH_CONTINUED_SESSION, STATUS_NEVER, PROCESS_THREADUNSAFE, &WorldSession::Handle_EarlyProccess ); DEFINE_OPCODE_HANDLER_OLD(CMSG_AUTH_SESSION, STATUS_NEVER, PROCESS_THREADUNSAFE, &WorldSession::Handle_EarlyProccess ); DEFINE_OPCODE_HANDLER_OLD(CMSG_AUTOBANK_ITEM, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleAutoBankItemOpcode ); DEFINE_OPCODE_HANDLER_OLD(CMSG_AUTOEQUIP_ITEM, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleAutoEquipItemOpcode ); @@ -157,6 +163,9 @@ void OpcodeTable::Initialize() DEFINE_OPCODE_HANDLER_OLD(CMSG_BATTLEMASTER_HELLO, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleBattlemasterHelloOpcode ); DEFINE_OPCODE_HANDLER_OLD(CMSG_BATTLEMASTER_JOIN_ARENA, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleBattlemasterJoinArena ); DEFINE_OPCODE_HANDLER_OLD(CMSG_BATTLEMASTER_JOIN_RATED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + DEFINE_OPCODE_HANDLER_OLD(CMSG_BATTLE_PAY_GET_PRODUCT_LIST_QUERY, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + DEFINE_OPCODE_HANDLER_OLD(CMSG_BATTLE_PAY_GET_PURCHASE_LIST_QUERY, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + DEFINE_OPCODE_HANDLER_OLD(CMSG_BATTLE_PET_NAME_QUERY, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); DEFINE_OPCODE_HANDLER_OLD(CMSG_BEGIN_TRADE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleBeginTradeOpcode ); DEFINE_OPCODE_HANDLER_OLD(CMSG_BINDER_ACTIVATE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleBinderActivateOpcode ); DEFINE_OPCODE_HANDLER_OLD(CMSG_BUG, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleBugOpcode ); @@ -188,7 +197,7 @@ void OpcodeTable::Initialize() DEFINE_OPCODE_HANDLER_OLD(CMSG_CANCEL_MOUNT_AURA, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleCancelMountAuraOpcode ); DEFINE_OPCODE_HANDLER_OLD(CMSG_CANCEL_QUEUED_SPELL, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); DEFINE_OPCODE_HANDLER_OLD(CMSG_CANCEL_TEMP_ENCHANTMENT, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleCancelTempEnchantmentOpcode); - DEFINE_OPCODE_HANDLER_OLD(CMSG_CANCEL_TRADE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleCancelTradeOpcode); + DEFINE_HANDLER(CMSG_CANCEL_TRADE, STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT, PROCESS_THREADUNSAFE, WorldPackets::Trade::CancelTrade, &WorldSession::HandleCancelTradeOpcode); DEFINE_OPCODE_HANDLER_OLD(CMSG_CAST_SPELL, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::HandleCastSpellOpcode ); DEFINE_OPCODE_HANDLER_OLD(CMSG_CHANGEPLAYER_DIFFICULTY, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); DEFINE_OPCODE_HANDLER_OLD(CMSG_CHANGE_SEATS_ON_CONTROLLED_VEHICLE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleChangeSeatsOnControlledVehicle); @@ -247,6 +256,7 @@ void OpcodeTable::Initialize() DEFINE_OPCODE_HANDLER_OLD(CMSG_DB_QUERY_BULK, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); DEFINE_OPCODE_HANDLER_OLD(CMSG_DEL_FRIEND, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleDelFriendOpcode ); DEFINE_OPCODE_HANDLER_OLD(CMSG_DEL_IGNORE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleDelIgnoreOpcode ); + DEFINE_OPCODE_HANDLER_OLD(CMSG_DEL_MUTE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); DEFINE_OPCODE_HANDLER_OLD(CMSG_DEL_VOICE_IGNORE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); DEFINE_OPCODE_HANDLER_OLD(CMSG_DESTROY_ITEM, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleDestroyItemOpcode ); DEFINE_OPCODE_HANDLER_OLD(CMSG_DISMISS_CONTROLLED_VEHICLE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleDismissControlledVehicle ); @@ -320,7 +330,7 @@ void OpcodeTable::Initialize() DEFINE_OPCODE_HANDLER_OLD(CMSG_GUILD_NEWS_UPDATE_STICKY, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::HandleGuildNewsUpdateStickyOpcode); DEFINE_OPCODE_HANDLER_OLD(CMSG_GUILD_PERMISSIONS, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildPermissions ); DEFINE_OPCODE_HANDLER_OLD(CMSG_GUILD_PROMOTE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildPromoteOpcode ); - DEFINE_OPCODE_HANDLER_OLD(CMSG_GUILD_QUERY, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildQueryOpcode ); + DEFINE_HANDLER(CMSG_GUILD_QUERY, STATUS_AUTHED, PROCESS_THREADUNSAFE, WorldPackets::Guild::QueryGuildInfo, &WorldSession::HandleGuildQueryOpcode); DEFINE_OPCODE_HANDLER_OLD(CMSG_GUILD_QUERY_NEWS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::HandleGuildQueryNewsOpcode ); DEFINE_OPCODE_HANDLER_OLD(CMSG_GUILD_QUERY_RANKS, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildQueryRanksOpcode ); DEFINE_OPCODE_HANDLER_OLD(CMSG_GUILD_REMOVE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildRemoveOpcode ); @@ -369,9 +379,9 @@ void OpcodeTable::Initialize() DEFINE_OPCODE_HANDLER_OLD(CMSG_LF_GUILD_REMOVE_RECRUIT, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildFinderRemoveRecruit ); DEFINE_OPCODE_HANDLER_OLD(CMSG_LF_GUILD_SET_GUILD_POST, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildFinderSetGuildPost ); DEFINE_OPCODE_HANDLER_OLD(CMSG_LIST_INVENTORY, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleListInventoryOpcode ); - DEFINE_OPCODE_HANDLER_OLD(CMSG_LOAD_SCREEN, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleLoadScreenOpcode ); - DEFINE_OPCODE_HANDLER_OLD(CMSG_LOGOUT_CANCEL, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleLogoutCancelOpcode ); - DEFINE_OPCODE_HANDLER_OLD(CMSG_LOGOUT_REQUEST, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleLogoutRequestOpcode ); + DEFINE_HANDLER(CMSG_LOAD_SCREEN, STATUS_AUTHED, PROCESS_THREADUNSAFE, WorldPackets::Character::LoadingScreenNotify, &WorldSession::HandleLoadScreenOpcode); + DEFINE_HANDLER(CMSG_LOGOUT_CANCEL, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Character::LogoutCancel, &WorldSession::HandleLogoutCancelOpcode); + DEFINE_HANDLER(CMSG_LOGOUT_REQUEST, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Character::LogoutRequest, &WorldSession::HandleLogoutRequestOpcode); DEFINE_OPCODE_HANDLER_OLD(CMSG_LOG_DISCONNECT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_EarlyProccess ); DEFINE_OPCODE_HANDLER_OLD(CMSG_LOOT, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleLootOpcode ); DEFINE_OPCODE_HANDLER_OLD(CMSG_LOOT_CURRENCY, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); @@ -421,17 +431,23 @@ void OpcodeTable::Initialize() DEFINE_OPCODE_HANDLER_OLD(CMSG_MOVE_FORCE_WALK_SPEED_CHANGE_ACK, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::HandleForceSpeedChangeAck ); DEFINE_OPCODE_HANDLER_OLD(CMSG_MOVE_GRAVITY_DISABLE_ACK, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); DEFINE_OPCODE_HANDLER_OLD(CMSG_MOVE_GRAVITY_ENABLE_ACK, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + DEFINE_OPCODE_HANDLER_OLD(CMSG_MOVE_HEARTBEAT, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes ); DEFINE_OPCODE_HANDLER_OLD(CMSG_MOVE_HOVER_ACK, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleMoveHoverAck ); + DEFINE_OPCODE_HANDLER_OLD(CMSG_MOVE_FALL_LAND, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes ); DEFINE_OPCODE_HANDLER_OLD(CMSG_MOVE_KNOCK_BACK_ACK, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::HandleMoveKnockBackAck ); + DEFINE_OPCODE_HANDLER_OLD(CMSG_MOVE_JUMP, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes ); DEFINE_OPCODE_HANDLER_OLD(CMSG_MOVE_NOT_ACTIVE_MOVER, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::HandleMoveNotActiveMover ); DEFINE_OPCODE_HANDLER_OLD(CMSG_MOVE_SET_CAN_FLY, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes ); DEFINE_OPCODE_HANDLER_OLD(CMSG_MOVE_SET_CAN_FLY_ACK, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::HandleMoveSetCanFlyAckOpcode ); DEFINE_OPCODE_HANDLER_OLD(CMSG_MOVE_SET_CAN_TRANSITION_BETWEEN_SWIM_AND_FLY_ACK, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); DEFINE_OPCODE_HANDLER_OLD(CMSG_MOVE_SET_COLLISION_HEIGHT_ACK, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::HandleSetCollisionHeightAck ); DEFINE_OPCODE_HANDLER_OLD(CMSG_MOVE_SPLINE_DONE, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::HandleMoveSplineDoneOpcode ); + DEFINE_OPCODE_HANDLER_OLD(CMSG_MOVE_START_BACKWARD, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes ); + DEFINE_OPCODE_HANDLER_OLD(CMSG_MOVE_START_FORWARD, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes ); + DEFINE_OPCODE_HANDLER_OLD(CMSG_MOVE_STOP, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes ); DEFINE_OPCODE_HANDLER_OLD(CMSG_MOVE_TIME_SKIPPED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::HandleMoveTimeSkippedOpcode ); DEFINE_OPCODE_HANDLER_OLD(CMSG_MOVE_WATER_WALK_ACK, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::HandleMoveWaterWalkAck ); - DEFINE_OPCODE_HANDLER_OLD(CMSG_NAME_QUERY, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleNameQueryOpcode ); + DEFINE_HANDLER(CMSG_NAME_QUERY, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, WorldPackets::Character::QueryPlayerName, &WorldSession::HandleNameQueryOpcode); DEFINE_OPCODE_HANDLER_OLD(CMSG_NEXT_CINEMATIC_CAMERA, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleNextCinematicCamera ); DEFINE_OPCODE_HANDLER_OLD(CMSG_NPC_TEXT_QUERY, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleNpcTextQueryOpcode ); DEFINE_OPCODE_HANDLER_OLD(CMSG_OBJECT_UPDATE_FAILED, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::HandleObjectUpdateFailedOpcode ); @@ -487,13 +503,13 @@ void OpcodeTable::Initialize() DEFINE_OPCODE_HANDLER_OLD(CMSG_QUEST_NPC_QUERY, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestNPCQuery ); DEFINE_OPCODE_HANDLER_OLD(CMSG_QUEST_POI_QUERY, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestPOIQuery ); DEFINE_OPCODE_HANDLER_OLD(CMSG_QUEST_QUERY, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleQuestQueryOpcode ); - DEFINE_OPCODE_HANDLER_OLD(CMSG_RANDOMIZE_CHAR_NAME, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleRandomizeCharNameOpcode ); + DEFINE_OPCODE_HANDLER_OLD(CMSG_QUEUED_MESSAGES_END, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + DEFINE_HANDLER(CMSG_RANDOMIZE_CHAR_NAME, STATUS_AUTHED, PROCESS_THREADUNSAFE, WorldPackets::Character::GenerateRandomCharacterName, &WorldSession::HandleRandomizeCharNameOpcode); DEFINE_OPCODE_HANDLER_OLD(CMSG_READ_ITEM, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleReadItem ); DEFINE_OPCODE_HANDLER_OLD(CMSG_REALM_SPLIT, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleRealmSplitOpcode ); DEFINE_OPCODE_HANDLER_OLD(CMSG_RECLAIM_CORPSE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleReclaimCorpseOpcode ); - DEFINE_OPCODE_HANDLER_OLD(CMSG_REDIRECTION_AUTH_PROOF, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); DEFINE_OPCODE_HANDLER_OLD(CMSG_REFORGE_ITEM, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::HandleReforgeItemOpcode ); - DEFINE_OPCODE_HANDLER_OLD(CMSG_REORDER_CHARACTERS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::HandleReorderCharacters ); + DEFINE_HANDLER(CMSG_REORDER_CHARACTERS, STATUS_AUTHED, PROCESS_THREADUNSAFE, WorldPackets::Character::ReorderCharacters, &WorldSession::HandleReorderCharacters); DEFINE_OPCODE_HANDLER_OLD(CMSG_REPAIR_ITEM, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleRepairItemOpcode ); DEFINE_OPCODE_HANDLER_OLD(CMSG_REPOP_REQUEST, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleRepopRequestOpcode ); DEFINE_OPCODE_HANDLER_OLD(CMSG_REPORT_PVP_AFK, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleReportPvPAFK ); @@ -539,13 +555,15 @@ void OpcodeTable::Initialize() DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_FACTION_ATWAR, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleSetFactionAtWar ); DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_FACTION_INACTIVE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleSetFactionInactiveOpcode ); DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_GUILD_BANK_TEXT, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleSetGuildBankTabText ); + DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_LOOT_SPECIALIZATION, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_PET_SLOT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_PLAYER_DECLINED_NAMES, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleSetPlayerDeclinedNames ); DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_PREFERED_CEMETERY, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); - DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_PRIMARY_TALENT_TREE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_RELATIVE_POSITION, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_SAVED_INSTANCE_EXTEND, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleSetSavedInstanceExtend ); DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_SELECTION, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::HandleSetSelectionOpcode ); + DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_SKILL_CHEAT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_SPECIALIZATION, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_TAXI_BENCHMARK_MODE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleSetTaxiBenchmarkOpcode ); DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_TITLE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleSetTitleOpcode ); DEFINE_OPCODE_HANDLER_OLD(CMSG_SET_TRADE_CURRENCY, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); @@ -565,7 +583,8 @@ void OpcodeTable::Initialize() DEFINE_OPCODE_HANDLER_OLD(CMSG_SUBMIT_COMPLAIN, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); DEFINE_OPCODE_HANDLER_OLD(CMSG_SUGGESTION_SUBMIT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); DEFINE_OPCODE_HANDLER_OLD(CMSG_SUMMON_RESPONSE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleSummonResponseOpcode ); - DEFINE_OPCODE_HANDLER_OLD(CMSG_SUSPEND_TOKEN, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + DEFINE_OPCODE_HANDLER_OLD(CMSG_SUSPEND_COMMS_ACK, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + DEFINE_OPCODE_HANDLER_OLD(CMSG_SUSPEND_TOKEN_RESPONSE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); DEFINE_OPCODE_HANDLER_OLD(CMSG_SWAP_INV_ITEM, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleSwapInvItemOpcode ); DEFINE_OPCODE_HANDLER_OLD(CMSG_SWAP_ITEM, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleSwapItem ); DEFINE_OPCODE_HANDLER_OLD(CMSG_SYNC_DANCE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); @@ -596,7 +615,7 @@ void OpcodeTable::Initialize() DEFINE_OPCODE_HANDLER_OLD(CMSG_UPDATE_PROJECTILE_POSITION, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleUpdateProjectilePosition ); DEFINE_OPCODE_HANDLER_OLD(CMSG_USED_FOLLOW, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); DEFINE_OPCODE_HANDLER_OLD(CMSG_USE_ITEM, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleUseItemOpcode ); - DEFINE_OPCODE_HANDLER_OLD(CMSG_VIOLENCE_LEVEL, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::HandleViolenceLevel ); + DEFINE_HANDLER(CMSG_VIOLENCE_LEVEL, STATUS_AUTHED, PROCESS_INPLACE, WorldPackets::Misc::ViolenceLevel, &WorldSession::HandleViolenceLevel); DEFINE_OPCODE_HANDLER_OLD(CMSG_VOICE_SESSION_ENABLE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleVoiceSessionEnableOpcode ); DEFINE_OPCODE_HANDLER_OLD(CMSG_VOID_STORAGE_QUERY, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::HandleVoidStorageQuery ); DEFINE_OPCODE_HANDLER_OLD(CMSG_VOID_STORAGE_TRANSFER, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::HandleVoidStorageTransfer ); @@ -611,25 +630,17 @@ void OpcodeTable::Initialize() DEFINE_OPCODE_HANDLER_OLD(CMSG_WORLD_TELEPORT, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleWorldTeleportOpcode ); DEFINE_OPCODE_HANDLER_OLD(CMSG_WRAP_ITEM, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleWrapItemOpcode ); DEFINE_OPCODE_HANDLER_OLD(CMSG_ZONEUPDATE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleZoneUpdateOpcode ); - DEFINE_OPCODE_HANDLER_OLD(MSG_AUCTION_HELLO, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleAuctionHelloOpcode ); - DEFINE_OPCODE_HANDLER_OLD(MSG_CHANNEL_START, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - DEFINE_OPCODE_HANDLER_OLD(MSG_CHANNEL_UPDATE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); DEFINE_OPCODE_HANDLER_OLD(MSG_CORPSE_QUERY, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleCorpseQueryOpcode ); DEFINE_OPCODE_HANDLER_OLD(MSG_INSPECT_ARENA_TEAMS, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleInspectArenaTeamsOpcode ); DEFINE_OPCODE_HANDLER_OLD(MSG_LIST_STABLED_PETS, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleListStabledPetsOpcode ); DEFINE_OPCODE_HANDLER_OLD(MSG_MINIMAP_PING, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::HandleMinimapPingOpcode ); DEFINE_OPCODE_HANDLER_OLD(MSG_MOVE_CHARM_TELEPORT_CHEAT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); - DEFINE_OPCODE_HANDLER_OLD(MSG_MOVE_FALL_LAND, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes ); - DEFINE_OPCODE_HANDLER_OLD(MSG_MOVE_HEARTBEAT, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes ); - DEFINE_OPCODE_HANDLER_OLD(MSG_MOVE_JUMP, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes ); DEFINE_OPCODE_HANDLER_OLD(MSG_MOVE_SET_FACING, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes ); DEFINE_OPCODE_HANDLER_OLD(MSG_MOVE_SET_PITCH, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes ); DEFINE_OPCODE_HANDLER_OLD(MSG_MOVE_SET_RUN_MODE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); DEFINE_OPCODE_HANDLER_OLD(MSG_MOVE_SET_WALK_MODE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); DEFINE_OPCODE_HANDLER_OLD(MSG_MOVE_START_ASCEND, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes ); - DEFINE_OPCODE_HANDLER_OLD(MSG_MOVE_START_BACKWARD, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes ); DEFINE_OPCODE_HANDLER_OLD(MSG_MOVE_START_DESCEND, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes ); - DEFINE_OPCODE_HANDLER_OLD(MSG_MOVE_START_FORWARD, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes ); DEFINE_OPCODE_HANDLER_OLD(MSG_MOVE_START_PITCH_DOWN, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes ); DEFINE_OPCODE_HANDLER_OLD(MSG_MOVE_START_PITCH_UP, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes ); DEFINE_OPCODE_HANDLER_OLD(MSG_MOVE_START_STRAFE_LEFT, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes ); @@ -637,7 +648,6 @@ void OpcodeTable::Initialize() DEFINE_OPCODE_HANDLER_OLD(MSG_MOVE_START_SWIM, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes ); DEFINE_OPCODE_HANDLER_OLD(MSG_MOVE_START_TURN_LEFT, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes ); DEFINE_OPCODE_HANDLER_OLD(MSG_MOVE_START_TURN_RIGHT, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes ); - DEFINE_OPCODE_HANDLER_OLD(MSG_MOVE_STOP, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes ); DEFINE_OPCODE_HANDLER_OLD(MSG_MOVE_STOP_ASCEND, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes ); DEFINE_OPCODE_HANDLER_OLD(MSG_MOVE_STOP_PITCH, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes ); DEFINE_OPCODE_HANDLER_OLD(MSG_MOVE_STOP_STRAFE, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes ); @@ -674,6 +684,7 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_ACCOUNT_DATA_TIMES, STATUS_NEVER); DEFINE_SERVER_OPCODE_HANDLER(SMSG_ACCOUNT_INFO_RESPONSE, STATUS_UNHANDLED); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_ACCOUNT_MOUNT_UPDATE, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_ACCOUNT_RESTRICTED_WARNING, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_ACHIEVEMENT_DELETED, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_ACHIEVEMENT_EARNED, STATUS_UNHANDLED); @@ -705,6 +716,7 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_AUCTION_BIDDER_LIST_RESULT, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_AUCTION_BIDDER_NOTIFICATION, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_AUCTION_COMMAND_RESULT, STATUS_UNHANDLED); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_AUCTION_HELLO, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_AUCTION_LIST_PENDING_SALES, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_AUCTION_LIST_RESULT, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_AUCTION_OWNER_LIST_RESULT, STATUS_UNHANDLED); @@ -739,7 +751,12 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_BATTLEGROUND_INFO_THROTTLED, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_BATTLEGROUND_PLAYER_JOINED, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_BATTLEGROUND_PLAYER_LEFT, STATUS_UNHANDLED); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_BATTLE_PAY_GET_DISTRIBUTION_LIST_RESPONSE, STATUS_UNHANDLED); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_BATTLE_PAY_GET_PRODUCT_LIST_RESPONSE, STATUS_UNHANDLED); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_BATTLE_PAY_GET_PURCHASE_LIST_RESPONSE, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_BATTLE_PET_JOURNAL, STATUS_UNHANDLED); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_BATTLE_PET_JOURNAL_LOCK_ACQUIRED, STATUS_UNHANDLED); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_BATTLE_PET_NAME_QUERY_RESPONSE, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_BINDER_CONFIRM, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_BINDPOINTUPDATE, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_BINDZONEREPLY, STATUS_UNHANDLED); @@ -775,6 +792,8 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHANNEL_LIST, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHANNEL_MEMBER_COUNT, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHANNEL_NOTIFY, STATUS_UNHANDLED); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHANNEL_START, STATUS_UNHANDLED); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHANNEL_UPDATE, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHARACTER_LOGIN_FAILED, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHAR_CREATE, STATUS_NEVER); DEFINE_SERVER_OPCODE_HANDLER(SMSG_CHAR_CUSTOMIZE, STATUS_UNHANDLED); @@ -795,7 +814,7 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_CLEAR_COOLDOWNS, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_CLEAR_FAR_SIGHT_IMMEDIATE, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_CLEAR_TARGET, STATUS_UNHANDLED); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_CLIENTCACHE_VERSION, STATUS_UNHANDLED); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_CLIENTCACHE_VERSION, STATUS_NEVER); DEFINE_SERVER_OPCODE_HANDLER(SMSG_CLIENT_CONTROL_UPDATE, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_COMBAT_EVENT_FAILED, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_COMMENTATOR_MAP_INFO, STATUS_UNHANDLED); @@ -811,6 +830,7 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_COMSAT_DISCONNECT, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_COMSAT_RECONNECT_TRY, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_CONTACT_LIST, STATUS_UNHANDLED); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_CONTACT_STATUS, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_CONVERT_RUNE, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_COOLDOWN_CHEAT, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_COOLDOWN_EVENT, STATUS_UNHANDLED); @@ -826,6 +846,7 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_CUSTOM_LOAD_SCREEN, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_DAMAGE_CALC_LOG, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_DANCE_QUERY_RESPONSE, STATUS_UNHANDLED); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_DANCE_STUDIO_CREATE_RESULT, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_DB_REPLY, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_DEATH_RELEASE_LOC, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_DEBUG_RUNE_REGEN, STATUS_UNHANDLED); @@ -869,7 +890,6 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_FORCEACTIONSHOW, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_FORCED_DEATH_UPDATE, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_FORCE_ANIM, STATUS_UNHANDLED); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_FORCE_SEND_QUEUED_PACKETS, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_FORCE_SET_VEHICLE_REC_ID, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_FORGE_MASTER_SET, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_FRIEND_STATUS, STATUS_UNHANDLED); @@ -940,7 +960,7 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_GUILD_NEWS_UPDATE, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_GUILD_PARTY_STATE_RESPONSE, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_GUILD_PERMISSIONS_QUERY_RESULTS, STATUS_UNHANDLED); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_GUILD_QUERY_RESPONSE, STATUS_UNHANDLED); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_GUILD_QUERY_RESPONSE, STATUS_NEVER); DEFINE_SERVER_OPCODE_HANDLER(SMSG_GUILD_RANK, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_GUILD_RANKS_UPDATE, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_GUILD_RECIPES, STATUS_UNHANDLED); @@ -1016,9 +1036,9 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_LOAD_CUF_PROFILES, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_LOGIN_SETTIMESPEED, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_LOGIN_VERIFY_WORLD, STATUS_NEVER); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_LOGOUT_CANCEL_ACK, STATUS_UNHANDLED); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_LOGOUT_COMPLETE, STATUS_UNHANDLED); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_LOGOUT_RESPONSE, STATUS_UNHANDLED); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_LOGOUT_CANCEL_ACK, STATUS_NEVER); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_LOGOUT_COMPLETE, STATUS_NEVER); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_LOGOUT_RESPONSE, STATUS_NEVER); DEFINE_SERVER_OPCODE_HANDLER(SMSG_LOG_XPGAIN, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_LOOT_ALL_PASSED, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_LOOT_CLEAR_MONEY, STATUS_UNHANDLED); @@ -1047,7 +1067,7 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_MONEY_NOTIFY, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_MONSTER_MOVE, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_MONSTER_MOVE_TRANSPORT, STATUS_UNHANDLED); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_MOTD, STATUS_UNHANDLED); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_MOTD, STATUS_NEVER); DEFINE_SERVER_OPCODE_HANDLER(SMSG_MOUNTRESULT, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_MOUNTSPECIAL_ANIM, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_MOVE_COLLISION_DISABLE, STATUS_UNHANDLED); @@ -1092,7 +1112,7 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_MOVE_UPDATE_WALK_SPEED, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_MOVE_WATER_WALK, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_MULTIPLE_PACKETS, STATUS_UNHANDLED); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_NAME_QUERY_RESPONSE, STATUS_UNHANDLED); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_NAME_QUERY_RESPONSE, STATUS_NEVER); DEFINE_SERVER_OPCODE_HANDLER(SMSG_NEW_TAXI_PATH, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_NEW_WORLD, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_NEW_WORLD_ABORT, STATUS_UNHANDLED); @@ -1158,6 +1178,7 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_PVP_CREDIT, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_PVP_LOG_DATA, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_PVP_OPTIONS_ENABLED, STATUS_UNHANDLED); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_PVP_SEASON, STATUS_NEVER); DEFINE_SERVER_OPCODE_HANDLER(SMSG_QUERY_QUESTS_COMPLETED_RESPONSE, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_QUERY_TIME_RESPONSE, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_QUESTGIVER_OFFER_REWARD, STATUS_UNHANDLED); @@ -1186,7 +1207,7 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_RAID_MARKERS_CHANGED, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_RAID_READY_CHECK_THROTTLED_ERROR, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_RAID_SUMMON_FAILED, STATUS_UNHANDLED); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_RANDOMIZE_CHAR_NAME, STATUS_UNHANDLED); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_RANDOMIZE_CHAR_NAME, STATUS_NEVER); DEFINE_SERVER_OPCODE_HANDLER(SMSG_RATED_BG_RATING, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_RATED_BG_STATS, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_READ_ITEM_FAILED, STATUS_UNHANDLED); @@ -1194,7 +1215,7 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_REALM_SPLIT, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_REAL_GROUP_UPDATE, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_RECEIVED_MAIL, STATUS_UNHANDLED); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_REDIRECT_CLIENT, STATUS_UNHANDLED); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_REDIRECT_CLIENT, STATUS_NEVER); DEFINE_SERVER_OPCODE_HANDLER(SMSG_REFER_A_FRIEND_EXPIRED, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_REFER_A_FRIEND_FAILURE, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_REFORGE_RESULT, STATUS_UNHANDLED); @@ -1207,6 +1228,7 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_RESET_COMPRESSION_CONTEXT, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_RESET_FAILED_NOTIFY, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_RESPOND_INSPECT_ACHIEVEMENTS, STATUS_UNHANDLED); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_RESUME_COMMS, STATUS_NEVER); DEFINE_SERVER_OPCODE_HANDLER(SMSG_RESURRECT_FAILED, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_RESURRECT_REQUEST, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_RESYNC_RUNES, STATUS_UNHANDLED); @@ -1304,7 +1326,7 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_SUPERCEDED_SPELL, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SUPPRESS_NPC_GREETINGS, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_SUSPEND_COMMS, STATUS_UNHANDLED); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_SUSPEND_TOKEN_RESPONSE, STATUS_UNHANDLED); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_SUSPEND_TOKEN, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_TALENTS_ERROR, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_TALENTS_INFO, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_TALENTS_INVOLUNTARILY_RESET, STATUS_UNHANDLED); @@ -1345,7 +1367,7 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_UPDATE_LAST_INSTANCE, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_UPDATE_OBJECT, STATUS_NEVER); DEFINE_SERVER_OPCODE_HANDLER(SMSG_UPDATE_SERVER_PLAYER_POSITION, STATUS_UNHANDLED); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_UPDATE_WORLD_STATE, STATUS_UNHANDLED); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_UPDATE_WORLD_STATE, STATUS_NEVER); DEFINE_SERVER_OPCODE_HANDLER(SMSG_USERLIST_ADD, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_USERLIST_REMOVE, STATUS_UNHANDLED); DEFINE_SERVER_OPCODE_HANDLER(SMSG_USERLIST_UPDATE, STATUS_UNHANDLED); diff --git a/src/server/game/Server/Protocol/Opcodes.h b/src/server/game/Server/Protocol/Opcodes.h index 6023f45adb0..a77793ce6dd 100644 --- a/src/server/game/Server/Protocol/Opcodes.h +++ b/src/server/game/Server/Protocol/Opcodes.h @@ -26,6 +26,12 @@ #include "Common.h" #include <iomanip> +enum ConnectionType +{ + CONNECTION_TYPE_REALM = 0, + CONNECTION_TYPE_INSTANCE = 1 +}; + enum OpcodeMisc : uint32 { MAX_OPCODE = 0x1FFF, @@ -34,7 +40,7 @@ enum OpcodeMisc : uint32 NULL_OPCODE = 0xBADD }; -// CMSGs 6.0.3.19103 +// CMSGs 6.0.3.19116 enum OpcodeClient : uint32 { CMSG_ACCEPT_LEVEL_GRANT = 0xBADD, @@ -42,8 +48,9 @@ enum OpcodeClient : uint32 CMSG_ACTIVATETAXI = 0xBADD, CMSG_ACTIVATETAXIEXPRESS = 0xBADD, CMSG_ADDON_REGISTERED_PREFIXES = 0x03F4, - CMSG_ADD_FRIEND = 0xBADD, - CMSG_ADD_IGNORE = 0xBADD, + CMSG_ADD_FRIEND = 0x0DB9, + CMSG_ADD_IGNORE = 0x1321, + CMSG_ADD_MUTE = 0x098A, CMSG_ADD_VOICE_IGNORE = 0xBADD, CMSG_ALTER_APPEARANCE = 0xBADD, CMSG_AREATRIGGER = 0x01B4, @@ -69,6 +76,7 @@ enum OpcodeClient : uint32 CMSG_AUCTION_PLACE_BID = 0xBADD, CMSG_AUCTION_REMOVE_ITEM = 0xBADD, CMSG_AUCTION_SELL_ITEM = 0xBADD, + CMSG_AUTH_CONTINUED_SESSION = 0x0485, CMSG_AUTH_SESSION = 0x0487, CMSG_AUTOBANK_ITEM = 0xBADD, CMSG_AUTOEQUIP_GROUND_ITEM = 0xBADD, @@ -96,6 +104,9 @@ enum OpcodeClient : uint32 CMSG_BATTLEMASTER_JOIN_ARENA = 0xBADD, CMSG_BATTLEMASTER_JOIN_RATED = 0xBADD, CMSG_BATTLEMASTER_HELLO = 0xBADD, + CMSG_BATTLE_PAY_GET_PRODUCT_LIST_QUERY = 0x1389, + CMSG_BATTLE_PAY_GET_PURCHASE_LIST_QUERY = 0x120C, + CMSG_BATTLE_PET_NAME_QUERY = 0x041C, CMSG_BEGIN_TRADE = 0xBADD, CMSG_BINDER_ACTIVATE = 0xBADD, CMSG_BOT_DETECTED2 = 0xBADD, @@ -121,7 +132,7 @@ enum OpcodeClient : uint32 CMSG_CALENDAR_GUILD_FILTER = 0xBADD, CMSG_CALENDAR_REMOVE_EVENT = 0xBADD, CMSG_CALENDAR_UPDATE_EVENT = 0xBADD, - CMSG_CANCEL_AURA = 0xBADD, + CMSG_CANCEL_AURA = 0x08AE, CMSG_CANCEL_AUTO_REPEAT_SPELL = 0xBADD, CMSG_CANCEL_CAST = 0xBADD, CMSG_CANCEL_CHANNELLING = 0xBADD, @@ -187,8 +198,9 @@ enum OpcodeClient : uint32 CMSG_DANCE_QUERY = 0xBADD, CMSG_DB_QUERY_BULK = 0x138B, CMSG_DECLINE_CHANNEL_INVITE = 0xBADD, - CMSG_DEL_FRIEND = 0xBADD, - CMSG_DEL_IGNORE = 0xBADD, + CMSG_DEL_FRIEND = 0x0F2A, + CMSG_DEL_IGNORE = 0x033D, + CMSG_DEL_MUTE = 0x0128, CMSG_DEL_VOICE_IGNORE = 0xBADD, CMSG_DESTROY_ITEM = 0xBADD, CMSG_DISMISS_CONTROLLED_VEHICLE = 0xBADD, @@ -204,9 +216,9 @@ enum OpcodeClient : uint32 CMSG_EQUIPMENT_SET_USE = 0xBADD, CMSG_FACTION_BONUS_INFO = 0x0928, CMSG_FAR_SIGHT = 0xBADD, - CMSG_FORCE_MOVE_ROOT_ACK = 0xBADD, + CMSG_FORCE_MOVE_ROOT_ACK = 0x0B73, CMSG_FORCE_MOVE_UNROOT_ACK = 0xBADD, - CMSG_GAMEOBJECT_QUERY = 0x0D97, + CMSG_GAMEOBJECT_QUERY = 0x03AE, CMSG_GAMEOBJ_REPORT_USE = 0x082E, CMSG_GAMEOBJ_USE = 0xBADD, CMSG_GAMESPEED_SET = 0xBADD, @@ -323,7 +335,7 @@ enum OpcodeClient : uint32 CMSG_LF_GUILD_SET_GUILD_POST = 0xBADD, CMSG_LIST_INVENTORY = 0xBADD, CMSG_LOAD_SCREEN = 0x0B08, - CMSG_LOGOUT_CANCEL = 0xBADD, + CMSG_LOGOUT_CANCEL = 0x03C2, CMSG_LOGOUT_REQUEST = 0x1911, CMSG_LOG_DISCONNECT = 0x04D5, CMSG_LOOT = 0xBADD, @@ -375,18 +387,24 @@ enum OpcodeClient : uint32 CMSG_MOVE_FORCE_SWIM_SPEED_CHANGE_ACK = 0xBADD, CMSG_MOVE_FORCE_TURN_RATE_CHANGE_ACK = 0xBADD, CMSG_MOVE_FORCE_WALK_SPEED_CHANGE_ACK = 0xBADD, - CMSG_MOVE_GRAVITY_DISABLE_ACK = 0xBADD, + CMSG_MOVE_GRAVITY_DISABLE_ACK = 0x0553, CMSG_MOVE_GRAVITY_ENABLE_ACK = 0xBADD, + CMSG_MOVE_HEARTBEAT = 0x19C1, CMSG_MOVE_HOVER_ACK = 0xBADD, + CMSG_MOVE_JUMP = 0x0282, CMSG_MOVE_KNOCK_BACK_ACK = 0xBADD, + CMSG_MOVE_FALL_LAND = 0x0D54, CMSG_MOVE_NOT_ACTIVE_MOVER = 0xBADD, CMSG_MOVE_SET_CAN_FLY = 0xBADD, CMSG_MOVE_SET_CAN_FLY_ACK = 0xBADD, CMSG_MOVE_SET_CAN_TRANSITION_BETWEEN_SWIM_AND_FLY_ACK = 0xBADD, - CMSG_MOVE_SET_COLLISION_HEIGHT_ACK = 0xBADD, + CMSG_MOVE_SET_COLLISION_HEIGHT_ACK = 0x0141, CMSG_MOVE_SET_RELATIVE_POSITION = 0xBADD, CMSG_MOVE_SET_VEHICLE_REC_ID_ACK = 0xBADD, CMSG_MOVE_SPLINE_DONE = 0xBADD, + CMSG_MOVE_START_BACKWARD = 0x0583, + CMSG_MOVE_START_FORWARD = 0x0521, + CMSG_MOVE_STOP = 0x0513, CMSG_MOVE_TIME_SKIPPED = 0x19C2, CMSG_MOVE_TOGGLE_COLLISION_ACK = 0xBADD, CMSG_MOVE_WATER_WALK_ACK = 0xBADD, @@ -409,7 +427,7 @@ enum OpcodeClient : uint32 CMSG_PETITION_SHOW_SIGNATURES = 0xBADD, CMSG_PETITION_SIGN = 0xBADD, CMSG_PET_ABANDON = 0xBADD, - CMSG_PET_ACTION = 0xBADD, + CMSG_PET_ACTION = 0x133A, CMSG_PET_CANCEL_AURA = 0xBADD, CMSG_PET_CAST_SPELL = 0xBADD, CMSG_PET_LEARN_TALENT = 0xBADD, @@ -453,11 +471,11 @@ enum OpcodeClient : uint32 CMSG_QUEST_NPC_QUERY = 0x0B81, CMSG_QUEST_POI_QUERY = 0x0BD9, CMSG_QUEST_QUERY = 0x09A6, - CMSG_RANDOMIZE_CHAR_NAME = 0xBADD, + CMSG_QUEUED_MESSAGES_END = 0x04DF, + CMSG_RANDOMIZE_CHAR_NAME = 0x1981, CMSG_READ_ITEM = 0xBADD, CMSG_REALM_SPLIT = 0xBADD, CMSG_RECLAIM_CORPSE = 0xBADD, - CMSG_REDIRECTION_AUTH_PROOF = 0x0485, CMSG_REFORGE_ITEM = 0xBADD, CMSG_REORDER_CHARACTERS = 0x0DAA, CMSG_REPAIR_ITEM = 0xBADD, @@ -481,7 +499,7 @@ enum OpcodeClient : uint32 CMSG_REQUEST_VEHICLE_NEXT_SEAT = 0xBADD, CMSG_REQUEST_VEHICLE_PREV_SEAT = 0xBADD, CMSG_REQUEST_VEHICLE_SWITCH_SEAT = 0xBADD, - CMSG_RESET_FACTION_CHEAT = 0x0C56, + CMSG_RESET_FACTION_CHEAT = 0xBADD, CMSG_RESET_INSTANCES = 0xBADD, CMSG_RESURRECT_RESPONSE = 0xBADD, CMSG_RETURN_TO_GRAVEYARD = 0xBADD, @@ -513,15 +531,16 @@ enum OpcodeClient : uint32 CMSG_SET_FACTION_INACTIVE = 0xBADD, CMSG_SET_GUILD_BANK_TEXT = 0xBADD, CMSG_SET_LFG_COMMENT = 0xBADD, + CMSG_SET_LOOT_SPECIALIZATION = 0x0226, CMSG_SET_PET_SLOT = 0xBADD, CMSG_SET_PLAYER_DECLINED_NAMES = 0xBADD, CMSG_SET_PREFERED_CEMETERY = 0xBADD, - CMSG_SET_PRIMARY_TALENT_TREE = 0xBADD, - CMSG_SET_RAID_DIFFICULTY = 0x04DF, + CMSG_SET_RAID_DIFFICULTY = 0xBADD, CMSG_SET_RELATIVE_POSITION = 0xBADD, CMSG_SET_SAVED_INSTANCE_EXTEND = 0xBADD, CMSG_SET_SELECTION = 0x05BD, CMSG_SET_SKILL_CHEAT = 0xBADD, + CMSG_SET_SPECIALIZATION = 0x0AC5, CMSG_SET_TAXI_BENCHMARK_MODE = 0xBADD, CMSG_SET_TITLE = 0xBADD, CMSG_SET_TRADE_CURRENCY = 0xBADD, @@ -529,10 +548,10 @@ enum OpcodeClient : uint32 CMSG_SET_TRADE_ITEM = 0xBADD, CMSG_SET_VEHICLE_REC_ID_ACK = 0xBADD, CMSG_SET_WATCHED_FACTION = 0xBADD, - CMSG_SHOWING_CLOAK = 0xBADD, - CMSG_SHOWING_HELM = 0xBADD, + CMSG_SHOWING_CLOAK = 0x0132, + CMSG_SHOWING_HELM = 0x11E1, CMSG_SOCKET_GEMS = 0xBADD, - CMSG_SPELLCLICK = 0xBADD, + CMSG_SPELLCLICK = 0x0BC2, CMSG_SPIRIT_HEALER_ACTIVATE = 0xBADD, CMSG_SPLIT_ITEM = 0xBADD, CMSG_STANDSTATECHANGE = 0xBADD, @@ -543,7 +562,8 @@ enum OpcodeClient : uint32 CMSG_SUBMIT_COMPLAIN = 0xBADD, CMSG_SUGGESTION_SUBMIT = 0xBADD, CMSG_SUMMON_RESPONSE = 0xBADD, - CMSG_SUSPEND_TOKEN = 0x0142, + CMSG_SUSPEND_COMMS_ACK = 0x0C56, + CMSG_SUSPEND_TOKEN_RESPONSE = 0xBADD, CMSG_SWAP_INV_ITEM = 0xBADD, CMSG_SWAP_ITEM = 0xBADD, CMSG_SYNC_DANCE = 0xBADD, @@ -561,7 +581,7 @@ enum OpcodeClient : uint32 CMSG_TOTEM_DESTROYED = 0xBADD, CMSG_TRAINER_BUY_SPELL = 0xBADD, CMSG_TRAINER_LIST = 0xBADD, - CMSG_TRANSMOGRIFY_ITEMS = 0xBADD, + CMSG_TRANSMOGRIFY_ITEMS = 0x0A85, CMSG_TRIGGER_CINEMATIC_CHEAT = 0xBADD, CMSG_TURN_IN_PETITION = 0xBADD, CMSG_TUTORIAL_CLEAR = 0xBADD, @@ -580,10 +600,10 @@ enum OpcodeClient : uint32 CMSG_USE_ITEM = 0xBADD, CMSG_VIOLENCE_LEVEL = 0x098D, CMSG_VOICE_SESSION_ENABLE = 0xBADD, - CMSG_VOID_STORAGE_QUERY = 0xBADD, - CMSG_VOID_STORAGE_TRANSFER = 0xBADD, + CMSG_VOID_STORAGE_QUERY = 0x019E, + CMSG_VOID_STORAGE_TRANSFER = 0x0463, CMSG_VOID_STORAGE_UNLOCK = 0xBADD, - CMSG_VOID_SWAP_ITEM = 0xBADD, + CMSG_VOID_SWAP_ITEM = 0x0619, CMSG_WARDEN_DATA = 0x0BA1, CMSG_WARGAME_ACCEPT = 0xBADD, CMSG_WARGAME_START = 0xBADD, @@ -593,9 +613,6 @@ enum OpcodeClient : uint32 CMSG_WORLD_TELEPORT = 0xBADD, CMSG_WRAP_ITEM = 0xBADD, CMSG_ZONEUPDATE = 0xBADD, - MSG_AUCTION_HELLO = 0xBADD, - MSG_CHANNEL_START = 0xBADD, // SMSG only? - MSG_CHANNEL_UPDATE = 0xBADD, // SMSG only? MSG_CORPSE_QUERY = 0xBADD, MSG_GM_BIND_OTHER = 0xBADD, MSG_GM_SHOWLABEL = 0xBADD, @@ -604,9 +621,6 @@ enum OpcodeClient : uint32 MSG_LIST_STABLED_PETS = 0xBADD, MSG_MINIMAP_PING = 0xBADD, MSG_MOVE_CHARM_TELEPORT_CHEAT = 0xBADD, - MSG_MOVE_FALL_LAND = 0xBADD, - MSG_MOVE_HEARTBEAT = 0xBADD, - MSG_MOVE_JUMP = 0xBADD, MSG_MOVE_SET_ALL_SPEED_CHEAT = 0xBADD, MSG_MOVE_SET_COLLISION_HEIGHT = 0xBADD, MSG_MOVE_SET_FACING = 0xBADD, @@ -622,9 +636,7 @@ enum OpcodeClient : uint32 MSG_MOVE_SET_WALK_MODE = 0xBADD, MSG_MOVE_SET_WALK_SPEED_CHEAT = 0xBADD, MSG_MOVE_START_ASCEND = 0xBADD, - MSG_MOVE_START_BACKWARD = 0xBADD, MSG_MOVE_START_DESCEND = 0xBADD, - MSG_MOVE_START_FORWARD = 0xBADD, MSG_MOVE_START_PITCH_DOWN = 0xBADD, MSG_MOVE_START_PITCH_UP = 0xBADD, MSG_MOVE_START_STRAFE_LEFT = 0xBADD, @@ -632,7 +644,6 @@ enum OpcodeClient : uint32 MSG_MOVE_START_SWIM = 0xBADD, MSG_MOVE_START_TURN_LEFT = 0xBADD, MSG_MOVE_START_TURN_RIGHT = 0xBADD, - MSG_MOVE_STOP = 0xBADD, MSG_MOVE_STOP_ASCEND = 0xBADD, MSG_MOVE_STOP_PITCH = 0xBADD, MSG_MOVE_STOP_STRAFE = 0xBADD, @@ -666,11 +677,12 @@ enum OpcodeClient : uint32 MSG_TALENT_WIPE_CONFIRM = 0xBADD }; -// SMSGs 6.0.3.19103 +// SMSGs 6.0.3.19116 enum OpcodeServer : uint32 { SMSG_ACCOUNT_DATA_TIMES = 0x0120, SMSG_ACCOUNT_INFO_RESPONSE = 0xBADD, + SMSG_ACCOUNT_MOUNT_UPDATE = 0x0140, SMSG_ACCOUNT_RESTRICTED_WARNING = 0xBADD, SMSG_ACHIEVEMENT_DELETED = 0xBADD, SMSG_ACHIEVEMENT_EARNED = 0xBADD, @@ -678,7 +690,7 @@ enum OpcodeServer : uint32 SMSG_ACTIVATETAXIREPLY = 0xBADD, SMSG_ADDON_INFO = 0x1D9F, SMSG_ADD_RUNE_POWER = 0xBADD, - SMSG_AI_REACTION = 0xBADD, + SMSG_AI_REACTION = 0x0BA1, SMSG_ALL_ACHIEVEMENT_DATA = 0xBADD, SMSG_ALL_ACHIEVEMENT_DATA_ACCOUNT = 0x0123, SMSG_ALL_ACHIEVEMENT_DATA_PLAYER = 0x0030, @@ -686,7 +698,6 @@ enum OpcodeServer : uint32 SMSG_AREA_TRIGGER_MESSAGE = 0xBADD, SMSG_AREA_TRIGGER_MOVEMENT_UPDATE = 0xBADD, SMSG_ARENA_ERROR = 0xBADD, - SMSG_ARENA_SEASON_WORLD_STATE = 0x09E3, SMSG_ARENA_UNIT_DESTROYED = 0xBADD, SMSG_ARENA_TEAM_CHANGE_FAILED_QUEUED = 0xBADD, SMSG_ARENA_TEAM_COMMAND_RESULT = 0xBADD, @@ -731,7 +742,7 @@ enum OpcodeServer : uint32 SMSG_BATTLEFIELD_MGR_STATE_CHANGE = 0xBADD, SMSG_BATTLEFIELD_PLAYER_POSITIONS = 0xBADD, SMSG_BATTLEFIELD_PORT_DENIED = 0xBADD, - SMSG_BATTLEFIELD_RATED_INFO = 0xBADD, + SMSG_BATTLEFIELD_RATED_INFO = 0x1F0A, SMSG_BATTLEFIELD_STATUS = 0xBADD, SMSG_BATTLEFIELD_STATUS_QUEUED = 0xBADD, SMSG_BATTLEFIELD_STATUS_ACTIVE = 0xBADD, @@ -741,7 +752,12 @@ enum OpcodeServer : uint32 SMSG_BATTLEGROUND_INFO_THROTTLED = 0xBADD, SMSG_BATTLEGROUND_PLAYER_JOINED = 0xBADD, SMSG_BATTLEGROUND_PLAYER_LEFT = 0xBADD, + SMSG_BATTLE_PAY_GET_DISTRIBUTION_LIST_RESPONSE = 0x0F2A, + SMSG_BATTLE_PAY_GET_PRODUCT_LIST_RESPONSE = 0x12A4, + SMSG_BATTLE_PAY_GET_PURCHASE_LIST_RESPONSE = 0x168A, SMSG_BATTLE_PET_JOURNAL = 0x19A2, + SMSG_BATTLE_PET_JOURNAL_LOCK_ACQUIRED = 0x01A3, + SMSG_BATTLE_PET_NAME_QUERY_RESPONSE = 0x09EC, SMSG_BINDER_CONFIRM = 0xBADD, SMSG_BINDPOINTUPDATE = 0x0A30, SMSG_BINDZONEREPLY = 0xBADD, @@ -780,6 +796,8 @@ enum OpcodeServer : uint32 SMSG_CHANNEL_MEMBER_COUNT = 0xBADD, SMSG_CHANNEL_NOTIFY = 0x0643, SMSG_CHANNEL_NOTIFY_JOINED = 0x1602, + SMSG_CHANNEL_START = 0x016C, + SMSG_CHANNEL_UPDATE = 0x19DB, SMSG_CHARACTER_LOGIN_FAILED = 0xBADD, SMSG_CHAR_CREATE = 0x0107, SMSG_CHAR_CUSTOMIZE = 0xBADD, @@ -819,6 +837,7 @@ enum OpcodeServer : uint32 SMSG_COMSAT_DISCONNECT = 0xBADD, SMSG_COMSAT_RECONNECT_TRY = 0xBADD, SMSG_CONTACT_LIST = 0xBADD, + SMSG_CONTACT_STATUS = 0x1BEA, SMSG_CONVERT_RUNE = 0xBADD, SMSG_COOLDOWN_CHEAT = 0xBADD, SMSG_COOLDOWN_EVENT = 0xBADD, @@ -837,6 +856,7 @@ enum OpcodeServer : uint32 SMSG_DAMAGE_CALC_LOG = 0xBADD, SMSG_DAMAGE_DONE_OBSOLETE = 0xBADD, SMSG_DANCE_QUERY_RESPONSE = 0xBADD, + SMSG_DANCE_STUDIO_CREATE_RESULT = 0x178D, SMSG_DB_REPLY = 0x1939, SMSG_DEATH_RELEASE_LOC = 0xBADD, SMSG_DEBUG_RUNE_REGEN = 0xBADD, @@ -882,7 +902,6 @@ enum OpcodeServer : uint32 SMSG_FORCED_DEATH_UPDATE = 0xBADD, SMSG_FORCE_ANIM = 0xBADD, SMSG_FORCE_DISPLAY_UPDATE = 0xBADD, - SMSG_FORCE_SEND_QUEUED_PACKETS = 0xBADD, SMSG_FORCE_SET_VEHICLE_REC_ID = 0xBADD, SMSG_FORGE_MASTER_SET = 0xBADD, SMSG_FRIEND_STATUS = 0xBADD, @@ -926,7 +945,7 @@ enum OpcodeServer : uint32 SMSG_GUILD_ACHIEVEMENT_MEMBERS = 0xBADD, SMSG_GUILD_BANK_LIST = 0xBADD, SMSG_GUILD_BANK_LOG_QUERY_RESULT = 0xBADD, - SMSG_GUILD_BANK_MONEY_WITHDRAWN = 0xBADD, + SMSG_GUILD_BANK_MONEY_WITHDRAWN = 0x1047, SMSG_GUILD_BANK_QUERY_TEXT_RESULT = 0xBADD, SMSG_GUILD_CANCEL = 0xBADD, SMSG_GUILD_CHALLENGE_COMPLETED = 0xBADD, @@ -955,7 +974,7 @@ enum OpcodeServer : uint32 SMSG_GUILD_NEWS_DELETED = 0xBADD, SMSG_GUILD_NEWS_UPDATE = 0xBADD, SMSG_GUILD_PARTY_STATE_RESPONSE = 0x1225, - SMSG_GUILD_PERMISSIONS_QUERY_RESULTS = 0xBADD, + SMSG_GUILD_PERMISSIONS_QUERY_RESULTS = 0x1827, SMSG_GUILD_QUERY_RESPONSE = 0x1046, SMSG_GUILD_RANK = 0x1218, SMSG_GUILD_RANKS_UPDATE = 0xBADD, @@ -1041,7 +1060,7 @@ enum OpcodeServer : uint32 SMSG_LOAD_CUF_PROFILES = 0x1530, SMSG_LOGIN_SETTIMESPEED = 0x09AA, SMSG_LOGIN_VERIFY_WORLD = 0x0B19, - SMSG_LOGOUT_CANCEL_ACK = 0xBADD, + SMSG_LOGOUT_CANCEL_ACK = 0x0FAD, SMSG_LOGOUT_COMPLETE = 0x0B21, SMSG_LOGOUT_RESPONSE = 0x052D, SMSG_LOG_XPGAIN = 0xBADD, @@ -1081,16 +1100,16 @@ enum OpcodeServer : uint32 SMSG_MOVE_COLLISION_DISABLE = 0xBADD, SMSG_MOVE_COLLISION_ENABLE = 0xBADD, SMSG_MOVE_FEATHER_FALL = 0xBADD, - SMSG_MOVE_GRAVITY_DISABLE = 0xBADD, + SMSG_MOVE_GRAVITY_DISABLE = 0x02C6, SMSG_MOVE_GRAVITY_ENABLE = 0xBADD, SMSG_MOVE_KNOCK_BACK = 0xBADD, SMSG_MOVE_LAND_WALK = 0xBADD, SMSG_MOVE_NORMAL_FALL = 0xBADD, - SMSG_MOVE_ROOT = 0xBADD, + SMSG_MOVE_ROOT = 0x1B5A, SMSG_MOVE_SET_ACTIVE_MOVER = 0xBADD, SMSG_MOVE_SET_CAN_FLY = 0xBADD, SMSG_MOVE_SET_CAN_TRANSITION_BETWEEN_SWIM_AND_FLY = 0xBADD, - SMSG_MOVE_SET_COLLISION_HEIGHT = 0xBADD, + SMSG_MOVE_SET_COLLISION_HEIGHT = 0x008D, SMSG_MOVE_SET_COMPOUND_STATE = 0xBADD, SMSG_MOVE_SET_FLIGHT_BACK_SPEED = 0xBADD, SMSG_MOVE_SET_FLIGHT_SPEED = 0xBADD, @@ -1118,7 +1137,7 @@ enum OpcodeServer : uint32 SMSG_MOVE_UPDATE_RUN_SPEED = 0xBADD, SMSG_MOVE_UPDATE_SWIM_BACK_SPEED = 0xBADD, SMSG_MOVE_UPDATE_SWIM_SPEED = 0xBADD, - SMSG_MOVE_UPDATE_TELEPORT = 0xBADD, + SMSG_MOVE_UPDATE_TELEPORT = 0x03D5, SMSG_MOVE_UPDATE_TURN_RATE = 0xBADD, SMSG_MOVE_UPDATE_WALK_SPEED = 0xBADD, SMSG_MOVE_WATER_WALK = 0xBADD, @@ -1134,7 +1153,7 @@ enum OpcodeServer : uint32 SMSG_NPC_TEXT_UPDATE = 0x1122, SMSG_NPC_WONT_TALK = 0xBADD, SMSG_OFFER_PETITION_ERROR = 0xBADD, - SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA = 0xBADD, + SMSG_ON_CANCEL_EXPECTED_RIDE_VEHICLE_AURA = 0x053F, SMSG_OPEN_CONTAINER = 0xBADD, SMSG_OPEN_LFG_DUNGEON_FINDER = 0xBADD, SMSG_OVERRIDE_LIGHT = 0xBADD, @@ -1165,7 +1184,7 @@ enum OpcodeServer : uint32 SMSG_PET_REMOVED_SPELL = 0xBADD, SMSG_PET_RENAMEABLE = 0xBADD, SMSG_PET_SLOT_UPDATED = 0xBADD, - SMSG_PET_SPELLS = 0xBADD, + SMSG_PET_SPELLS = 0x0174, SMSG_PET_TAME_FAILURE = 0xBADD, SMSG_PET_UPDATE_COMBO_POINTS = 0xBADD, SMSG_PLAYED_TIME = 0xBADD, @@ -1179,7 +1198,7 @@ enum OpcodeServer : uint32 SMSG_PLAY_MUSIC = 0xBADD, SMSG_PLAY_OBJECT_SOUND = 0xBADD, SMSG_PLAY_ONE_SHOT_ANIM_KIT = 0xBADD, - SMSG_PLAY_SOUND = 0xBADD, + SMSG_PLAY_SOUND = 0x02D2, SMSG_PLAY_SPELL_VISUAL = 0xBADD, SMSG_PLAY_SPELL_VISUAL_KIT = 0xBADD, SMSG_PLAY_TIME_WARNING = 0xBADD, @@ -1192,8 +1211,9 @@ enum OpcodeServer : uint32 SMSG_PVP_CREDIT = 0xBADD, SMSG_PVP_LOG_DATA = 0xBADD, SMSG_PVP_OPTIONS_ENABLED = 0xBADD, + SMSG_PVP_SEASON = 0x09E3, SMSG_QUERY_QUESTS_COMPLETED_RESPONSE = 0xBADD, - SMSG_QUERY_TIME_RESPONSE = 0xBADD, + SMSG_QUERY_TIME_RESPONSE = 0x1DB0, SMSG_QUESTGIVER_OFFER_REWARD = 0xBADD, SMSG_QUESTGIVER_QUEST_COMPLETE = 0xBADD, SMSG_QUESTGIVER_QUEST_DETAILS = 0x15B3, @@ -1221,7 +1241,7 @@ enum OpcodeServer : uint32 SMSG_RAID_MARKERS_CHANGED = 0xBADD, SMSG_RAID_READY_CHECK_THROTTLED_ERROR = 0xBADD, SMSG_RAID_SUMMON_FAILED = 0xBADD, - SMSG_RANDOMIZE_CHAR_NAME = 0xBADD, + SMSG_RANDOMIZE_CHAR_NAME = 0x0D8F, SMSG_RATED_BG_RATING = 0xBADD, SMSG_RATED_BG_STATS = 0xBADD, SMSG_READ_ITEM_FAILED = 0xBADD, @@ -1243,6 +1263,7 @@ enum OpcodeServer : uint32 SMSG_RESET_FAILED_NOTIFY = 0xBADD, SMSG_RESISTLOG = 0xBADD, SMSG_RESPOND_INSPECT_ACHIEVEMENTS = 0xBADD, + SMSG_RESUME_COMMS = 0x07C9, SMSG_RESURRECT_FAILED = 0xBADD, SMSG_RESURRECT_REQUEST = 0xBADD, SMSG_RESYNC_RUNES = 0xBADD, @@ -1263,13 +1284,13 @@ enum OpcodeServer : uint32 SMSG_SET_FACTION_STANDING = 0xBADD, SMSG_SET_FACTION_VISIBLE = 0xBADD, SMSG_SET_FLAT_SPELL_MODIFIER = 0x1884, - SMSG_SET_FORCED_REACTIONS = 0xBADD, + SMSG_SET_FORCED_REACTIONS = 0x09A9, SMSG_SET_MELEE_ANIM_KIT = 0xBADD, SMSG_SET_MOVEMENT_ANIM_KIT = 0xBADD, SMSG_SET_PCT_SPELL_MODIFIER = 0x113C, SMSG_SET_PHASE_SHIFT = 0x00D1, SMSG_SET_PLAYER_DECLINED_NAMES_RESULT = 0xBADD, - SMSG_SET_PLAY_HOVER_ANIM = 0xBADD, + SMSG_SET_PLAY_HOVER_ANIM = 0x02D4, SMSG_SET_PROFICIENCY = 0x00D3, SMSG_SET_PROJECTILE_POSITION = 0xBADD, SMSG_SET_TIME_ZONE_INFORMATION = 0x153E, @@ -1299,11 +1320,11 @@ enum OpcodeServer : uint32 SMSG_SPELL_FAILURE = 0xBADD, SMSG_SPELL_GO = 0x1161, SMSG_SPELL_START = 0x0803, - SMSG_SPELL_UPDATE_CHAIN_TARGETS = 0xBADD, + SMSG_SPELL_UPDATE_CHAIN_TARGETS = 0x0374, SMSG_SPIRIT_HEALER_CONFIRM = 0xBADD, SMSG_SPLINE_MOVE_COLLISION_DISABLE = 0xBADD, SMSG_SPLINE_MOVE_COLLISION_ENABLE = 0xBADD, - SMSG_SPLINE_MOVE_GRAVITY_DISABLE = 0xBADD, + SMSG_SPLINE_MOVE_GRAVITY_DISABLE = 0x03B2, SMSG_SPLINE_MOVE_GRAVITY_ENABLE = 0xBADD, SMSG_SPLINE_MOVE_ROOT = 0xBADD, SMSG_SPLINE_MOVE_SET_ANIM = 0xBADD, @@ -1328,10 +1349,10 @@ enum OpcodeServer : uint32 SMSG_SPLINE_MOVE_STOP_SWIM = 0xBADD, SMSG_SPLINE_MOVE_UNROOT = 0xBADD, SMSG_SPLINE_MOVE_UNSET_FLYING = 0xBADD, - SMSG_SPLINE_MOVE_UNSET_HOVER = 0xBADD, + SMSG_SPLINE_MOVE_UNSET_HOVER = 0x1959, SMSG_SPLINE_MOVE_WATER_WALK = 0xBADD, SMSG_STABLE_RESULT = 0xBADD, - SMSG_STANDSTATE_UPDATE = 0xBADD, + SMSG_STANDSTATE_UPDATE = 0x1311, SMSG_START_MIRROR_TIMER = 0xBADD, SMSG_START_TIMER = 0xBADD, SMSG_STOP_DANCE = 0xBADD, @@ -1342,7 +1363,7 @@ enum OpcodeServer : uint32 SMSG_SUPERCEDED_SPELL = 0xBADD, SMSG_SUPPRESS_NPC_GREETINGS = 0xBADD, SMSG_SUSPEND_COMMS = 0x076A, - SMSG_SUSPEND_TOKEN_RESPONSE = 0x12A2, + SMSG_SUSPEND_TOKEN = 0x12A2, SMSG_TALENTS_ERROR = 0xBADD, SMSG_TALENTS_INFO = 0x012D, SMSG_TALENTS_INVOLUNTARILY_RESET = 0xBADD, @@ -1393,11 +1414,11 @@ enum OpcodeServer : uint32 SMSG_VOICE_SESSION_LEAVE = 0xBADD, SMSG_VOICE_SESSION_ROSTER_UPDATE = 0xBADD, SMSG_VOICE_SET_TALKER_MUTED = 0xBADD, - SMSG_VOID_ITEM_SWAP_RESPONSE = 0xBADD, - SMSG_VOID_STORAGE_CONTENTS = 0xBADD, + SMSG_VOID_ITEM_SWAP_RESPONSE = 0x1131, + SMSG_VOID_STORAGE_CONTENTS = 0x0108, SMSG_VOID_STORAGE_FAILED = 0xBADD, - SMSG_VOID_STORAGE_TRANSFER_CHANGES = 0xBADD, - SMSG_VOID_TRANSFER_RESULT = 0xBADD, + SMSG_VOID_STORAGE_TRANSFER_CHANGES = 0x0321, + SMSG_VOID_TRANSFER_RESULT = 0x0539, SMSG_WAIT_QUEUE_FINISH = 0xBADD, SMSG_WAIT_QUEUE_UPDATE = 0xBADD, SMSG_WARDEN_DATA = 0x0BEC, diff --git a/src/server/game/Server/Protocol/PacketLog.cpp b/src/server/game/Server/Protocol/PacketLog.cpp index fd7e9278bdd..2a94aa03eba 100644 --- a/src/server/game/Server/Protocol/PacketLog.cpp +++ b/src/server/game/Server/Protocol/PacketLog.cpp @@ -98,13 +98,13 @@ void PacketLog::Initialize() } } -void PacketLog::LogPacket(WorldPacket const& packet, Direction direction, boost::asio::ip::address const& addr, uint16 port) +void PacketLog::LogPacket(WorldPacket const& packet, Direction direction, boost::asio::ip::address const& addr, uint16 port, ConnectionType connectionType) { std::lock_guard<std::mutex> lock(_logPacketLock); PacketHeader header; *reinterpret_cast<uint32*>(header.Direction) = direction == CLIENT_TO_SERVER ? 0x47534d43 : 0x47534d53; - header.ConnectionId = 0; + header.ConnectionId = connectionType; header.ArrivalTicks = getMSTime(); header.OptionalDataSize = sizeof(header.OptionalData); diff --git a/src/server/game/Server/Protocol/PacketLog.h b/src/server/game/Server/Protocol/PacketLog.h index 06674b88b9e..89b593ef9d4 100644 --- a/src/server/game/Server/Protocol/PacketLog.h +++ b/src/server/game/Server/Protocol/PacketLog.h @@ -48,7 +48,7 @@ class PacketLog void Initialize(); bool CanLogPacket() const { return (_file != NULL); } - void LogPacket(WorldPacket const& packet, Direction direction, boost::asio::ip::address const& addr, uint16 port); + void LogPacket(WorldPacket const& packet, Direction direction, boost::asio::ip::address const& addr, uint16 port, ConnectionType connectionType); private: FILE* _file; diff --git a/src/server/game/Server/WorldPacket.h b/src/server/game/Server/WorldPacket.h index e7d6d4fb5b1..65b2f6fcae1 100644 --- a/src/server/game/Server/WorldPacket.h +++ b/src/server/game/Server/WorldPacket.h @@ -27,17 +27,18 @@ class WorldPacket : public ByteBuffer { public: // just container for later use - WorldPacket() : ByteBuffer(0), m_opcode(UNKNOWN_OPCODE) + WorldPacket() : ByteBuffer(0), m_opcode(UNKNOWN_OPCODE), _connection(CONNECTION_TYPE_REALM) { } - explicit WorldPacket(uint32 opcode, size_t res = 200) : ByteBuffer(res), m_opcode(opcode) { } + WorldPacket(uint32 opcode, size_t res = 200, ConnectionType connection = CONNECTION_TYPE_REALM) : ByteBuffer(res), + m_opcode(opcode), _connection(connection) { } - WorldPacket(WorldPacket&& packet) : ByteBuffer(std::move(packet)), m_opcode(packet.m_opcode) + WorldPacket(WorldPacket&& packet) : ByteBuffer(std::move(packet)), m_opcode(packet.m_opcode), _connection(packet._connection) { } - WorldPacket(WorldPacket const& right) : ByteBuffer(right), m_opcode(right.m_opcode) + WorldPacket(WorldPacket const& right) : ByteBuffer(right), m_opcode(right.m_opcode), _connection(right._connection) { } @@ -46,26 +47,31 @@ class WorldPacket : public ByteBuffer if (this != &right) { m_opcode = right.m_opcode; + _connection = right._connection; ByteBuffer::operator =(right); } return *this; } - WorldPacket(uint32 opcode, MessageBuffer&& buffer) : ByteBuffer(std::move(buffer)), m_opcode(opcode) { } + WorldPacket(uint32 opcode, MessageBuffer&& buffer, ConnectionType connection) : ByteBuffer(std::move(buffer)), m_opcode(opcode), _connection(connection) { } - void Initialize(uint32 opcode, size_t newres = 200) + void Initialize(uint32 opcode, size_t newres = 200, ConnectionType connection = CONNECTION_TYPE_REALM) { clear(); _storage.reserve(newres); m_opcode = opcode; + _connection = connection; } uint32 GetOpcode() const { return m_opcode; } void SetOpcode(uint32 opcode) { m_opcode = opcode; } + ConnectionType GetConnection() const { return _connection; } + protected: uint32 m_opcode; + ConnectionType _connection; }; #endif diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp index 0164ad9a575..c0f97733d33 100644 --- a/src/server/game/Server/WorldSession.cpp +++ b/src/server/game/Server/WorldSession.cpp @@ -106,7 +106,6 @@ WorldSession::WorldSession(uint32 id, uint32 battlenetAccountId, std::shared_ptr AntiDOS(this), m_GUIDLow(UI64LIT(0)), _player(NULL), - m_Socket(sock), _security(sec), _accountId(id), _battlenetAccountId(battlenetAccountId), @@ -114,7 +113,6 @@ WorldSession::WorldSession(uint32 id, uint32 battlenetAccountId, std::shared_ptr _warden(NULL), _logoutTime(0), m_inQueue(false), - m_playerLoading(false), m_playerLogout(false), m_playerRecentlyLogout(false), m_playerSave(false), @@ -140,17 +138,9 @@ WorldSession::WorldSession(uint32 id, uint32 battlenetAccountId, std::shared_ptr LoginDatabase.PExecute("UPDATE account SET online = 1 WHERE id = %u;", GetAccountId()); // One-time query } - InitializeQueryCallbackParameters(); + m_Socket[CONNECTION_TYPE_REALM] = sock; - _compressionStream = new z_stream(); - _compressionStream->zalloc = (alloc_func)NULL; - _compressionStream->zfree = (free_func)NULL; - _compressionStream->opaque = (voidpf)NULL; - _compressionStream->avail_in = 0; - _compressionStream->next_in = NULL; - int32 z_res = deflateInit2(_compressionStream, sWorld->getIntConfig(CONFIG_COMPRESSION), Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY); - if (z_res != Z_OK) - TC_LOG_ERROR("network", "Can't initialize packet compression (zlib: deflateInit) Error code: %i (%s)", z_res, zError(z_res)); + InitializeQueryCallbackParameters(); } /// WorldSession destructor @@ -161,10 +151,13 @@ WorldSession::~WorldSession() LogoutPlayer (true); /// - If have unclosed socket, close it - if (m_Socket) + for (uint8 i = 0; i < 2; ++i) { - m_Socket->CloseSocket(); - m_Socket = nullptr; + if (m_Socket[i]) + { + m_Socket[i]->CloseSocket(); + m_Socket[i].reset(); + } } delete _warden; @@ -176,12 +169,6 @@ WorldSession::~WorldSession() delete packet; LoginDatabase.PExecute("UPDATE account SET online = 0 WHERE id = %u;", GetAccountId()); // One-time query - - int32 z_res = deflateEnd(_compressionStream); - if (z_res != Z_OK && z_res != Z_DATA_ERROR) // Z_DATA_ERROR signals that internal state was BUSY - TC_LOG_ERROR("network", "Can't close packet compression stream (zlib: deflateEnd) Error code: %i (%s)", z_res, zError(z_res)); - - delete _compressionStream; } std::string const & WorldSession::GetPlayerName() const @@ -205,7 +192,7 @@ std::string WorldSession::GetPlayerInfo() const /// Send a packet to the client void WorldSession::SendPacket(WorldPacket const* packet, bool forced /*= false*/) { - if (!m_Socket) + if (!m_Socket[packet->GetConnection()]) return; if (packet->GetOpcode() == NULL_OPCODE) @@ -265,38 +252,7 @@ void WorldSession::SendPacket(WorldPacket const* packet, bool forced /*= false*/ sScriptMgr->OnPacketSend(this, *packet); - m_Socket->SendPacket(*packet); -} - -uint32 WorldSession::CompressPacket(uint8* buffer, WorldPacket const& packet) -{ - uint32 opcode = packet.GetOpcode(); - uint32 bufferSize = deflateBound(_compressionStream, packet.size() + sizeof(opcode)); - - _compressionStream->next_out = buffer; - _compressionStream->avail_out = bufferSize; - _compressionStream->next_in = (Bytef*)&opcode; - _compressionStream->avail_in = sizeof(uint32); - - int32 z_res = deflate(_compressionStream, Z_BLOCK); - if (z_res != Z_OK) - { - TC_LOG_ERROR("network", "Can't compress packet opcode (zlib: deflate) Error code: %i (%s, msg: %s)", z_res, zError(z_res), _compressionStream->msg); - return 0; - } - - _compressionStream->next_in = (Bytef*)packet.contents(); - _compressionStream->avail_in = packet.size(); - - z_res = deflate(_compressionStream, Z_SYNC_FLUSH); - if (z_res != Z_OK) - { - TC_LOG_ERROR("network", "Can't compress packet data (zlib: deflate) Error code: %i (%s, msg: %s)", z_res, zError(z_res), _compressionStream->msg); - return 0; - } - - - return bufferSize - _compressionStream->avail_out; + m_Socket[packet->GetConnection()]->SendPacket(*packet); } /// Add an incoming packet to the queue @@ -332,7 +288,7 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater) ///- Before we process anything: /// If necessary, kick the player from the character select screen if (IsConnectionIdle()) - m_Socket->CloseSocket(); + m_Socket[CONNECTION_TYPE_REALM]->CloseSocket(); ///- Retrieve packets from the receive queue and call the appropriate handlers /// not process packets if socket already closed @@ -349,7 +305,7 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater) uint32 processedPackets = 0; time_t currentTime = time(NULL); - while (m_Socket && !_recvQueue.empty() && _recvQueue.peek(true) != firstDelayedPacket && _recvQueue.next(packet, updater)) + while (m_Socket[CONNECTION_TYPE_REALM] && !_recvQueue.empty() && _recvQueue.peek(true) != firstDelayedPacket && _recvQueue.next(packet, updater)) { if (!AntiDOS.EvaluateOpcode(*packet, currentTime)) KickPlayer(); @@ -458,7 +414,7 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater) break; } - if (m_Socket && m_Socket->IsOpen() && _warden) + if (m_Socket[CONNECTION_TYPE_REALM] && m_Socket[CONNECTION_TYPE_REALM]->IsOpen() && _warden) _warden->Update(); ProcessQueryCallbacks(); @@ -469,23 +425,25 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater) { time_t currTime = time(NULL); ///- If necessary, log the player out - if (ShouldLogOut(currTime) && !m_playerLoading) + if (ShouldLogOut(currTime) && m_playerLoading.IsEmpty()) LogoutPlayer(true); - if (m_Socket && GetPlayer() && _warden) + if (m_Socket[CONNECTION_TYPE_REALM] && GetPlayer() && _warden) _warden->Update(); ///- Cleanup socket pointer if need - if (m_Socket && !m_Socket->IsOpen()) + if ((m_Socket[CONNECTION_TYPE_REALM] && !m_Socket[CONNECTION_TYPE_REALM]->IsOpen()) || + (m_Socket[CONNECTION_TYPE_INSTANCE] && !m_Socket[CONNECTION_TYPE_INSTANCE]->IsOpen())) { expireTime -= expireTime > diff ? diff : expireTime; if (expireTime < diff || forceExit || !GetPlayer()) { - m_Socket = nullptr; + m_Socket[CONNECTION_TYPE_REALM].reset(); + m_Socket[CONNECTION_TYPE_INSTANCE].reset(); } } - if (!m_Socket) + if (!m_Socket[CONNECTION_TYPE_REALM]) return false; //Will remove this session from the world session map } @@ -587,7 +545,7 @@ void WorldSession::LogoutPlayer(bool save) // remove player from the group if he is: // a) in group; b) not in raid group; c) logging out normally (not being kicked or disconnected) - if (_player->GetGroup() && !_player->GetGroup()->isRaidGroup() && m_Socket) + if (_player->GetGroup() && !_player->GetGroup()->isRaidGroup() && m_Socket[CONNECTION_TYPE_REALM]) _player->RemoveFromGroup(); //! Send update to group and reset stored max enchanting level @@ -621,8 +579,7 @@ void WorldSession::LogoutPlayer(bool save) //! Send the 'logout complete' packet to the client //! Client will respond by sending 3x CMSG_CANCEL_TRADE, which we currently dont handle - WorldPacket data(SMSG_LOGOUT_COMPLETE, 0); - SendPacket(&data); + SendPacket(WorldPackets::Character::LogoutComplete().Write()); TC_LOG_DEBUG("network", "SESSION: Sent SMSG_LOGOUT_COMPLETE Message"); //! Since each account can only have one online character at any given time, ensure all characters for active account are marked as offline @@ -631,19 +588,28 @@ void WorldSession::LogoutPlayer(bool save) CharacterDatabase.Execute(stmt); } + if (m_Socket[CONNECTION_TYPE_INSTANCE]) + { + m_Socket[CONNECTION_TYPE_INSTANCE]->CloseSocket(); + m_Socket[CONNECTION_TYPE_INSTANCE].reset(); + } + m_playerLogout = false; m_playerSave = false; m_playerRecentlyLogout = true; - LogoutRequest(0); + SetLogoutStartTime(0); } /// Kick a player out of the World void WorldSession::KickPlayer() { - if (m_Socket) + for (uint8 i = 0; i < 2; ++i) { - m_Socket->CloseSocket(); - forceExit = true; + if (m_Socket[i]) + { + m_Socket[i]->CloseSocket(); + forceExit = true; + } } } @@ -985,7 +951,7 @@ void WorldSession::ProcessQueryCallbacks() { _charEnumCallback.GetResult(result); - if (bool undelete = _charEnumCallback.GetParam()) + if (_charEnumCallback.GetParam()) HandleCharUndeleteEnum(result); else HandleCharEnum(result); diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index 6bda4e2d162..ec791a52ca6 100644 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -54,7 +54,6 @@ struct DeclinedName; struct ItemTemplate; struct MovementInfo; struct TradeStatusInfo; -struct z_stream_s; namespace lfg { @@ -84,8 +83,29 @@ namespace WorldPackets class CharacterCreate; class CharacterDelete; + class GenerateRandomCharacterName; + class ReorderCharacters; class UndeleteCharacter; class PlayerLogin; + class LogoutRequest; + class LogoutCancel; + class LoadingScreenNotify; + class QueryPlayerName; + } + + namespace Guild + { + class QueryGuildInfo; + } + + namespace Trade + { + class CancelTrade; + } + + namespace Misc + { + class ViolenceLevel; } } @@ -221,7 +241,7 @@ class WorldSession WorldSession(uint32 id, uint32 battlenetAccountId, std::shared_ptr<WorldSocket> sock, AccountTypes sec, uint8 expansion, time_t mute_time, LocaleConstant locale, uint32 recruiter, bool isARecruiter); ~WorldSession(); - bool PlayerLoading() const { return m_playerLoading; } + bool PlayerLoading() const { return !m_playerLoading.IsEmpty(); } bool PlayerLogout() const { return m_playerLogout; } bool PlayerLogoutWithSave() const { return m_playerLogout && m_playerSave; } bool PlayerRecentlyLoggedOut() const { return m_playerRecentlyLogout; } @@ -231,7 +251,7 @@ class WorldSession bool IsAddonRegistered(const std::string& prefix) const; void SendPacket(WorldPacket const* packet, bool forced = false); - uint32 CompressPacket(uint8* buffer, WorldPacket const& packet); + void AddInstanceConnection(std::shared_ptr<WorldSocket> sock) { m_Socket[1] = sock; } void SendNotification(const char *format, ...) ATTR_PRINTF(2, 3); void SendNotification(uint32 string_id, ...); @@ -270,7 +290,7 @@ class WorldSession bool isLogingOut() const { return _logoutTime || m_playerLogout; } /// Engage the logout process for the user - void LogoutRequest(time_t requestTime) + void SetLogoutStartTime(time_t requestTime) { _logoutTime = requestTime; } @@ -417,8 +437,6 @@ class WorldSession uint32 GetRecruiterId() const { return recruiterId; } bool IsARecruiter() const { return isRecruiter; } - z_stream_s* GetCompressionStream() { return _compressionStream; } - public: // opcodes handlers void Handle_NULL(WorldPacket& recvPacket); // not used @@ -434,15 +452,16 @@ class WorldSession void HandleCharCreateOpcode(WorldPackets::Character::CharacterCreate& charCreate); void HandleCharCreateCallback(PreparedQueryResult result, WorldPackets::Character::CharacterCreateInfo* createInfo); void HandlePlayerLoginOpcode(WorldPackets::Character::PlayerLogin& playerLogin); - void HandleLoadScreenOpcode(WorldPacket& recvPacket); + void HandleContinuePlayerLogin(); + void HandleLoadScreenOpcode(WorldPackets::Character::LoadingScreenNotify& loadingScreenNotify); void HandlePlayerLogin(LoginQueryHolder * holder); void HandleCharRenameOpcode(WorldPacket& recvData); void HandleCharRenameCallBack(PreparedQueryResult result, WorldPackets::Character::CharacterRenameInfo const* renameInfo); void HandleSetPlayerDeclinedNames(WorldPacket& recvData); void HandleAlterAppearance(WorldPacket& recvData); void HandleCharFactionOrRaceChange(WorldPacket& recvData); - void HandleRandomizeCharNameOpcode(WorldPacket& recvData); - void HandleReorderCharacters(WorldPacket& recvData); + void HandleRandomizeCharNameOpcode(WorldPackets::Character::GenerateRandomCharacterName& packet); + void HandleReorderCharacters(WorldPackets::Character::ReorderCharacters& reorderChars); void HandleOpeningCinematic(WorldPacket& recvData); void HandleUndeleteCooldownStatusQuery(WorldPacket& /*recvData*/); void HandleUndeleteCooldownStatusCallback(PreparedQueryResult result); @@ -506,9 +525,8 @@ class WorldSession void HandleLootReleaseOpcode(WorldPacket& recvPacket); void HandleLootMasterGiveOpcode(WorldPacket& recvPacket); void HandleWhoOpcode(WorldPacket& recvPacket); - void HandleLogoutRequestOpcode(WorldPacket& recvPacket); - void HandlePlayerLogoutOpcode(WorldPacket& recvPacket); - void HandleLogoutCancelOpcode(WorldPacket& recvPacket); + void HandleLogoutRequestOpcode(WorldPackets::Character::LogoutRequest& logoutRequest); + void HandleLogoutCancelOpcode(WorldPackets::Character::LogoutCancel& logoutCancel); // GM Ticket opcodes void HandleGMTicketCreateOpcode(WorldPacket& recvPacket); @@ -551,7 +569,7 @@ class WorldSession void HandleMeetingStoneInfo(WorldPacket& recPacket); void HandleGameobjectReportUse(WorldPacket& recvPacket); - void HandleNameQueryOpcode(WorldPacket& recvPacket); + void HandleNameQueryOpcode(WorldPackets::Character::QueryPlayerName& packet); void HandleQueryTimeOpcode(WorldPacket& recvPacket); @@ -607,7 +625,7 @@ class WorldSession void HandleOfferPetitionOpcode(WorldPacket& recvData); void HandleTurnInPetitionOpcode(WorldPacket& recvData); - void HandleGuildQueryOpcode(WorldPacket& recvPacket); + void HandleGuildQueryOpcode(WorldPackets::Guild::QueryGuildInfo& query); void HandleGuildInviteOpcode(WorldPacket& recvPacket); void HandleGuildRemoveOpcode(WorldPacket& recvPacket); void HandleGuildAcceptOpcode(WorldPacket& recvPacket); @@ -681,7 +699,7 @@ class WorldSession void HandleAcceptTradeOpcode(WorldPacket& recvPacket); void HandleBeginTradeOpcode(WorldPacket& recvPacket); void HandleBusyTradeOpcode(WorldPacket& recvPacket); - void HandleCancelTradeOpcode(WorldPacket& recvPacket); + void HandleCancelTradeOpcode(WorldPackets::Trade::CancelTrade& cancelTrade); void HandleClearTradeItemOpcode(WorldPacket& recvPacket); void HandleIgnoreTradeOpcode(WorldPacket& recvPacket); void HandleInitiateTradeOpcode(WorldPacket& recvPacket); @@ -1006,7 +1024,7 @@ class WorldSession void HandleUpdateProjectilePosition(WorldPacket& recvPacket); void HandleRequestHotfix(WorldPacket& recvPacket); void HandleUpdateMissileTrajectory(WorldPacket& recvPacket); - void HandleViolenceLevel(WorldPacket& recvPacket); + void HandleViolenceLevel(WorldPackets::Misc::ViolenceLevel& violenceLevel); void HandleObjectUpdateFailedOpcode(WorldPacket& recvPacket); void HandleRequestCategoryCooldowns(WorldPacket& recvPacket); int32 HandleEnableNagleAlgorithm(); @@ -1084,7 +1102,7 @@ class WorldSession ObjectGuid::LowType m_GUIDLow; // set logined or recently logout player (while m_playerRecentlyLogout set) Player* _player; - std::shared_ptr<WorldSocket> m_Socket; + std::shared_ptr<WorldSocket> m_Socket[2]; std::string m_Address; // Current Remote Address // std::string m_LAddress; // Last Attempted Remote Adress - we can not set attempted ip for a non-existing session! @@ -1100,7 +1118,7 @@ class WorldSession time_t _logoutTime; bool m_inQueue; // session wait in auth.queue - bool m_playerLoading; // code processed in LoginPlayer + ObjectGuid m_playerLoading; // code processed in LoginPlayer bool m_playerLogout; // code processed in LogoutPlayer bool m_playerRecentlyLogout; bool m_playerSave; @@ -1117,7 +1135,6 @@ class WorldSession uint32 recruiterId; bool isRecruiter; LockedQueue<WorldPacket*> _recvQueue; - z_stream_s* _compressionStream; rbac::RBACData* _RBACData; uint32 expireTime; bool forceExit; diff --git a/src/server/game/Server/WorldSocket.cpp b/src/server/game/Server/WorldSocket.cpp index 23bd9a65f88..5729cea131d 100644 --- a/src/server/game/Server/WorldSocket.cpp +++ b/src/server/game/Server/WorldSocket.cpp @@ -25,6 +25,7 @@ #include "SHA1.h" #include "PacketLog.h" #include "BattlenetAccountMgr.h" +#include "World.h" #include <zlib.h> #include <memory> @@ -53,12 +54,22 @@ uint32 const SizeOfClientHeader[2][2] = uint32 const SizeOfServerHeader[2] = { sizeof(uint16) + sizeof(uint32), sizeof(uint32) }; -WorldSocket::WorldSocket(tcp::socket&& socket) - : Socket(std::move(socket)), _authSeed(rand32()), _OverSpeedPings(0), _worldSession(nullptr), _initialized(false) +WorldSocket::WorldSocket(tcp::socket&& socket) : Socket(std::move(socket)), + _type(CONNECTION_TYPE_REALM), _authSeed(rand32()), + _OverSpeedPings(0), _worldSession(nullptr), _initialized(false) { _headerBuffer.Resize(SizeOfClientHeader[0][0]); } +WorldSocket::~WorldSocket() +{ + if (_compressionStream) + { + deflateEnd(_compressionStream); + delete _compressionStream; + } +} + void WorldSocket::Start() { AsyncRead(); @@ -75,15 +86,13 @@ void WorldSocket::Start() void WorldSocket::HandleSendAuthSession() { - BigNumber seed1; - BigNumber seed2; - seed1.SetRand(16 * 8); - seed2.SetRand(16 * 8); + _encryptSeed.SetRand(16 * 8); + _decryptSeed.SetRand(16 * 8); WorldPackets::Auth::AuthChallenge challenge; challenge.Challenge = _authSeed; - memcpy(&challenge.DosChallenge[0], seed1.AsByteArray(16).get(), 16); - memcpy(&challenge.DosChallenge[4], seed2.AsByteArray(16).get(), 16); + memcpy(&challenge.DosChallenge[0], _encryptSeed.AsByteArray(16).get(), 16); + memcpy(&challenge.DosChallenge[4], _decryptSeed.AsByteArray(16).get(), 16); challenge.DosZeroBits = 1; SendPacket(*challenge.Write()); @@ -175,11 +184,11 @@ bool WorldSocket::ReadHeaderHandler() if (_worldSession) { Player* player = _worldSession->GetPlayer(); - TC_LOG_ERROR("network", "WorldSocket::ReadHeaderHandler(): client (account: %u, char [%s, name: %s]) sent malformed packet (size: %hu, cmd: %u)", + TC_LOG_ERROR("network", "WorldSocket::ReadHeaderHandler(): client (account: %u, char [%s, name: %s]) sent malformed packet (size: %u, cmd: %u)", _worldSession->GetAccountId(), player ? player->GetGUID().ToString().c_str() : "GUID: Empty", player ? player->GetName().c_str() : "<none>", size, opcode); } else - TC_LOG_ERROR("network", "WorldSocket::ReadHeaderHandler(): client %s sent malformed packet (size: %hu, cmd: %u)", + TC_LOG_ERROR("network", "WorldSocket::ReadHeaderHandler(): client %s sent malformed packet (size: %u, cmd: %u)", GetRemoteIpAddress().to_string().c_str(), size, opcode); CloseSocket(); @@ -204,10 +213,10 @@ bool WorldSocket::ReadDataHandler() std::string opcodeName = GetOpcodeNameForLogging(opcode); - WorldPacket packet(opcode, std::move(_packetBuffer)); + WorldPacket packet(opcode, std::move(_packetBuffer), GetConnectionType()); if (sPacketLog->CanLogPacket()) - sPacketLog->LogPacket(packet, CLIENT_TO_SERVER, GetRemoteIpAddress(), GetRemotePort()); + sPacketLog->LogPacket(packet, CLIENT_TO_SERVER, GetRemoteIpAddress(), GetRemotePort(), GetConnectionType()); TC_LOG_TRACE("network.opcode", "C->S: %s %s", (_worldSession ? _worldSession->GetPlayerInfo() : GetRemoteIpAddress().to_string()).c_str(), opcodeName.c_str()); @@ -217,15 +226,32 @@ bool WorldSocket::ReadDataHandler() HandlePing(packet); break; case CMSG_AUTH_SESSION: + { if (_worldSession) { TC_LOG_ERROR("network", "WorldSocket::ProcessIncoming: received duplicate CMSG_AUTH_SESSION from %s", _worldSession->GetPlayerInfo().c_str()); break; } - HandleAuthSession(packet); + WorldPackets::Auth::AuthSession authSession(std::move(packet)); + authSession.Read(); + HandleAuthSession(authSession); + break; + } + case CMSG_AUTH_CONTINUED_SESSION: + { + if (_worldSession) + { + TC_LOG_ERROR("network", "WorldSocket::ProcessIncoming: received duplicate CMSG_AUTH_CONTINUED_SESSION from %s", _worldSession->GetPlayerInfo().c_str()); + break; + } + + WorldPackets::Auth::AuthContinuedSession authSession(std::move(packet)); + authSession.Read(); + HandleAuthContinuedSession(authSession); break; - /* + } + /* case CMSG_KEEP_ALIVE: TC_LOG_DEBUG("network", "%s", opcodeName.c_str()); sScriptMgr->OnPacketReceive(_worldSession, packet); @@ -286,6 +312,20 @@ bool WorldSocket::ReadDataHandler() return false; } + _compressionStream = new z_stream(); + _compressionStream->zalloc = (alloc_func)NULL; + _compressionStream->zfree = (free_func)NULL; + _compressionStream->opaque = (voidpf)NULL; + _compressionStream->avail_in = 0; + _compressionStream->next_in = NULL; + int32 z_res = deflateInit2(_compressionStream, sWorld->getIntConfig(CONFIG_COMPRESSION), Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY); + if (z_res != Z_OK) + { + TC_LOG_ERROR("network", "Can't initialize packet compression (zlib: deflateInit) Error code: %i (%s)", z_res, zError(z_res)); + CloseSocket(); + return false; + } + _initialized = true; _headerBuffer.Resize(SizeOfClientHeader[1][0]); _packetBuffer.Reset(); @@ -295,6 +335,35 @@ bool WorldSocket::ReadDataHandler() return true; } +void WorldSocket::SendPacket(WorldPacket const& packet) +{ + if (!IsOpen()) + return; + + if (sPacketLog->CanLogPacket()) + sPacketLog->LogPacket(packet, SERVER_TO_CLIENT, GetRemoteIpAddress(), GetRemotePort(), GetConnectionType()); + + TC_LOG_TRACE("network.opcode", "S->C: %s %s", (_worldSession ? _worldSession->GetPlayerInfo() : GetRemoteIpAddress().to_string()).c_str(), GetOpcodeNameForLogging(static_cast<OpcodeServer>(packet.GetOpcode())).c_str()); + + uint32 packetSize = packet.size(); + uint32 sizeOfHeader = SizeOfServerHeader[_authCrypt.IsInitialized()]; + if (packetSize > 0x400) + packetSize = compressBound(packetSize) + sizeof(CompressedWorldPacket); + + std::unique_lock<std::mutex> guard(_writeLock); + +#ifndef TC_SOCKET_USE_IOCP + if (_writeQueue.empty() && _writeBuffer.GetRemainingSpace() >= sizeOfHeader + packetSize) + WritePacketToBuffer(packet, _writeBuffer); + else +#endif + { + MessageBuffer buffer(sizeOfHeader + packetSize); + WritePacketToBuffer(packet, buffer); + QueuePacket(std::move(buffer), guard); + } +} + void WorldSocket::WritePacketToBuffer(WorldPacket const& packet, MessageBuffer& buffer) { ServerPktHeader header; @@ -306,7 +375,7 @@ void WorldSocket::WritePacketToBuffer(WorldPacket const& packet, MessageBuffer& uint8* headerPos = buffer.GetWritePointer(); buffer.WriteCompleted(sizeOfHeader); - if (packetSize > 0x400 && _worldSession) + if (packetSize > 0x400) { CompressedWorldPacket cmp; cmp.UncompressedSize = packetSize + 4; @@ -316,7 +385,7 @@ void WorldSocket::WritePacketToBuffer(WorldPacket const& packet, MessageBuffer& uint8* compressionInfo = buffer.GetWritePointer(); buffer.WriteCompleted(sizeof(CompressedWorldPacket)); - uint32 compressedSize = _worldSession->CompressPacket(buffer.GetWritePointer(), packet); + uint32 compressedSize = CompressPacket(buffer.GetWritePointer(), packet); cmp.CompressedAdler = adler32(0x9827D8F1, buffer.GetWritePointer(), compressedSize); @@ -344,40 +413,39 @@ void WorldSocket::WritePacketToBuffer(WorldPacket const& packet, MessageBuffer& memcpy(headerPos, &header, sizeOfHeader); } -void WorldSocket::SendPacket(WorldPacket const& packet) +uint32 WorldSocket::CompressPacket(uint8* buffer, WorldPacket const& packet) { - if (!IsOpen()) - return; - - if (sPacketLog->CanLogPacket()) - sPacketLog->LogPacket(packet, SERVER_TO_CLIENT, GetRemoteIpAddress(), GetRemotePort()); + uint32 opcode = packet.GetOpcode(); + uint32 bufferSize = deflateBound(_compressionStream, packet.size() + sizeof(opcode)); - TC_LOG_TRACE("network.opcode", "S->C: %s %s", (_worldSession ? _worldSession->GetPlayerInfo() : GetRemoteIpAddress().to_string()).c_str(), GetOpcodeNameForLogging(static_cast<OpcodeServer>(packet.GetOpcode())).c_str()); + _compressionStream->next_out = buffer; + _compressionStream->avail_out = bufferSize; + _compressionStream->next_in = (Bytef*)&opcode; + _compressionStream->avail_in = sizeof(uint32); - uint32 packetSize = packet.size(); - uint32 sizeOfHeader = SizeOfServerHeader[_authCrypt.IsInitialized()]; - if (packetSize > 0x400 && _worldSession) - packetSize = compressBound(packetSize) + sizeof(CompressedWorldPacket); + int32 z_res = deflate(_compressionStream, Z_BLOCK); + if (z_res != Z_OK) + { + TC_LOG_ERROR("network", "Can't compress packet opcode (zlib: deflate) Error code: %i (%s, msg: %s)", z_res, zError(z_res), _compressionStream->msg); + return 0; + } - std::unique_lock<std::mutex> guard(_writeLock); + _compressionStream->next_in = (Bytef*)packet.contents(); + _compressionStream->avail_in = packet.size(); -#ifndef TC_SOCKET_USE_IOCP - if (_writeQueue.empty() && _writeBuffer.GetRemainingSpace() >= sizeOfHeader + packetSize) - WritePacketToBuffer(packet, _writeBuffer); - else -#endif + z_res = deflate(_compressionStream, Z_SYNC_FLUSH); + if (z_res != Z_OK) { - MessageBuffer buffer(sizeOfHeader + packetSize); - WritePacketToBuffer(packet, buffer); - QueuePacket(std::move(buffer), guard); + TC_LOG_ERROR("network", "Can't compress packet data (zlib: deflate) Error code: %i (%s, msg: %s)", z_res, zError(z_res), _compressionStream->msg); + return 0; } + + + return bufferSize - _compressionStream->avail_out; } -void WorldSocket::HandleAuthSession(WorldPacket& recvPacket) +void WorldSocket::HandleAuthSession(WorldPackets::Auth::AuthSession& authSession) { - WorldPackets::Auth::AuthSession authSession(std::move(recvPacket)); - authSession.Read(); - uint8 security; uint32 id; LocaleConstant locale; @@ -598,6 +666,59 @@ void WorldSocket::HandleAuthSession(WorldPacket& recvPacket) sWorld->AddSession(_worldSession); } +void WorldSocket::HandleAuthContinuedSession(WorldPackets::Auth::AuthContinuedSession& authSession) +{ + uint32 accountId = PAIR64_LOPART(authSession.Key); + _type = ConnectionType(PAIR64_HIPART(authSession.Key)); + + PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_INFO_CONTINUED_SESSION); + stmt->setUInt32(0, accountId); + PreparedQueryResult result = LoginDatabase.Query(stmt); + if (!result) + { + SendAuthResponseError(AUTH_UNKNOWN_ACCOUNT); + DelayedCloseSocket(); + return; + } + + Field* fields = result->Fetch(); + std::string login = fields[0].GetString(); + BigNumber k; + k.SetHexStr(fields[1].GetCString()); + + _authCrypt.Init(&k, _encryptSeed.AsByteArray().get(), _decryptSeed.AsByteArray().get()); + _headerBuffer.Resize(SizeOfClientHeader[1][1]); + + SHA1Hash sha; + sha.UpdateData(login); + sha.UpdateBigNumbers(&k, NULL); + sha.UpdateData((uint8*)&_authSeed, 4); + sha.Finalize(); + + if (memcmp(sha.GetDigest(), authSession.Digest, sha.GetLength())) + { + SendAuthResponseError(AUTH_UNKNOWN_ACCOUNT); + TC_LOG_ERROR("network", "WorldSocket::HandleAuthContinuedSession: Authentication failed for account: %u ('%s') address: %s", accountId, login.c_str(), GetRemoteIpAddress().to_string().c_str()); + DelayedCloseSocket(); + return; + } + + _worldSession = sWorld->FindSession(accountId); + if (!_worldSession) + { + SendAuthResponseError(AUTH_SESSION_EXPIRED); + TC_LOG_ERROR("network", "WorldSocket::HandleAuthContinuedSession: No active session found for account: %u ('%s') address: %s", accountId, login.c_str(), GetRemoteIpAddress().to_string().c_str()); + DelayedCloseSocket(); + return; + } + + WorldPackets::Auth::ResumeComms resumeComms; + SendPacket(*resumeComms.Write()); + + _worldSession->AddInstanceConnection(shared_from_this()); + _worldSession->HandleContinuePlayerLogin(); +} + void WorldSocket::SendAuthResponseError(uint8 code) { WorldPackets::Auth::AuthResponse response; diff --git a/src/server/game/Server/WorldSocket.h b/src/server/game/Server/WorldSocket.h index e0dad0a43a1..16769c68c33 100644 --- a/src/server/game/Server/WorldSocket.h +++ b/src/server/game/Server/WorldSocket.h @@ -31,10 +31,16 @@ #include <boost/asio/buffer.hpp> using boost::asio::ip::tcp; +struct z_stream_s; namespace WorldPackets { class ServerPacket; + namespace Auth + { + class AuthSession; + class AuthContinuedSession; + } } #pragma pack(push, 1) @@ -67,6 +73,7 @@ class WorldSocket : public Socket<WorldSocket> public: WorldSocket(tcp::socket&& socket); + ~WorldSocket(); WorldSocket(WorldSocket const& right) = delete; WorldSocket& operator=(WorldSocket const& right) = delete; @@ -74,7 +81,8 @@ public: void Start() override; void SendPacket(WorldPacket const& packet); - void WritePacketToBuffer(WorldPacket const& packet, MessageBuffer& buffer); + + ConnectionType GetConnectionType() const { return _type; } protected: void ReadHandler() override; @@ -82,16 +90,24 @@ protected: bool ReadDataHandler(); private: + void WritePacketToBuffer(WorldPacket const& packet, MessageBuffer& buffer); + uint32 CompressPacket(uint8* buffer, WorldPacket const& packet); + void HandleSendAuthSession(); - void HandleAuthSession(WorldPacket& recvPacket); + void HandleAuthSession(WorldPackets::Auth::AuthSession& authSession); + void HandleAuthContinuedSession(WorldPackets::Auth::AuthContinuedSession& authSession); void SendAuthResponseError(uint8 code); void HandlePing(WorldPacket& recvPacket); void ExtractOpcodeAndSize(ClientPktHeader const* header, uint32& opcode, uint32& size) const; + ConnectionType _type; + uint32 _authSeed; WorldPacketCrypt _authCrypt; + BigNumber _encryptSeed; + BigNumber _decryptSeed; std::chrono::steady_clock::time_point _LastPingTime; uint32 _OverSpeedPings; @@ -101,6 +117,8 @@ private: MessageBuffer _headerBuffer; MessageBuffer _packetBuffer; + z_stream_s* _compressionStream; + bool _initialized; }; diff --git a/src/server/game/Server/WorldSocketMgr.cpp b/src/server/game/Server/WorldSocketMgr.cpp index 21f62fa265c..5fcd308f376 100644 --- a/src/server/game/Server/WorldSocketMgr.cpp +++ b/src/server/game/Server/WorldSocketMgr.cpp @@ -46,6 +46,11 @@ WorldSocketMgr::WorldSocketMgr() : BaseSocketMgr(), _socketSendBufferSize(-1), m { } +WorldSocketMgr::~WorldSocketMgr() +{ + delete _instanceAcceptor; +} + bool WorldSocketMgr::StartNetwork(boost::asio::io_service& service, std::string const& bindIp, uint16 port) { _tcpNoDelay = sConfigMgr->GetBoolDefault("Network.TcpNodelay", true); @@ -64,8 +69,10 @@ bool WorldSocketMgr::StartNetwork(boost::asio::io_service& service, std::string } BaseSocketMgr::StartNetwork(service, bindIp, port); + _instanceAcceptor = new AsyncAcceptor(service, bindIp, uint16(sWorld->getIntConfig(CONFIG_PORT_INSTANCE))); _acceptor->AsyncAcceptManaged(&OnSocketAccept); + _instanceAcceptor->AsyncAcceptManaged(&OnSocketAccept); sScriptMgr->OnNetworkStart(); return true; diff --git a/src/server/game/Server/WorldSocketMgr.h b/src/server/game/Server/WorldSocketMgr.h index 92a28d0c135..389818b2f9b 100644 --- a/src/server/game/Server/WorldSocketMgr.h +++ b/src/server/game/Server/WorldSocketMgr.h @@ -35,6 +35,8 @@ class WorldSocketMgr : public SocketMgr<WorldSocket> typedef SocketMgr<WorldSocket> BaseSocketMgr; public: + ~WorldSocketMgr(); + static WorldSocketMgr& Instance() { static WorldSocketMgr instance; @@ -55,6 +57,7 @@ protected: NetworkThread<WorldSocket>* CreateThreads() const override; private: + AsyncAcceptor* _instanceAcceptor; int32 _socketSendBufferSize; int32 m_SockOutUBuff; bool _tcpNoDelay; diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 3b9acb90d79..7781e4fcc0c 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -4207,7 +4207,7 @@ void Spell::SendChannelUpdate(uint32 time) m_caster->SetUInt32Value(UNIT_CHANNEL_SPELL, 0); } - WorldPacket data(MSG_CHANNEL_UPDATE, 8+4); + WorldPacket data(SMSG_CHANNEL_UPDATE, 8+4); data << m_caster->GetPackGUID(); data << uint32(time); @@ -4221,7 +4221,7 @@ void Spell::SendChannelStart(uint32 duration) if (m_UniqueTargetInfo.size() + m_UniqueGOTargetInfo.size() == 1) // this is for TARGET_SELECT_CATEGORY_NEARBY channelTarget = !m_UniqueTargetInfo.empty() ? m_UniqueTargetInfo.front().targetGUID : m_UniqueGOTargetInfo.front().targetGUID; - WorldPacket data(MSG_CHANNEL_START, (8+4+4)); + WorldPacket data(SMSG_CHANNEL_START, (8+4+4)); data << m_caster->GetPackGUID(); data << uint32(m_spellInfo->Id); data << uint32(duration); diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index f043fafc261..8bc360abf4d 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -65,6 +65,7 @@ #include "WeatherMgr.h" #include "WorldSession.h" +#include <boost/algorithm/string.hpp> std::atomic<bool> World::m_stopEvent(false); uint8 World::m_ExitCode = SHUTDOWN_EXIT_CODE; @@ -173,16 +174,18 @@ void World::SetClosed(bool val) sScriptMgr->OnOpenStateChange(!val); } -void World::SetMotd(const std::string& motd) +void World::SetMotd(std::string motd) { - m_motd = motd; + /// we are using a string copy here to allow modifications in script hooks + sScriptMgr->OnMotdChange(motd); - sScriptMgr->OnMotdChange(m_motd); + _motd.clear(); + boost::split(_motd, motd, boost::is_any_of("@")); } -const char* World::GetMotd() const +std::vector<std::string> const& World::GetMotd() const { - return m_motd.c_str(); + return _motd; } /// Find a session by its id @@ -647,9 +650,16 @@ void World::LoadConfigSettings(bool reload) uint32 val = sConfigMgr->GetIntDefault("WorldServerPort", 8085); if (val != m_int_configs[CONFIG_PORT_WORLD]) TC_LOG_ERROR("server.loading", "WorldServerPort option can't be changed at worldserver.conf reload, using current value (%u).", m_int_configs[CONFIG_PORT_WORLD]); + + val = sConfigMgr->GetIntDefault("InstanceServerPort", 8086); + if (val != m_int_configs[CONFIG_PORT_INSTANCE]) + TC_LOG_ERROR("server.loading", "InstanceServerPort option can't be changed at worldserver.conf reload, using current value (%u).", m_int_configs[CONFIG_PORT_INSTANCE]); } else + { m_int_configs[CONFIG_PORT_WORLD] = sConfigMgr->GetIntDefault("WorldServerPort", 8085); + m_int_configs[CONFIG_PORT_INSTANCE] = sConfigMgr->GetIntDefault("InstanceServerPort", 8086); + } m_int_configs[CONFIG_SOCKET_TIMEOUTTIME] = sConfigMgr->GetIntDefault("SocketTimeOutTime", 900000); m_int_configs[CONFIG_SESSION_ADD_DELAY] = sConfigMgr->GetIntDefault("SessionAddDelay", 10000); @@ -1076,11 +1086,11 @@ void World::LoadConfigSettings(bool reload) m_int_configs[CONFIG_ARENA_RATED_UPDATE_TIMER] = sConfigMgr->GetIntDefault ("Arena.RatedUpdateTimer", 5 * IN_MILLISECONDS); m_bool_configs[CONFIG_ARENA_QUEUE_ANNOUNCER_ENABLE] = sConfigMgr->GetBoolDefault("Arena.QueueAnnouncer.Enable", false); m_bool_configs[CONFIG_ARENA_QUEUE_ANNOUNCER_PLAYERONLY] = sConfigMgr->GetBoolDefault("Arena.QueueAnnouncer.PlayerOnly", false); - m_int_configs[CONFIG_ARENA_SEASON_ID] = sConfigMgr->GetIntDefault ("Arena.ArenaSeason.ID", 1); + m_int_configs[CONFIG_ARENA_SEASON_ID] = sConfigMgr->GetIntDefault ("Arena.ArenaSeason.ID", 15); m_int_configs[CONFIG_ARENA_START_RATING] = sConfigMgr->GetIntDefault ("Arena.ArenaStartRating", 0); m_int_configs[CONFIG_ARENA_START_PERSONAL_RATING] = sConfigMgr->GetIntDefault ("Arena.ArenaStartPersonalRating", 1000); m_int_configs[CONFIG_ARENA_START_MATCHMAKER_RATING] = sConfigMgr->GetIntDefault ("Arena.ArenaStartMatchmakerRating", 1500); - m_bool_configs[CONFIG_ARENA_SEASON_IN_PROGRESS] = sConfigMgr->GetBoolDefault("Arena.ArenaSeason.InProgress", true); + m_bool_configs[CONFIG_ARENA_SEASON_IN_PROGRESS] = sConfigMgr->GetBoolDefault("Arena.ArenaSeason.InProgress", false); m_bool_configs[CONFIG_ARENA_LOG_EXTENDED_INFO] = sConfigMgr->GetBoolDefault("ArenaLog.ExtendedInfo", false); m_bool_configs[CONFIG_OFFHAND_CHECK_AT_SPELL_UNLEARN] = sConfigMgr->GetBoolDefault("OffhandCheckAtSpellUnlearn", true); @@ -2206,7 +2216,7 @@ void World::ForceGameEventUpdate() } /// Send a packet to all players (except self if mentioned) -void World::SendGlobalMessage(WorldPacket* packet, WorldSession* self, uint32 team) +void World::SendGlobalMessage(WorldPacket const* packet, WorldSession* self, uint32 team) { SessionMap::const_iterator itr; for (itr = m_sessions.begin(); itr != m_sessions.end(); ++itr) @@ -2223,7 +2233,7 @@ void World::SendGlobalMessage(WorldPacket* packet, WorldSession* self, uint32 te } /// Send a packet to all GMs (except self if mentioned) -void World::SendGlobalGMMessage(WorldPacket* packet, WorldSession* self, uint32 team) +void World::SendGlobalGMMessage(WorldPacket const* packet, WorldSession* self, uint32 team) { for (SessionMap::const_iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr) { @@ -2351,7 +2361,7 @@ void World::SendGlobalText(const char* text, WorldSession* self) } /// Send a packet to all players (or players selected team) in the zone (except self if mentioned) -bool World::SendZoneMessage(uint32 zone, WorldPacket* packet, WorldSession* self, uint32 team) +bool World::SendZoneMessage(uint32 zone, WorldPacket const* packet, WorldSession* self, uint32 team) { bool foundPlayerToSend = false; SessionMap::const_iterator itr; @@ -3321,3 +3331,8 @@ void World::ReloadRBAC() if (WorldSession* session = itr->second) session->InvalidateRBACData(); } + +uint32 GetVirtualRealmAddress() +{ + return uint32(realmHandle.Region) << 24 | uint32(realmHandle.Battlegroup) << 16 | realmHandle.Index; +} diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h index 4f4c3451b02..7bf8f5b70e7 100644 --- a/src/server/game/World/World.h +++ b/src/server/game/World/World.h @@ -30,6 +30,7 @@ #include "SharedDefines.h" #include "QueryResult.h" #include "Callback.h" +#include "Realm/Realm.h" #include <atomic> #include <map> @@ -204,6 +205,7 @@ enum WorldIntConfigs CONFIG_INTERVAL_CHANGEWEATHER, CONFIG_INTERVAL_DISCONNECT_TOLERANCE, CONFIG_PORT_WORLD, + CONFIG_PORT_INSTANCE, CONFIG_SOCKET_TIMEOUTTIME, CONFIG_SESSION_ADD_DELAY, CONFIG_GAME_TYPE, @@ -617,9 +619,9 @@ class World void SetAllowMovement(bool allow) { m_allowMovement = allow; } /// Set a new Message of the Day - void SetMotd(std::string const& motd); + void SetMotd(std::string motd); /// Get the current Message of the Day - const char* GetMotd() const; + std::vector<std::string> const& GetMotd() const; /// Set the string for new characters (first login) void SetNewCharString(std::string const& str) { m_newCharString = str; } @@ -660,9 +662,9 @@ class World void SendGlobalText(const char* text, WorldSession* self); void SendGMText(uint32 string_id, ...); void SendServerMessage(ServerMessageType type, const char *text = "", Player* player = NULL); - void SendGlobalMessage(WorldPacket* packet, WorldSession* self = nullptr, uint32 team = 0); - void SendGlobalGMMessage(WorldPacket* packet, WorldSession* self = nullptr, uint32 team = 0); - bool SendZoneMessage(uint32 zone, WorldPacket* packet, WorldSession* self = nullptr, uint32 team = 0); + void SendGlobalMessage(WorldPacket const* packet, WorldSession* self = nullptr, uint32 team = 0); + void SendGlobalGMMessage(WorldPacket const* packet, WorldSession* self = nullptr, uint32 team = 0); + bool SendZoneMessage(uint32 zone, WorldPacket const* packet, WorldSession* self = nullptr, uint32 team = 0); void SendZoneText(uint32 zone, const char *text, WorldSession* self = nullptr, uint32 team = 0); /// Are we in the middle of a shutdown? @@ -840,7 +842,7 @@ class World LocaleConstant m_defaultDbcLocale; // from config for one from loaded DBC locales uint32 m_availableDbcLocaleMask; // by loaded DBC bool m_allowMovement; - std::string m_motd; + std::vector<std::string> _motd; std::string m_dataPath; // for max speed access @@ -887,6 +889,8 @@ class World }; extern Battlenet::RealmHandle realmHandle; +extern Realm realm; +uint32 GetVirtualRealmAddress(); #define sWorld World::instance() #endif diff --git a/src/server/ipc/ZmqMux.cpp b/src/server/ipc/ZmqMux.cpp index 4b5a4f48b05..2b62eaaf1eb 100644 --- a/src/server/ipc/ZmqMux.cpp +++ b/src/server/ipc/ZmqMux.cpp @@ -56,6 +56,7 @@ void ZmqMux::Run() { for (;;) { + std::this_thread::sleep_for(std::chrono::milliseconds(50)); if (!_poller->poll()) break; diff --git a/src/server/scripts/Commands/cs_battlenet_account.cpp b/src/server/scripts/Commands/cs_battlenet_account.cpp index 06bd131150a..79b57cb94ff 100644 --- a/src/server/scripts/Commands/cs_battlenet_account.cpp +++ b/src/server/scripts/Commands/cs_battlenet_account.cpp @@ -44,17 +44,20 @@ public: static ChatCommand accountCommandTable[] = { - { "create", rbac::RBAC_PERM_COMMAND_BNET_ACCOUNT_CREATE, true, &HandleAccountCreateCommand, "", NULL }, - { "lock", rbac::RBAC_PERM_COMMAND_BNET_ACCOUNT, false, NULL, "", accountLockCommandTable }, - { "set", rbac::RBAC_PERM_COMMAND_BNET_ACCOUNT_SET, true, NULL, "", accountSetCommandTable }, - { "password", rbac::RBAC_PERM_COMMAND_BNET_ACCOUNT_PASSWORD, false, &HandleAccountPasswordCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "create", rbac::RBAC_PERM_COMMAND_BNET_ACCOUNT_CREATE, true, &HandleAccountCreateCommand, "", NULL }, + { "gameaccountcreate", rbac::RBAC_PERM_COMMAND_BNET_ACCOUNT_CREATE_GAME, true, &HandleGameAccountCreateCommand, "", NULL }, + { "lock", rbac::RBAC_PERM_COMMAND_BNET_ACCOUNT, false, NULL, "", accountLockCommandTable }, + { "set", rbac::RBAC_PERM_COMMAND_BNET_ACCOUNT_SET, true, NULL, "", accountSetCommandTable }, + { "password", rbac::RBAC_PERM_COMMAND_BNET_ACCOUNT_PASSWORD, false, &HandleAccountPasswordCommand, "", NULL }, + { "link", rbac::RBAC_PERM_COMMAND_BNET_ACCOUNT_LINK, true, &HandleAccountLinkCommand, "", NULL }, + { "unlink", rbac::RBAC_PERM_COMMAND_BNET_ACCOUNT_UNLINK, true, &HandleAccountUnlinkCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand commandTable[] = { - { "battlenetaccount", rbac::RBAC_PERM_COMMAND_BNET_ACCOUNT, true, NULL, "", accountCommandTable }, - { NULL, 0, false, NULL, "", NULL } + { "bnetaccount", rbac::RBAC_PERM_COMMAND_BNET_ACCOUNT, true, NULL, "", accountCommandTable }, + { NULL, 0, false, NULL, "", NULL } }; return commandTable; @@ -328,6 +331,124 @@ public: } return true; } + + static bool HandleAccountLinkCommand(ChatHandler* handler, char const* args) + { + Tokenizer tokens(args, ' ', 2); + if (tokens.size() != 2) + { + handler->SendSysMessage(LANG_CMD_SYNTAX); + handler->SetSentErrorMessage(true); + return false; + } + + std::string bnetAccountName = tokens[0]; + std::string gameAccountName = tokens[1]; + + switch (Battlenet::AccountMgr::LinkWithGameAccount(bnetAccountName, gameAccountName)) + { + case AccountOpResult::AOR_OK: + handler->PSendSysMessage(LANG_ACCOUNT_BNET_LINKED, bnetAccountName.c_str(), gameAccountName.c_str()); + break; + case AccountOpResult::AOR_NAME_NOT_EXIST: + handler->PSendSysMessage(LANG_ACCOUNT_OR_BNET_DOES_NOT_EXIST, bnetAccountName.c_str(), gameAccountName.c_str()); + handler->SetSentErrorMessage(true); + break; + case AccountOpResult::AOR_ACCOUNT_BAD_LINK: + handler->PSendSysMessage(LANG_ACCOUNT_ALREADY_LINKED, gameAccountName.c_str()); + handler->SetSentErrorMessage(true); + break; + default: + break; + } + + return true; + } + + static bool HandleAccountUnlinkCommand(ChatHandler* handler, char const* args) + { + if (!*args) + { + handler->SendSysMessage(LANG_CMD_SYNTAX); + handler->SetSentErrorMessage(true); + return false; + } + + std::string gameAccountName = args; + + switch (Battlenet::AccountMgr::UnlinkGameAccount(gameAccountName)) + { + case AccountOpResult::AOR_OK: + handler->PSendSysMessage(LANG_ACCOUNT_BNET_UNLINKED, gameAccountName.c_str()); + break; + case AccountOpResult::AOR_NAME_NOT_EXIST: + handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, gameAccountName.c_str()); + handler->SetSentErrorMessage(true); + break; + case AccountOpResult::AOR_ACCOUNT_BAD_LINK: + handler->PSendSysMessage(LANG_ACCOUNT_BNET_NOT_LINKED, gameAccountName.c_str()); + handler->SetSentErrorMessage(true); + break; + default: + break; + } + + return true; + } + + static bool HandleGameAccountCreateCommand(ChatHandler* handler, char const* args) + { + if (!*args) + { + handler->SendSysMessage(LANG_CMD_SYNTAX); + handler->SetSentErrorMessage(true); + return false; + } + + std::string bnetAccountName = args; + uint32 accountId = Battlenet::AccountMgr::GetId(bnetAccountName); + if (!accountId) + { + handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, bnetAccountName.c_str()); + handler->SetSentErrorMessage(true); + return false; + } + + uint8 index = Battlenet::AccountMgr::GetMaxIndex(accountId) + 1; + std::string accountName = std::to_string(accountId) + '#' + std::to_string(uint32(index)); + + switch (sAccountMgr->CreateAccount(accountName, "DUMMY", bnetAccountName, accountId, index)) + { + case AccountOpResult::AOR_OK: + handler->PSendSysMessage(LANG_ACCOUNT_CREATED, accountName.c_str()); + if (handler->GetSession()) + { + TC_LOG_INFO("entities.player.character", "Account: %u (IP: %s) Character:[%s] (%s) created Account %s (Email: '%s')", + handler->GetSession()->GetAccountId(), handler->GetSession()->GetRemoteAddress().c_str(), + handler->GetSession()->GetPlayer()->GetName().c_str(), handler->GetSession()->GetPlayer()->GetGUID().ToString().c_str(), + accountName.c_str(), bnetAccountName.c_str()); + } + break; + case AccountOpResult::AOR_NAME_TOO_LONG: + handler->SendSysMessage(LANG_ACCOUNT_TOO_LONG); + handler->SetSentErrorMessage(true); + return false; + case AccountOpResult::AOR_NAME_ALREADY_EXIST: + handler->SendSysMessage(LANG_ACCOUNT_ALREADY_EXIST); + handler->SetSentErrorMessage(true); + return false; + case AccountOpResult::AOR_DB_INTERNAL_ERROR: + handler->PSendSysMessage(LANG_ACCOUNT_NOT_CREATED_SQL_ERROR, accountName.c_str()); + handler->SetSentErrorMessage(true); + return false; + default: + handler->PSendSysMessage(LANG_ACCOUNT_NOT_CREATED, accountName.c_str()); + handler->SetSentErrorMessage(true); + return false; + } + + return true; + } }; void AddSC_battlenet_account_commandscript() diff --git a/src/server/scripts/Commands/cs_server.cpp b/src/server/scripts/Commands/cs_server.cpp index 74a947e42e4..a5b2ed045c6 100644 --- a/src/server/scripts/Commands/cs_server.cpp +++ b/src/server/scripts/Commands/cs_server.cpp @@ -129,7 +129,10 @@ public: // Display the 'Message of the day' for the realm static bool HandleServerMotdCommand(ChatHandler* handler, char const* /*args*/) { - handler->PSendSysMessage(LANG_MOTD_CURRENT, sWorld->GetMotd()); + std::string motd; + for (std::string const& line : sWorld->GetMotd()) + motd += line; + handler->PSendSysMessage(LANG_MOTD_CURRENT, motd.c_str()); return true; } diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockCaverns/blackrock_caverns.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockCaverns/blackrock_caverns.cpp index 4b40660fafc..f736aa6ffbc 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockCaverns/blackrock_caverns.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockCaverns/blackrock_caverns.cpp @@ -108,7 +108,7 @@ public: npc_twilight_flame_caller() : CreatureScript("npc_twilight_flame_caller" struct npc_twilight_flame_callerAI : public ScriptedAI { - npc_twilight_flame_callerAI(Creature* creature) : ScriptedAI(creature), _summons(me), _instance(creature->GetInstanceScript()) + npc_twilight_flame_callerAI(Creature* creature) : ScriptedAI(creature), _instance(creature->GetInstanceScript()), _summons(me) { Initialize(); } diff --git a/src/server/scripts/Maelstrom/CMakeLists.txt b/src/server/scripts/Maelstrom/CMakeLists.txt index 79f0789fd3f..8d3f1ee1c69 100644 --- a/src/server/scripts/Maelstrom/CMakeLists.txt +++ b/src/server/scripts/Maelstrom/CMakeLists.txt @@ -9,6 +9,13 @@ set(scripts_STAT_SRCS ${scripts_STAT_SRCS} Maelstrom/kezan.cpp + Maelstrom/Stonecore/instance_stonecore.cpp + Maelstrom/Stonecore/stonecore.cpp + Maelstrom/Stonecore/stonecore.h + Maelstrom/Stonecore/boss_corborus.cpp + Maelstrom/Stonecore/boss_slabhide.cpp + Maelstrom/Stonecore/boss_ozruk.cpp + Maelstrom/Stonecore/boss_high_priestess_azil.cpp ) message(" -> Prepared: The Maelstrom") diff --git a/src/server/scripts/Maelstrom/Stonecore/boss_corborus.cpp b/src/server/scripts/Maelstrom/Stonecore/boss_corborus.cpp new file mode 100644 index 00000000000..2d522928fce --- /dev/null +++ b/src/server/scripts/Maelstrom/Stonecore/boss_corborus.cpp @@ -0,0 +1,319 @@ +/* + * Copyright (C) 2008-2014 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 "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "CreatureGroups.h" +#include "stonecore.h" + +// TO-DO: +// Find heroic sniffs and script spawning Crystal Shards on heroic mode. + +enum Spells +{ + // Corborus intro + SPELL_TWILIGHT_DOCUMENTS = 93167, + SPELL_RING_WYRM_CHARGE = 81237, + SPELL_DOOR_BREAK = 81232, // cast by World Trigger 22515 + + // Corborus boss + SPELL_DAMPENING_WAVE = 82415, + SPELL_CRYSTAL_BARRAGE = 86881, // 81638 triggers 81637 +// SPELL_CRYSTAL_BARRAGE_SHARD = 92012, // heroic only, summons Crystal Shard (TO-DO!) + SPELL_CLEAR_ALL_DEBUFFS = 34098, + SPELL_SUBMERGE = 81629, + SPELL_TRASHING_CHARGE_TELEPORT = 81839, // triggers 81864 +// SPELL_TRASHING_CHARGE_TELEPORT_2= 81838, // dummy, targets all players, threat update packet follows + SPELL_SUMMON_TRASHING_CHARGE = 81816, + SPELL_TRASHING_CHARGE_VISUAL = 81801, // cast time 3.5 sec + SPELL_TRASHING_CHARGE_EFFECT = 81828, // 40 yard radius + SPELL_EMERGE = 81948, + + // Rock Borer npc (43917) + SPELL_ROCK_BORER_EMERGE = 82185, + SPELL_ROCK_BORE = 80028, +}; + +enum NPCs +{ + NPC_TRASHING_CHARGE = 43743, +// NPC_CRYSTAL_SHARD = 49267, // 49473 +}; + +enum Events +{ + EVENT_NONE, + + // Corborus intro + EVENT_CORBORUS_CHARGE, + EVENT_CORBORUS_KNOCKBACK, + EVENT_CORBORUS_FACEPLAYERS, + + // Corborus boss + EVENT_DAMPENING_WAVE, + EVENT_CRYSTAL_BARRAGE, + EVENT_SUBMERGE, + EVENT_TELEPORT, + EVENT_TRASHING_CHARGE, + EVENT_SUMMON_BEETLE, + EVENT_EMERGE, + EVENT_ATTACK, + + // Rock Borer + EVENT_EMERGED, + EVENT_ROCK_BORE, +}; + +class boss_corborus : public CreatureScript +{ + public: + boss_corborus() : CreatureScript("boss_corborus") { } + + struct boss_corborusAI : public BossAI + { + boss_corborusAI(Creature* creature) : BossAI(creature, DATA_CORBORUS) + { + stateIntro = NOT_STARTED; + } + + void Reset() override + { + _Reset(); + countTrashingCharge = 0; + events.ScheduleEvent(EVENT_DAMPENING_WAVE, 10000); + events.ScheduleEvent(EVENT_CRYSTAL_BARRAGE, 15000); + events.ScheduleEvent(EVENT_SUBMERGE, 36000); + } + + void DoAction(int32 action) override + { + switch (action) + { + case ACTION_CORBORUS_INTRO: // Executes Corborus intro event + { + if (stateIntro != NOT_STARTED) + return; + + stateIntro = IN_PROGRESS; + + if (Creature* Millhouse = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_MILLHOUSE_MANASTORM))) + { + Millhouse->InterruptNonMeleeSpells(true); + Millhouse->RemoveAllAuras(); + Millhouse->HandleEmoteCommand(EMOTE_ONESHOT_KNOCKDOWN); + } + + events.ScheduleEvent(EVENT_CORBORUS_CHARGE, 1000); + break; + } + default: + break; + } + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim() && stateIntro != IN_PROGRESS) + return; + + events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_CORBORUS_CHARGE: + // Face Millhouse and other mobs + instance->SetData(DATA_MILLHOUSE_EVENT_FACE, 0); + + // Open rock gate and cast visual from nearby worldtrigger + instance->HandleGameObject(instance->GetGuidData(GAMEOBJECT_CORBORUS_ROCKDOOR), true); + if (Creature* worldtrigger = me->FindNearestCreature(NPC_WORLDTRIGGER, 60.0f)) + worldtrigger->CastSpell(worldtrigger, SPELL_DOOR_BREAK, true); + + // Make Corborus charge + me->CastSpell(me, SPELL_RING_WYRM_CHARGE, true); + + events.ScheduleEvent(EVENT_CORBORUS_KNOCKBACK, 1000); + break; + case EVENT_CORBORUS_KNOCKBACK: + // Spawn Twilight Documents (quest gameobject) + if (Creature* Millhouse = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_MILLHOUSE_MANASTORM))) + Millhouse->CastSpell(Millhouse, SPELL_TWILIGHT_DOCUMENTS, true); + + // Knockback Millhouse and other mobs + instance->SetData(DATA_MILLHOUSE_EVENT_KNOCKBACK, 0); + + events.ScheduleEvent(EVENT_CORBORUS_FACEPLAYERS, 2000); + break; + case EVENT_CORBORUS_FACEPLAYERS: + // Face Corborus to players and set new home position + me->SetFacingTo(3.176499f); + me->SetHomePosition(1154.55f, 878.843f, 284.963f, 3.176499f); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); + + // Despawn Millhouse and all trash + instance->SetData(DATA_MILLHOUSE_EVENT_DESPAWN, 0); + + stateIntro = DONE; + break; + case EVENT_DAMPENING_WAVE: + DoCastVictim(SPELL_DAMPENING_WAVE); + events.ScheduleEvent(EVENT_DAMPENING_WAVE, 15000); + break; + case EVENT_CRYSTAL_BARRAGE: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true)) + DoCast(target, SPELL_CRYSTAL_BARRAGE); + events.ScheduleEvent(EVENT_CRYSTAL_BARRAGE, 10000); + break; + case EVENT_SUBMERGE: + events.RescheduleEvent(EVENT_DAMPENING_WAVE, 35000); + events.RescheduleEvent(EVENT_CRYSTAL_BARRAGE, 30000); + events.RescheduleEvent(EVENT_SUBMERGE, 100000); + + me->SetReactState(REACT_PASSIVE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + DoCast(me, SPELL_CLEAR_ALL_DEBUFFS); + me->AttackStop(); + + DoCast(me, SPELL_SUBMERGE); + + countTrashingCharge = 0; + events.ScheduleEvent(EVENT_TELEPORT, 500); + break; + case EVENT_TELEPORT: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true)) + DoCast(target, SPELL_TRASHING_CHARGE_TELEPORT); + countTrashingCharge += 1; + if (countTrashingCharge <= 4) + events.ScheduleEvent(EVENT_TRASHING_CHARGE, 1000); + else + events.ScheduleEvent(EVENT_EMERGE, 2500); + break; + case EVENT_TRASHING_CHARGE: + DoCast(me, SPELL_SUMMON_TRASHING_CHARGE); + DoCast(me, SPELL_TRASHING_CHARGE_VISUAL); + events.ScheduleEvent(EVENT_TELEPORT, 5000); + break; + case EVENT_EMERGE: + me->RemoveAllAuras(); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + DoCast(me, SPELL_EMERGE); + events.ScheduleEvent(EVENT_ATTACK, 2500); + break; + case EVENT_ATTACK: + me->SetReactState(REACT_AGGRESSIVE); + break; + default: + break; + } + } + + DoMeleeAttackIfReady(); + } + + void JustSummoned(Creature* summon) override + { + if (summon->GetEntry() != NPC_TRASHING_CHARGE) + return; + + summon->SetReactState(REACT_PASSIVE); + summon->CastSpell(summon, SPELL_TRASHING_CHARGE_EFFECT); + summon->DespawnOrUnsummon(6000); + } + + private: + EncounterState stateIntro; + uint32 countTrashingCharge; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetInstanceAI<boss_corborusAI>(creature); + } +}; + +// 43391 - Rock Borer +class npc_rock_borer : public CreatureScript +{ + public: + npc_rock_borer() : CreatureScript("npc_rock_borer") { } + + struct npc_rock_borerAI : public ScriptedAI + { + npc_rock_borerAI(Creature* creature) : ScriptedAI(creature) + { + me->SetDisableGravity(true); + me->SetReactState(REACT_PASSIVE); + events.ScheduleEvent(EVENT_EMERGED, 1200); + events.ScheduleEvent(EVENT_ROCK_BORE, urand(15000, 20000)); // Need sniffs for this timer + } + + void IsSummonedBy(Unit* summoner) override + { + me->SetInCombatState(false, summoner); + DoCast(SPELL_ROCK_BORER_EMERGE); + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim() && me->GetReactState() != REACT_PASSIVE) + return; + + events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_EMERGED: + me->RemoveAurasDueToSpell(SPELL_ROCK_BORER_EMERGE); + me->SetReactState(REACT_AGGRESSIVE); + break; + case EVENT_ROCK_BORE: + DoCast(SPELL_ROCK_BORE); + events.ScheduleEvent(EVENT_ROCK_BORE, urand(15000, 20000)); // Need sniffs for this timer + break; + default: + break; + } + } + + DoMeleeAttackIfReady(); + } + + private: + EventMap events; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetInstanceAI<npc_rock_borerAI>(creature); + } +}; + +void AddSC_boss_corborus() +{ + new boss_corborus(); + new npc_rock_borer(); +} diff --git a/src/server/scripts/Maelstrom/Stonecore/boss_high_priestess_azil.cpp b/src/server/scripts/Maelstrom/Stonecore/boss_high_priestess_azil.cpp new file mode 100644 index 00000000000..0535ac64a9f --- /dev/null +++ b/src/server/scripts/Maelstrom/Stonecore/boss_high_priestess_azil.cpp @@ -0,0 +1,808 @@ +/* + * Copyright (C) 2008-2014 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 "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "SpellScript.h" +#include "Player.h" +#include "Vehicle.h" +#include "stonecore.h" + +enum Spells +{ + SPELL_ENERGY_SHIELD = 82858, + + SPELL_CURSE_OF_BLOOD = 79345, + SPELL_FORCE_GRIP = 79351, + SPELL_SUMMON_GRAVITY_WELL = 79340, + SPELL_EARTH_FURY_ENERGY_SHIELD = 79050, + + // Gravity Well + SPELL_GRAVITY_WELL_VISUAL = 79245, + SPELL_GRAVITY_WELL_AURA_DAMAGE = 79244, + SPELL_GRAVITY_WELL_AURA_PULL = 79333, + + SPELL_GRAVITY_WELL_DAMAGE = 79249, + SPELL_GRAVITY_WELL_PULL = 79332, + + // Fury of Earth phase + SPELL_EARTH_FURY_CASTING_VISUAL = 79002, + SPELL_SEISMIC_SHARD_SUMMON_1 = 86860, + SPELL_SEISMIC_SHARD_SUMMON_2 = 86858, + SPELL_SEISMIC_SHARD_SUMMON_3 = 86856, + SPELL_SEISMIC_SHARD_VISUAL = 79009, + SPELL_SEISMIC_SHARD_PREPARE = 86862, + SPELL_SEISMIC_SHARD_TARGETING = 80511, + SPELL_SEISMIC_SHARD_LAUNCH = 79015, + SPELL_SEISMIC_SHARD_MISSLE = 79014, + SPELL_EJECT_ALL_PASSENGERS = 68576, + + // Add wave spells + SPELL_SUMMON_WAVE_SOUTH = 79200, + SPELL_SUMMON_WAVE_WEST = 79196, + SPELL_SUMMON_ADD_SOUTH = 79193, + SPELL_SUMMON_ADD_WEST = 79199, +}; + +enum NPCs +{ + NPC_DEVOUT_FOLLOWER = 42428, + NPC_SEISMIC_SHARD = 42355, +}; + +enum Texts +{ + SAY_AGGRO = 0, + SAY_PHASE_TWO = 1, + SAY_DEATH = 2, +}; + +enum Events +{ + EVENT_NONE, + + EVENT_INTRO_MOVE, + + EVENT_CURSE_OF_BLOOD, + EVENT_FORCE_GRIP, + EVENT_SUMMON_GRAVITY_WELL, + EVENT_ENERGY_SHIELD, + EVENT_EARTH_FURY, + + EVENT_SUMMON_WAVE_SOUTH, + EVENT_SUMMON_WAVE_WEST, + + EVENT_GRAVITY_WELL_AURA_DAMAGE, + EVENT_GRAVITY_WELL_AURA_PULL, + + // Phase 2: Fury of Earth + EVENT_EARTH_FURY_FLY_UP, + EVENT_EARTH_FURY_FLY_ABOVE_PLATFORM, + EVENT_EARTH_FURY_CHECK_SEAT0, + EVENT_EARTH_FURY_LAUNCH_SHARD, + EVENT_EARTH_FURY_FLY_DOWN, + EVENT_START_ATTACK, + + EVENT_LAUNCH, + EVENT_SEISMIC_SHARD_MOUNT +}; + +enum EventGroups +{ + EVENT_GROUP_PHASE_ONE, + EVENT_GROUP_ADDS, +}; + +enum Points +{ + POINT_NONE, + + POINT_INTRO_MOVE, + POINT_FLY_UP, + POINT_ABOVE_PLATFORM, + POINT_PLATFORM, + POINT_GROUND, +}; + +Position const GroundPos = { 1331.82f, 980.314f, 207.542f }; +Position const AbovePlatformPos = { 1336.21f, 960.813f, 215.0f }; + +// TO-DO: +// - Find out why NPCs summoned by boss are usually two times bigger than their normal size. +// - Find more sniffs and script Force Grip spell (79351) + +class boss_high_priestess_azil : public CreatureScript +{ + public: + boss_high_priestess_azil() : CreatureScript("boss_high_priestess_azil") { } + + struct boss_high_priestess_azilAI : public BossAI + { + boss_high_priestess_azilAI(Creature* creature) : BossAI(creature, DATA_HIGH_PRIESTESS_AZIL), vehicle(creature->GetVehicleKit()) + { + ASSERT(vehicle); + } + + Vehicle* vehicle; + + void Reset() override + { + _Reset(); + + me->SetCanFly(false); + me->SetDisableGravity(false); + me->SetReactState(REACT_PASSIVE); + + events.ScheduleEvent(EVENT_INTRO_MOVE, 2000); + events.ScheduleEvent(EVENT_CURSE_OF_BLOOD, 6000, EVENT_GROUP_PHASE_ONE); + events.ScheduleEvent(EVENT_FORCE_GRIP, urand(8000,10000), EVENT_GROUP_PHASE_ONE); + events.ScheduleEvent(EVENT_SUMMON_GRAVITY_WELL, 16000, EVENT_GROUP_PHASE_ONE); + events.ScheduleEvent(EVENT_ENERGY_SHIELD, urand(35000,36000)); + events.ScheduleEvent(EVENT_SUMMON_WAVE_SOUTH, 0); + events.ScheduleEvent(EVENT_SUMMON_WAVE_WEST, 40000); + } + + void EnterCombat(Unit* /*victim*/) override + { + _EnterCombat(); + + DoCast(SPELL_ENERGY_SHIELD); + Talk(SAY_AGGRO); + } + + void JustDied(Unit* /*killer*/) override + { + Talk(SAY_DEATH); + } + + /* + void PassengerBoarded(Unit* who, int8 seatId, bool apply) override + { + if (!apply || who->GetEntry() != NPC_SEISMIC_SHARD) + return; + + Movement::MoveSplineInit init(who); + init.DisableTransportPathTransformations(); + if (seatId == 0) + init.MoveTo(12.13748f, 0.0f, 2.442475f); + else if (seatId == 1) + init.MoveTo(12.13748f, 17.5f, 11.19248f); + else + init.MoveTo(12.13748f, -17.5f, 11.19248f); + init.Launch(); + } + */ + + void MovementInform(uint32 type, uint32 id) override + { + if (type != POINT_MOTION_TYPE && id != POINT_INTRO_MOVE) + return; + + switch (id) + { + case POINT_INTRO_MOVE: + me->RemoveAurasDueToSpell(SPELL_ENERGY_SHIELD); + me->SetReactState(REACT_AGGRESSIVE); + break; + case POINT_FLY_UP: + me->SetCanFly(true); + me->SetDisableGravity(true); + events.ScheduleEvent(EVENT_EARTH_FURY_FLY_ABOVE_PLATFORM, 1000); + break; + case POINT_ABOVE_PLATFORM: + me->SetFacingTo(5.218534f); + DoCast(SPELL_EARTH_FURY_CASTING_VISUAL); + DoCast(SPELL_SEISMIC_SHARD_SUMMON_1); + DoCast(SPELL_SEISMIC_SHARD_SUMMON_2); + DoCast(SPELL_SEISMIC_SHARD_SUMMON_3); + events.ScheduleEvent(EVENT_EARTH_FURY_CHECK_SEAT0, 6700); + break; + case POINT_GROUND: + DoCast(SPELL_EJECT_ALL_PASSENGERS); + me->SetCanFly(false); + me->SetDisableGravity(false); + me->SetReactState(REACT_AGGRESSIVE); + // Find more sniffs to correct these timers, this was copied from Reset() void. + events.ScheduleEvent(EVENT_CURSE_OF_BLOOD, 6000, EVENT_GROUP_PHASE_ONE); + events.ScheduleEvent(EVENT_FORCE_GRIP, urand(8000, 10000), EVENT_GROUP_PHASE_ONE); + events.ScheduleEvent(EVENT_SUMMON_GRAVITY_WELL, 16000, EVENT_GROUP_PHASE_ONE); + break; + default: + break; + } + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_INTRO_MOVE: + me->GetMotionMaster()->MoveJump(GroundPos, me->GetSpeed(MOVE_FLIGHT), 1.918408f, POINT_INTRO_MOVE); + break; + case EVENT_CURSE_OF_BLOOD: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true)) + DoCast(target, SPELL_CURSE_OF_BLOOD); + events.ScheduleEvent(EVENT_CURSE_OF_BLOOD, urand(13000, 15000), EVENT_GROUP_PHASE_ONE); + break; + case EVENT_FORCE_GRIP: + DoCastVictim(SPELL_FORCE_GRIP); + events.ScheduleEvent(EVENT_CURSE_OF_BLOOD, urand(13000, 15000), EVENT_GROUP_PHASE_ONE); + break; + case EVENT_SUMMON_GRAVITY_WELL: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true)) + DoCast(target, SPELL_SUMMON_GRAVITY_WELL); + events.ScheduleEvent(EVENT_SUMMON_GRAVITY_WELL, urand(13000, 15000), EVENT_GROUP_PHASE_ONE); + break; + case EVENT_ENERGY_SHIELD: + events.CancelEventGroup(EVENT_GROUP_PHASE_ONE); + DoCast(SPELL_EARTH_FURY_ENERGY_SHIELD); + events.ScheduleEvent(EVENT_EARTH_FURY, 0); + break; + case EVENT_EARTH_FURY: + countSeismicShard = 3; + me->SetReactState(REACT_PASSIVE); + me->SetFacingTo(5.862942f); + events.ScheduleEvent(EVENT_EARTH_FURY_FLY_UP, 1600); + break; + case EVENT_EARTH_FURY_FLY_UP: + Talk(SAY_PHASE_TWO); + me->GetMotionMaster()->MovePoint(POINT_FLY_UP, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ() + 5); + break; + case EVENT_EARTH_FURY_FLY_ABOVE_PLATFORM: + me->GetMotionMaster()->MovePoint(POINT_ABOVE_PLATFORM, AbovePlatformPos); + break; + case EVENT_EARTH_FURY_CHECK_SEAT0: + if (!vehicle->GetPassenger(0)) + DoCast(SPELL_SEISMIC_SHARD_PREPARE); + events.ScheduleEvent(EVENT_EARTH_FURY_LAUNCH_SHARD, 1800); + break; + case EVENT_EARTH_FURY_LAUNCH_SHARD: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true)) + { + me->SetFacingToObject(target); + DoCast(target, SPELL_SEISMIC_SHARD_TARGETING); + DoCast(SPELL_SEISMIC_SHARD_LAUNCH); + countSeismicShard -= 1; + } + events.ScheduleEvent(countSeismicShard > 0 ? EVENT_EARTH_FURY_CHECK_SEAT0 : EVENT_EARTH_FURY_FLY_DOWN, 4800); + break; + case EVENT_EARTH_FURY_FLY_DOWN: + { + me->RemoveAurasDueToSpell(SPELL_EARTH_FURY_CASTING_VISUAL); + me->RemoveAurasDueToSpell(SPELL_EARTH_FURY_ENERGY_SHIELD); + Position pos = me->GetPosition(); + pos.m_positionZ = me->GetMap()->GetHeight(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ()); + me->GetMotionMaster()->MovePoint(POINT_GROUND, pos); + break; + } + case EVENT_SUMMON_WAVE_SOUTH: + if (Creature* worldtrigger = me->FindNearestCreature(NPC_WORLDTRIGGER, 150.0f)) + worldtrigger->CastSpell(worldtrigger, SPELL_SUMMON_WAVE_SOUTH); + events.ScheduleEvent(EVENT_SUMMON_WAVE_SOUTH, 12000); + break; + case EVENT_SUMMON_WAVE_WEST: + if (Creature* worldtrigger = me->FindNearestCreature(NPC_WORLDTRIGGER, 150.0f)) + worldtrigger->CastSpell(worldtrigger, SPELL_SUMMON_WAVE_WEST); + events.ScheduleEvent(EVENT_SUMMON_WAVE_WEST, 20000); + break; + default: + break; + } + } + + DoMeleeAttackIfReady(); + } + + private: + uint8 countSeismicShard; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetInstanceAI<boss_high_priestess_azilAI>(creature); + } +}; + +// 42428 - Devout Follower +class npc_devout_follower : public CreatureScript +{ +public: + npc_devout_follower() : CreatureScript("npc_devout_follower") { } + + struct npc_devout_followerAI : public ScriptedAI + { + npc_devout_followerAI(Creature* creature) : ScriptedAI(creature) { } + + void IsSummonedBy(Unit* summoner) override + { + if (summoner->GetEntry() != NPC_WORLDTRIGGER) + return; + + if (Unit* target = me->SelectNearestPlayer(200.0f)) + { + me->AddThreat(target, 0.0f); + me->SetInCombatWith(target); + target->SetInCombatWith(me); + DoStartMovement(target); + me->Attack(target, true); + } + else + me->GetMotionMaster()->MovePoint(POINT_NONE, summoner->GetPosition()); + } + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetInstanceAI<npc_devout_followerAI>(creature); + } +}; + +// 42499 - Gravity Well +class npc_gravity_well : public CreatureScript +{ +public: + npc_gravity_well() : CreatureScript("npc_gravity_well") { } + + struct npc_gravity_wellAI : public ScriptedAI + { + npc_gravity_wellAI(Creature* creature) : ScriptedAI(creature) + { + me->SetReactState(REACT_PASSIVE); + DoCast(SPELL_GRAVITY_WELL_VISUAL); + events.ScheduleEvent(EVENT_GRAVITY_WELL_AURA_DAMAGE, 3200); + events.ScheduleEvent(EVENT_GRAVITY_WELL_AURA_PULL, 4500); + if (!me->GetMap()->IsHeroic()) + me->DespawnOrUnsummon(23200); + } + + void KilledUnit(Unit* victim) override + { + if (victim->GetEntry() != NPC_DEVOUT_FOLLOWER) + return; + + me->SetObjectScale(me->GetObjectScale() - 0.25f); + if (me->GetObjectScale() <= 0.0f) + me->DespawnOrUnsummon(1000); + } + + void UpdateAI(uint32 diff) override + { + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_GRAVITY_WELL_AURA_DAMAGE: + me->RemoveAurasDueToSpell(SPELL_GRAVITY_WELL_VISUAL); + DoCast(SPELL_GRAVITY_WELL_AURA_DAMAGE); + break; + case EVENT_GRAVITY_WELL_AURA_PULL: + DoCast(SPELL_GRAVITY_WELL_AURA_PULL); + break; + default: + break; + } + } + } + + private: + EventMap events; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetInstanceAI<npc_gravity_wellAI>(creature); + } +}; + +// 42355 - Seismic Shard +class npc_seismic_shard : public CreatureScript +{ +public: + npc_seismic_shard() : CreatureScript("npc_seismic_shard") { } + + struct npc_seismic_shardAI : public ScriptedAI + { + npc_seismic_shardAI(Creature* creature) : ScriptedAI(creature) + { + instance = creature->GetInstanceScript(); + me->SetDisableGravity(true); + me->SetReactState(REACT_PASSIVE); + DoCast(SPELL_SEISMIC_SHARD_VISUAL); + + Movement::MoveSplineInit init(me); + FillPath(me->GetPosition(), init.Path()); + init.SetFly(); + init.Launch(); + + events.ScheduleEvent(EVENT_SEISMIC_SHARD_MOUNT, 2400); + } + + void UpdateAI(uint32 diff) override + { + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_SEISMIC_SHARD_MOUNT: + if (Creature* highPriestAzil = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_HIGH_PRIESTESS_AZIL))) + if (Vehicle* vehicle = highPriestAzil->GetVehicleKit()) + me->EnterVehicle(highPriestAzil, vehicle->GetNextEmptySeat(0, false)->first); + break; + default: + break; + } + } + + } + + private: + void FillPath(Position const& pos, Movement::PointsArray& path) + { + G3D::Vector3 point; + + point.x = pos.GetPositionX(); + point.y = pos.GetPositionY(); + point.z = pos.GetPositionZ(); + + point.x -= 1.0f; + path.push_back(point); + + point.x += 1.0f; + path.push_back(point); + + point.z += 25.0f; + path.push_back(point); + + path.push_back(point); + } + + InstanceScript* instance; + EventMap events; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetInstanceAI<npc_seismic_shardAI>(creature); + } +}; + +// 79200 - Summon Follower +class spell_summon_wave_south : public SpellScriptLoader +{ +public: + spell_summon_wave_south() : SpellScriptLoader("spell_summon_wave_south") { } + + class spell_summon_wave_south_SpellScript : public SpellScript + { + PrepareSpellScript(spell_summon_wave_south_SpellScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_SUMMON_ADD_SOUTH)) + return false; + return true; + } + + void HandleScript(SpellEffIndex /*effIndex*/) + { + Unit* caster = GetCaster(); + for (uint8 i = 0; i < 3; i++) + caster->CastSpell(caster, SPELL_SUMMON_ADD_SOUTH, true); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_summon_wave_south_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_summon_wave_south_SpellScript(); + } +}; + +// 79196 - Summon Follower +class spell_summon_wave_west : public SpellScriptLoader +{ +public: + spell_summon_wave_west() : SpellScriptLoader("spell_summon_wave_west") { } + + class spell_summon_wave_west_SpellScript : public SpellScript + { + PrepareSpellScript(spell_summon_wave_west_SpellScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_SUMMON_ADD_WEST)) + return false; + return true; + } + + void HandleScript(SpellEffIndex /*effIndex*/) + { + Unit* caster = GetCaster(); + for (uint8 i = 0; i < 10; i++) + caster->CastSpell(caster, SPELL_SUMMON_ADD_WEST, true); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_summon_wave_west_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_summon_wave_west_SpellScript(); + } +}; + +// 79251 - Gravity Well (casts damage spell on units within 10 yards) +class PlayerPetOrDevoutFollowerCheck +{ +public: + bool operator()(WorldObject* object) const + { + // Valid targets are players, pets and Devout Followers + if (Creature* creature = object->ToCreature()) + return (!creature->ToPet() && object->GetEntry() != NPC_DEVOUT_FOLLOWER); + return (!object->ToPlayer()); + } +}; + +class spell_gravity_well_damage_nearby : public SpellScriptLoader +{ +public: + spell_gravity_well_damage_nearby() : SpellScriptLoader("spell_gravity_well_damage_nearby") { } + + class spell_gravity_well_damage_nearby_SpellScript : public SpellScript + { + PrepareSpellScript(spell_gravity_well_damage_nearby_SpellScript); + + void SetRadiusMod() + { + GetSpell()->SetSpellValue(SPELLVALUE_RADIUS_MOD, int32(GetCaster()->GetObjectScale() * 10000 * 2 / 3)); + } + + void FilterTargets(std::list<WorldObject*>& unitList) + { + unitList.remove_if(PlayerPetOrDevoutFollowerCheck()); + } + + void HandleScript(SpellEffIndex /*effIndex*/) + { + GetCaster()->CastSpell(GetHitUnit(), SPELL_GRAVITY_WELL_DAMAGE, true); + } + + void Register() override + { + BeforeCast += SpellCastFn(spell_gravity_well_damage_nearby_SpellScript::SetRadiusMod); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_gravity_well_damage_nearby_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnEffectHitTarget += SpellEffectFn(spell_gravity_well_damage_nearby_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_gravity_well_damage_nearby_SpellScript(); + } +}; + +// 79249 - Gravity Well (damage) +class spell_gravity_well_damage : public SpellScriptLoader +{ +public: + spell_gravity_well_damage() : SpellScriptLoader("spell_gravity_well_damage") { } + + class spell_gravity_well_damage_SpellScript : public SpellScript + { + PrepareSpellScript(spell_gravity_well_damage_SpellScript); + + void CalculateDamage(SpellEffIndex /*effIndex*/) + { + Unit* target = GetHitUnit(); + if (!target) + return; + + float distance = GetCaster()->GetDistance2d(target); + + if (target->GetEntry() == NPC_DEVOUT_FOLLOWER) + SetHitDamage(int32(200000 - (1000 * distance))); //need more research on this formula, damage values from sniffs: 189264, 190318, 190478, 196134, 197672, 199735 + else + SetHitDamage(int32(4000 - (200 * distance))); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_gravity_well_damage_SpellScript::CalculateDamage, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_gravity_well_damage_SpellScript(); + } +}; + +// 79332 - Gravity Well (pull units within 10 yards) +class PulledRecentlyCheck +{ +public: + bool operator()(WorldObject* object) const + { + return (object->ToUnit() && object->ToUnit()->HasAura(SPELL_GRAVITY_WELL_PULL)); + } +}; + +class spell_gravity_well_pull : public SpellScriptLoader +{ +public: + spell_gravity_well_pull() : SpellScriptLoader("spell_gravity_well_pull") { } + + class spell_gravity_well_pull_SpellScript : public SpellScript + { + PrepareSpellScript(spell_gravity_well_pull_SpellScript); + + void SetRadiusMod() + { + GetSpell()->SetSpellValue(SPELLVALUE_RADIUS_MOD, int32(GetCaster()->GetObjectScale() * 10000 * 2 / 3)); + } + + void FilterTargets(std::list<WorldObject*>& unitList) + { + unitList.remove_if(PulledRecentlyCheck()); + } + + void Register() override + { + BeforeCast += SpellCastFn(spell_gravity_well_pull_SpellScript::SetRadiusMod); + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_gravity_well_pull_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_gravity_well_pull_SpellScript(); + } +}; + +// 86862 - Seismic Shard (forces target to cast 86863) +class spell_seismic_shard_prepare : public SpellScriptLoader +{ +public: + spell_seismic_shard_prepare() : SpellScriptLoader("spell_seismic_shard_prepare") { } + + class spell_seismic_shard_prepare_SpellScript : public SpellScript + { + PrepareSpellScript(spell_seismic_shard_prepare_SpellScript); + + void SetTarget(WorldObject*& target) + { + target = GetCaster()->FindNearestCreature(NPC_SEISMIC_SHARD, 50.0f); + } + + void Register() override + { + OnObjectTargetSelect += SpellObjectTargetSelectFn(spell_seismic_shard_prepare_SpellScript::SetTarget, EFFECT_0, TARGET_UNIT_NEARBY_ENTRY); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_seismic_shard_prepare_SpellScript(); + } +}; + +// 86863 - Seismic Shard (moves shard to seat 0) +class spell_seismic_shard_change_seat : public SpellScriptLoader +{ +public: + spell_seismic_shard_change_seat() : SpellScriptLoader("spell_seismic_shard_change_seat") { } + + class spell_seismic_shard_change_seat_SpellScript : public SpellScript + { + PrepareSpellScript(spell_seismic_shard_change_seat_SpellScript); + + void SetTarget(WorldObject*& target) + { + if (InstanceScript* instance = GetCaster()->GetInstanceScript()) + target = ObjectAccessor::GetCreature(*GetCaster(), instance->GetGuidData(DATA_HIGH_PRIESTESS_AZIL)); + } + + void ChangeSeat(SpellEffIndex /*effIndex*/) + { + GetCaster()->ExitVehicle(); + if (GetHitUnit()->IsVehicle()) + GetCaster()->EnterVehicle(GetHitUnit(), 0); + } + + void Register() override + { + OnObjectTargetSelect += SpellObjectTargetSelectFn(spell_seismic_shard_change_seat_SpellScript::SetTarget, EFFECT_0, TARGET_UNIT_NEARBY_ENTRY); + OnEffectHitTarget += SpellEffectFn(spell_seismic_shard_change_seat_SpellScript::ChangeSeat, EFFECT_0, SPELL_EFFECT_APPLY_AURA); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_seismic_shard_change_seat_SpellScript(); + } +}; + +// 79015 - Seismic Shard (launches shard) +class spell_seismic_shard : public SpellScriptLoader +{ +public: + spell_seismic_shard() : SpellScriptLoader("spell_seismic_shard") { } + + class spell_seismic_shard_SpellScript : public SpellScript + { + PrepareSpellScript(spell_seismic_shard_SpellScript); + + void HandleScript(SpellEffIndex /*effIndex*/) + { + Creature* target = GetHitUnit()->ToCreature(); + if (!target) + return; + + target->ExitVehicle(); + DynamicObject* dynamicObject = GetCaster()->GetDynObject(SPELL_SEISMIC_SHARD_TARGETING); + target->CastSpell(dynamicObject->GetPositionX(), dynamicObject->GetPositionY(), dynamicObject->GetPositionZ(), SPELL_SEISMIC_SHARD_MISSLE, true); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_seismic_shard_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_seismic_shard_SpellScript(); + } +}; + +void AddSC_boss_high_priestess_azil() +{ + new boss_high_priestess_azil(); + new npc_devout_follower(); + new npc_gravity_well(); + new npc_seismic_shard(); + new spell_summon_wave_south(); + new spell_summon_wave_west(); + new spell_gravity_well_damage_nearby(); + new spell_gravity_well_damage(); + new spell_gravity_well_pull(); + new spell_seismic_shard_prepare(); + new spell_seismic_shard_change_seat(); + new spell_seismic_shard(); +} diff --git a/src/server/scripts/Maelstrom/Stonecore/boss_ozruk.cpp b/src/server/scripts/Maelstrom/Stonecore/boss_ozruk.cpp new file mode 100644 index 00000000000..92c9bba4bc1 --- /dev/null +++ b/src/server/scripts/Maelstrom/Stonecore/boss_ozruk.cpp @@ -0,0 +1,287 @@ +/* + * Copyright (C) 2008-2014 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 "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "SpellScript.h" +#include "SpellAuraEffects.h" +#include "Vehicle.h" +#include "stonecore.h" + +enum Spells +{ + SPELL_ELEMENTIUM_BULWARK = 78939, + SPELL_GROUND_SLAM = 78903, + SPELL_ELEMENTIUM_SPIKE_SHIELD = 78835, + SPELL_SHATTER = 78807, + SPELL_ENRAGE = 80467, + + // Rupture Controller and Rupture + SPELL_RUPTURE = 92393, +// SPELL_RUPTURE_SUMMON_CENTER? = 95669, // summons rupture 8 yards front +// SPELL_RUPTURE_SUMMON_LEFT? = 95348, // summons rupture 3 yards left? +// SPELL_RUPTURE_SUMMON_RIGHT? = 92383, // summons rupture 3 yards right? + SPELL_RUPTURE_DAMAGE = 92381, +}; + +enum NPCs +{ + NPC_BOUNCER_SPIKE = 42189, + NPC_RUPTURE_CONTROLLER = 49597, + NPC_RUPTURE = 49576, +}; + +enum Texts +{ + SAY_AGGRO = 0, + SAY_ELEMENTIUM_BULWARK = 1, + SAY_ELEMENTIUM_SPIKE_SHIELD = 2, + SAY_ENRAGE = 3, + SAY_DEATH = 4, +}; + +enum Events +{ + EVENT_NONE, + + EVENT_ELEMENTIUM_BULWARK, + EVENT_GROUND_SLAM, + EVENT_ELEMENTIUM_SPIKE_SHIELD, + EVENT_SHATTER, + EVENT_ENRAGE, + + EVENT_START_ATTACK, +}; + +// TO-DO: +// - Find heroic sniffs and spawn Ruptures using spells commented above. +// - Make Bouncer Spikes enter ozruk without jump animation. + +class boss_ozruk : public CreatureScript +{ + public: + boss_ozruk() : CreatureScript("boss_ozruk") { } + + struct boss_ozrukAI : public BossAI + { + boss_ozrukAI(Creature* creature) : BossAI(creature, DATA_OZRUK) { } + + void Reset() override + { + _Reset(); + + me->SetReactState(REACT_AGGRESSIVE); + + events.ScheduleEvent(EVENT_ELEMENTIUM_BULWARK, 5000); + events.ScheduleEvent(EVENT_GROUND_SLAM, 10000); + events.ScheduleEvent(EVENT_ELEMENTIUM_SPIKE_SHIELD, 13000); + + RemoveBouncerSpikes(); + } + + void EnterCombat(Unit* /*victim*/) override + { + _EnterCombat(); + + Talk(SAY_AGGRO); + } + + void JustSummoned(Creature* summon) override + { + if (summon->GetEntry() != NPC_RUPTURE_CONTROLLER) + return; + + summon->SetReactState(REACT_PASSIVE); + summon->CastSpell(summon, SPELL_RUPTURE, true); + summon->DespawnOrUnsummon(10000); + } + + void DamageTaken(Unit* /*attacker*/, uint32 &damage) override + { + if (!me->HealthBelowPctDamaged(25, damage) || me->HasAura(SPELL_ENRAGE)) + return; + + DoCast(me, SPELL_ENRAGE); + me->Say(SAY_ENRAGE); + } + + void JustDied(Unit* killer) override + { + me->Say(SAY_DEATH, killer); // receiver is the killer, sniff source! + + RemoveBouncerSpikes(); + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING) || me->HasAura(SPELL_ELEMENTIUM_SPIKE_SHIELD)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_ELEMENTIUM_BULWARK: + DoCast(me, SPELL_ELEMENTIUM_BULWARK); + Talk(SAY_ELEMENTIUM_BULWARK); + break; + case EVENT_GROUND_SLAM: + me->SetReactState(REACT_PASSIVE); + me->AttackStop(); + DoCast(me, SPELL_GROUND_SLAM); + events.ScheduleEvent(EVENT_START_ATTACK, 4600); + break; + case EVENT_ELEMENTIUM_SPIKE_SHIELD: + DoCast(me, SPELL_ELEMENTIUM_SPIKE_SHIELD); + Talk(SAY_ELEMENTIUM_SPIKE_SHIELD); + events.ScheduleEvent(EVENT_SHATTER, 10000); + break; + case EVENT_SHATTER: + RemoveBouncerSpikes(); + me->SetReactState(REACT_PASSIVE); + me->AttackStop(); + DoCast(me, SPELL_SHATTER); + events.ScheduleEvent(EVENT_START_ATTACK, 4600); + // Spells are cast in same order everytime after Shatter, so we schedule them here + events.ScheduleEvent(EVENT_ELEMENTIUM_BULWARK, urand(3000,4000)); + events.ScheduleEvent(EVENT_GROUND_SLAM, urand(7000,9000)); + events.ScheduleEvent(EVENT_ELEMENTIUM_SPIKE_SHIELD, urand(10000,12000)); + break; + case EVENT_START_ATTACK: + me->SetReactState(REACT_AGGRESSIVE); + break; + default: + break; + } + } + + DoMeleeAttackIfReady(); + } + + void RemoveBouncerSpikes() + { + Vehicle* vehicle = me->GetVehicleKit(); + if (!vehicle) + return; + + for (uint8 i = 0; i < vehicle->GetAvailableSeatCount(); i++) + if (Unit* passenger = vehicle->GetPassenger(i)) + if (Creature* creature = passenger->ToCreature()) + creature->RemoveFromWorld(); + } + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetInstanceAI<boss_ozrukAI>(creature); + } +}; + +// 92393 - Rupture +class spell_rupture : public SpellScriptLoader +{ +public: + spell_rupture() : SpellScriptLoader("spell_rupture") { } + + class spell_rupture_AuraScript : public AuraScript + { + PrepareAuraScript(spell_rupture_AuraScript); + + void HandleEffectPeriodic(AuraEffect const* aurEff) + { + Unit* caster = GetCaster(); + + float dist = aurEff->GetTickNumber() * 8.0f; + + // probably hack, should use spells (see Spells enum above) + Position pos = caster->GetNearPosition(dist, 0.0f); + SummonRupture(caster, pos); + + pos = caster->GetNearPosition(dist, 0.2f); + SummonRupture(caster, pos); + + pos = caster->GetNearPosition(dist, -0.2f); + SummonRupture(caster, pos); + } + + void SummonRupture(Unit* caster, Position pos) + { + Creature* rupture = caster->SummonCreature(NPC_RUPTURE, pos, TEMPSUMMON_TIMED_DESPAWN, 2500); + if (!rupture) + return; + + rupture->SetReactState(REACT_PASSIVE); + rupture->CastSpell(rupture, SPELL_RUPTURE_DAMAGE, true); + } + + void Register() + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_rupture_AuraScript::HandleEffectPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_rupture_AuraScript(); + } +}; + +// 78835 - Elementium Spike Shield +class spell_elementium_spike_shield : public SpellScriptLoader +{ +public: + spell_elementium_spike_shield() : SpellScriptLoader("spell_elementium_spike_shield") { } + + class spell_elementium_spike_shield_SpellScript : public SpellScript + { + PrepareSpellScript(spell_elementium_spike_shield_SpellScript); + + void HandleBouncerSpikes() + { + Unit* caster = GetCaster(); + Vehicle* vehicle = caster->GetVehicleKit(); + if (!vehicle) + return; + + for (uint8 i = 0; i < vehicle->GetAvailableSeatCount(); i++) + if (Creature* summon = caster->SummonCreature(NPC_BOUNCER_SPIKE, caster->GetPosition(), TEMPSUMMON_TIMED_DESPAWN, 10000)) + summon->EnterVehicle(caster, i); + } + + void Register() override + { + OnCast += SpellCastFn(spell_elementium_spike_shield_SpellScript::HandleBouncerSpikes); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_elementium_spike_shield_SpellScript(); + } +}; + +void AddSC_boss_ozruk() +{ + new boss_ozruk(); + new spell_rupture(); + new spell_elementium_spike_shield(); +} diff --git a/src/server/scripts/Maelstrom/Stonecore/boss_slabhide.cpp b/src/server/scripts/Maelstrom/Stonecore/boss_slabhide.cpp new file mode 100644 index 00000000000..6827312deef --- /dev/null +++ b/src/server/scripts/Maelstrom/Stonecore/boss_slabhide.cpp @@ -0,0 +1,599 @@ +/* + * Copyright (C) 2008-2014 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 "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "SpellScript.h" +#include "stonecore.h" + +enum Spells +{ + SPELL_FACE_RANDOM_PLAYER = 82530, + + // Stalactite Trigger - Trash, On Ground + SPELL_STALACTITE_SUMMON_TRIGGER = 81028, + + // Slabhide + SPELL_LAVA_FISSURE = 80803, + SPELL_SAND_BLAST = 80807, + SPELL_STALACTITE_SUMMON = 80656, +// SPELL_COOLDOWN_5S = 95323, Cooldown: Creature Special 1 (5s)? + SPELL_CRYSTAL_STORM = 92305, + SPELL_CRYSTAL_STORM_TRIGGER = 92265, + + // Lava Fissure + SPELL_LAVA_FISSURE_CRACK = 80798, + SPELL_LAVA_FISSURE_ERUPTION = 80800, + + // Stalactite Trigger - Boss + SPELL_STALACTITE_SHADE = 80654, + SPELL_STALACTITE_MISSLE = 80643, + SPELL_STALACTITE_CREATE = 80647, +}; + +enum Entries +{ + NPC_LAVA_FISSURE = 43242, + NPC_STALACTITE_TRIGGER_GROUND = 43357, + NPC_STALACTITE_TRIGGER = 43159, + GO_STALACTITE = 204337, +}; + +enum Actions +{ + ACTION_STALACTITE_MISSLE, +}; + +enum Events +{ + EVENT_NONE, + + // Intro events + EVENT_ROAR_EMOTE, + + // Slabhide combat + EVENT_HANDLE_ROCK_WALLS, + EVENT_LAVA_FISSURE, + EVENT_SAND_BLAST, + EVENT_AIR_PHASE, + EVENT_TAKEOFF, + EVENT_STALACTITE, + EVENT_LAND, + EVENT_ATTACK, + + // Lava Fissure + EVENT_LAVA_FISSURE_ERUPTION, + + // Stalactite Trigger - Boss + EVENT_STALACTITE_MISSLE, +}; + +enum MovementPoints +{ + POINT_NONE, + + POINT_SLABHIDE_INTRO, + POINT_SLABHIDE_INTRO_LAND, + + POINT_SLABHIDE_MIDDLE, + POINT_SLABHIDE_IN_AIR, + POINT_SLABHIDE_LAND, +}; + +Position const SlabhideIntroPos = { 1292.27f, 1226.16f, 265.573f }; +Position const SlabhideIntroLandPos = { 1292.352f, 1226.478f, 247.6368f, 3.630285f }; + +Position const SlabhideMiddlePos = { 1280.73f, 1212.31f, 247.3837f }; +Position const SlabhideInAirPos = { 1280.73f, 1212.31f, 257.3837f }; +Position const SlabhideLandPos = { 1282.7f, 1229.77f, 247.155f, 3.82227f }; + +class boss_slabhide : public CreatureScript +{ + public: + boss_slabhide() : CreatureScript("boss_slabhide") { } + + struct boss_slabhideAI : public BossAI + { + boss_slabhideAI(Creature* creature) : BossAI(creature, DATA_SLABHIDE) + { + me->setActive(true); + me->SetCanFly(true); + me->SetDisableGravity(true); + me->SetByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER); + me->SetReactState(REACT_PASSIVE); + instance->SetData(DATA_SLABHIDE_INTRO, NOT_STARTED); + } + + void Reset() + { + if (instance->GetData(DATA_SLABHIDE_INTRO) == NOT_STARTED) + return; + + _Reset(); + DespawnAll(); + + me->SetCanFly(false); + me->SetDisableGravity(false); + me->RemoveByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER); + me->SetReactState(REACT_AGGRESSIVE); + } + + void EnterCombat(Unit* /*victim*/) override + { + _EnterCombat(); + + events.ScheduleEvent(EVENT_HANDLE_ROCK_WALLS, 4000); + events.ScheduleEvent(EVENT_LAVA_FISSURE, urand(6000, 8000)); + events.ScheduleEvent(EVENT_SAND_BLAST, urand(8000, 10000)); + events.ScheduleEvent(EVENT_AIR_PHASE, 10000); + } + + void JustDied(Unit* /*killer*/) override + { + _JustDied(); + + // Despawn related npcs and gameobjects + DespawnAll(); + } + + void DoAction(int32 action) override + { + switch (action) + { + case ACTION_SLABHIDE_INTRO: + { + if (instance->GetData(DATA_SLABHIDE_INTRO) != NOT_STARTED) + return; + + instance->SetData(DATA_SLABHIDE_INTRO, IN_PROGRESS); + + // Execute Slabhide intro event + me->GetMotionMaster()->MovePoint(POINT_SLABHIDE_INTRO, SlabhideIntroPos); + break; + } + default: + break; + } + } + + void MovementInform(uint32 type, uint32 id) override + { + if (type != POINT_MOTION_TYPE && type != EFFECT_MOTION_TYPE) + return; + + switch (id) + { + case POINT_SLABHIDE_INTRO: + me->SetFacingTo(SlabhideIntroLandPos.GetOrientation()); + me->GetMotionMaster()->MoveLand(POINT_SLABHIDE_INTRO_LAND, SlabhideIntroLandPos); + break; + case POINT_SLABHIDE_INTRO_LAND: + me->SetCanFly(false); + me->SetDisableGravity(false); + me->RemoveByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER); + me->SetHover(false); + me->SetHomePosition(SlabhideIntroLandPos); + me->HandleEmoteCommand(EMOTE_ONESHOT_ROAR); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetReactState(REACT_AGGRESSIVE); + instance->SetData(DATA_SLABHIDE_INTRO, DONE); + break; + case POINT_SLABHIDE_MIDDLE: + events.ScheduleEvent(EVENT_TAKEOFF, 100); + break; + case POINT_SLABHIDE_IN_AIR: + events.ScheduleEvent(EVENT_STALACTITE, 400); + break; + case POINT_SLABHIDE_LAND: + //DoCast(SPELL_COOLDOWN_5S); // unknown purpose + events.ScheduleEvent(EVENT_ATTACK, 1200); + break; + default: + break; + } + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_HANDLE_ROCK_WALLS: // Close rock walls + instance->SetData(DATA_SLABHIDE_ROCK_WALL, false); + break; + case EVENT_LAVA_FISSURE: + DoCast(SPELL_LAVA_FISSURE); + events.ScheduleEvent(EVENT_LAVA_FISSURE, urand(6000, 8000)); + break; + case EVENT_SAND_BLAST: + DoCast(SPELL_SAND_BLAST); + events.ScheduleEvent(EVENT_SAND_BLAST, urand(8000, 11000)); + break; + case EVENT_AIR_PHASE: + events.Reset(); + me->SetReactState(REACT_PASSIVE); + me->AttackStop(); + me->GetMotionMaster()->MovePoint(POINT_SLABHIDE_MIDDLE, SlabhideMiddlePos); + events.ScheduleEvent(EVENT_AIR_PHASE, 60000); + break; + case EVENT_TAKEOFF: + me->GetMotionMaster()->MoveTakeoff(POINT_SLABHIDE_IN_AIR, SlabhideInAirPos); + break; + case EVENT_STALACTITE: + me->SetCanFly(true); + me->SetDisableGravity(true); + me->SetByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER); + me->SetHover(true); + + DoCast(SPELL_STALACTITE_SUMMON); + + events.ScheduleEvent(EVENT_LAND, 8000); + break; + case EVENT_LAND: + { + Position pos = me->GetPosition(); + pos.m_positionZ = me->GetMap()->GetHeight(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ()); + me->GetMotionMaster()->MoveLand(POINT_SLABHIDE_LAND, pos); + break; + } + case EVENT_ATTACK: + me->SetCanFly(false); + me->SetDisableGravity(false); + me->RemoveByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER); + me->SetHover(false); + + events.ScheduleEvent(EVENT_LAVA_FISSURE, urand(6000, 8000)); + events.ScheduleEvent(EVENT_SAND_BLAST, urand(8000, 10000)); + DoCast(SPELL_CRYSTAL_STORM); + me->SetReactState(REACT_AGGRESSIVE); + break; + default: + break; + } + } + + DoMeleeAttackIfReady(); + } + + private: + void DespawnAll() + { + // Despawn stalactite triggers npcs + std::list<Creature*> listStalactiteTrigger; + me->GetCreatureListWithEntryInGrid(listStalactiteTrigger, NPC_STALACTITE_TRIGGER, 200.0f); + if (!listStalactiteTrigger.empty()) + for (std::list<Creature*>::const_iterator itr = listStalactiteTrigger.begin(); itr != listStalactiteTrigger.end(); ++itr) + (*itr)->DespawnOrUnsummon(); + + // Despawn stalactite objects + std::list<GameObject*> listStalactite; + me->GetGameObjectListWithEntryInGrid(listStalactite, GO_STALACTITE, 200.0f); + if (!listStalactite.empty()) + for (std::list<GameObject*>::const_iterator itr = listStalactite.begin(); itr != listStalactite.end(); ++itr) + (*itr)->Delete(); + } + + EventMap events; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetInstanceAI<boss_slabhideAI>(creature); + } +}; + +// 43242 - Lava Fissure +class npc_lava_fissure : public CreatureScript +{ +public: + npc_lava_fissure() : CreatureScript("npc_lava_fissure") { } + + struct npc_lava_fissureAI : public ScriptedAI + { + npc_lava_fissureAI(Creature* creature) : ScriptedAI(creature) + { + me->SetReactState(REACT_PASSIVE); + me->CastSpell(me, SPELL_LAVA_FISSURE_CRACK, true); + events.ScheduleEvent(EVENT_LAVA_FISSURE_ERUPTION, 6000); + } + + void UpdateAI(uint32 diff) override + { + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_LAVA_FISSURE_ERUPTION: + me->RemoveAurasDueToSpell(SPELL_LAVA_FISSURE_CRACK); + me->CastSpell(me, SPELL_LAVA_FISSURE_ERUPTION, true); + me->DespawnOrUnsummon(14000); + break; + default: + break; + } + } + } + + private: + EventMap events; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetInstanceAI<npc_lava_fissureAI>(creature); + } +}; + +// 43159 - Stalactite Trigger - Boss +class npc_stalactite_trigger : public CreatureScript +{ +public: + npc_stalactite_trigger() : CreatureScript("npc_stalactite_trigger") { } + + struct npc_stalactite_triggerAI : public ScriptedAI + { + npc_stalactite_triggerAI(Creature* creature) : ScriptedAI(creature) + { + me->SetReactState(REACT_PASSIVE); + me->SetDisableGravity(true); + me->CastSpell(me, SPELL_STALACTITE_SHADE, true); + events.ScheduleEvent(EVENT_STALACTITE_MISSLE, 5600); + } + + void UpdateAI(uint32 diff) override + { + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_STALACTITE_MISSLE: + DoCast(SPELL_STALACTITE_MISSLE); + me->DespawnOrUnsummon(11000); + break; + default: + break; + } + } + } + + private: + EventMap events; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetInstanceAI<npc_stalactite_triggerAI>(creature); + } +}; + +// 81035 - Stalactite (check if player is near to summon stalactite) +class NotPlayerCheck +{ + public: + bool operator()(WorldObject* object) const + { + return (object->GetTypeId() != TYPEID_PLAYER); + } +}; + +class spell_s81035_stalactite : public SpellScriptLoader +{ +public: + spell_s81035_stalactite() : SpellScriptLoader("spell_s81035_stalactite") { } + + class spell_s81035_stalactite_SpellScript : public SpellScript + { + PrepareSpellScript(spell_s81035_stalactite_SpellScript); + + void FilterTargets(std::list<WorldObject*>& targets) + { + targets.remove_if(NotPlayerCheck()); + } + + void SummonStalactiteTrigger() + { + Unit* caster = GetCaster(); + caster->CastSpell(caster, SPELL_STALACTITE_SUMMON_TRIGGER, true); + } + + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_s81035_stalactite_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnHit += SpellHitFn(spell_s81035_stalactite_SpellScript::SummonStalactiteTrigger); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_s81035_stalactite_SpellScript(); + } +}; + +// 81028 - Stalactite (summons "Stalactite Trigger - Boss", 20 yard radius) +// 80650 - Stalactite (summons "Stalactite Trigger - Boss", 40 yard radius) +class spell_s81028_s80650_stalactite : public SpellScriptLoader +{ +public: + spell_s81028_s80650_stalactite() : SpellScriptLoader("spell_s81028_s80650_stalactite") { } + + class spell_s81028_s80650_stalactite_SpellScript : public SpellScript + { + PrepareSpellScript(spell_s81028_s80650_stalactite_SpellScript); + + void ModDestHeight(SpellDestination& dest) + { + // All stalactite triggers should have Z position 301.3837f, but no way to relocate (not relocateoffset!) height only. + Position offset = { 0.0f, 0.0f, 50.0f, 0.0f }; + dest.RelocateOffset(offset); + } + + void Register() override + { + OnDestinationTargetSelect += SpellDestinationTargetSelectFn(spell_s81028_s80650_stalactite_SpellScript::ModDestHeight, EFFECT_0, TARGET_DEST_CASTER_RANDOM); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_s81028_s80650_stalactite_SpellScript(); + } +}; + +// 80654 - Stalactite (creates visual shade on ground) +// 80643/92653 - Stalactite (launches missle to the ground) +// 80647/92309 - Stalactite (creates stalactite object) +class spell_stalactite_mod_dest_height : public SpellScriptLoader +{ +public: + spell_stalactite_mod_dest_height() : SpellScriptLoader("spell_stalactite_mod_dest_height") { } + + class spell_stalactite_mod_dest_height_SpellScript : public SpellScript + { + PrepareSpellScript(spell_stalactite_mod_dest_height_SpellScript); + + void ModDestHeight(SpellDestination& dest) + { + Unit* caster = GetCaster(); + Position pos = caster->GetPosition(); + pos.m_positionZ = caster->GetMap()->GetHeight(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), true, 100.0f); + dest.Relocate(pos); + } + + void Register() override + { + OnDestinationTargetSelect += SpellDestinationTargetSelectFn(spell_stalactite_mod_dest_height_SpellScript::ModDestHeight, EFFECT_0, TARGET_DEST_CASTER); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_stalactite_mod_dest_height_SpellScript(); + } +}; + +// 92306 - Crystal storm (heroic mode check) +class spell_s92306_crystal_storm : public SpellScriptLoader +{ +public: + spell_s92306_crystal_storm() : SpellScriptLoader("spell_s92306_crystal_storm") { } + + class spell_s92306_crystal_storm_SpellScript : public SpellScript + { + PrepareSpellScript(spell_s92306_crystal_storm_SpellScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_CRYSTAL_STORM_TRIGGER)) + return false; + return true; + } + + void HandleDummyEffect(SpellEffIndex /*eff*/) + { + Unit* caster = GetCaster(); + if (caster->GetMap()->IsHeroic()) + caster->CastSpell(caster, SPELL_CRYSTAL_STORM_TRIGGER, true); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_s92306_crystal_storm_SpellScript::HandleDummyEffect, EFFECT_0, SPELL_EFFECT_APPLY_AURA); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_s92306_crystal_storm_SpellScript(); + } +}; + +// 92300 - Crystal Storm (damage) +class BehindObjectCheck +{ + public: + BehindObjectCheck(Unit* caster, std::list<GameObject*> objectList) : caster(caster), objectList(objectList) { } + + bool operator()(WorldObject* unit) + { + for (std::list<GameObject*>::const_iterator itr = objectList.begin(); itr != objectList.end(); ++itr) + if (!(*itr)->IsInvisibleDueToDespawn() && (*itr)->IsInBetween(caster, unit, 1.5f)) + return true; + return false; + } + + private: + Unit* caster; + std::list<GameObject*> objectList; +}; + +class spell_s92300_crystal_storm : public SpellScriptLoader +{ +public: + spell_s92300_crystal_storm() : SpellScriptLoader("spell_s92300_crystal_storm") { } + + class spell_s92300_crystal_storm_SpellScript : public SpellScript + { + PrepareSpellScript(spell_s92300_crystal_storm_SpellScript); + + void FilterTargets(std::list<WorldObject*>& unitList) + { + Unit* caster = GetCaster(); + + std::list<GameObject*> goList; + caster->GetGameObjectListWithEntryInGrid(goList, GO_STALACTITE, 40.0f); + if (goList.empty()) + return; + + unitList.remove_if(BehindObjectCheck(caster, goList)); + } + + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_s92300_crystal_storm_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_s92300_crystal_storm_SpellScript(); + } +}; + +void AddSC_boss_slabhide() +{ + new boss_slabhide(); + new npc_lava_fissure(); + new npc_stalactite_trigger(); + new spell_s81035_stalactite(); + new spell_s81028_s80650_stalactite(); + new spell_stalactite_mod_dest_height(); + new spell_s92306_crystal_storm(); + new spell_s92300_crystal_storm(); +} diff --git a/src/server/scripts/Maelstrom/Stonecore/instance_stonecore.cpp b/src/server/scripts/Maelstrom/Stonecore/instance_stonecore.cpp new file mode 100644 index 00000000000..ca5e40ab117 --- /dev/null +++ b/src/server/scripts/Maelstrom/Stonecore/instance_stonecore.cpp @@ -0,0 +1,262 @@ +/* +* Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/> +* Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/> +* +* 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 "ScriptMgr.h" +#include "Player.h" +#include "CreatureGroups.h" +#include "InstanceScript.h" +#include "stonecore.h" + +#define MAX_ENCOUNTER 4 + +/* Stonecore encounters: +0 - Corborus +1 - Slabhide +2 - Ozruk +3 - High Priestess Azil +*/ + +// TO-DO: +// - Find out spell IDs for both Stonecore Teleporters (spellclick). + +class instance_stonecore : public InstanceMapScript +{ + public: + instance_stonecore() : InstanceMapScript(SCScriptName, 725) { } + + struct instance_stonecore_InstanceScript : public InstanceScript + { + instance_stonecore_InstanceScript(Map* map) : InstanceScript(map) + { + SetHeaders(DataHeader); + SetBossNumber(MAX_ENCOUNTER); + } + + void OnGameObjectCreate(GameObject* go) override + { + switch (go->GetEntry()) + { + case GAMEOBJECT_CORBORUS_ROCKDOOR: + corborusRockDoorGUID = go->GetGUID(); + go->SetGoState(GetBossState(DATA_CORBORUS) != DONE ? GO_STATE_READY : GO_STATE_ACTIVE); + break; + case GAMEOBJECT_SLABHIDE_ROCK_WALL: + slabhideRockWallGUIDs.push_back(go->GetGUID()); + break; + default: + break; + } + } + + void OnCreatureCreate(Creature* creature) override + { + switch (creature->GetEntry()) + { + case NPC_MILLHOUSE_MANASTORM: + millhouseGUID = creature->GetGUID(); + break; + case NPC_CORBORUS: + corobrusGUID = creature->GetGUID(); + break; + case NPC_SLABHIDE: + slabhideGUID = creature->GetGUID(); + break; + case NPC_HIGH_PRIESTESS_AZIL: + highPriestessAzilGUID = creature->GetGUID(); + break; + case NPC_STONECORE_TELEPORTER: + case NPC_STONECORE_TELEPORTER_2: + if (GetBossState(DATA_SLABHIDE) != DONE) + stonecoreTeleporterGUID[creature->GetEntry() - NPC_STONECORE_TELEPORTER] = creature->GetGUID(); + else // If Slabhide is already dead, no need to store teleporter guids + { + creature->CastSpell(creature, SPELL_TELEPORTER_ACTIVE_VISUAL, true); + creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); + } + break; + default: + break; + } + + // Check if creature is part of Millhouse event + creature->SearchFormation(); + if (CreatureGroup* group = creature->GetFormation()) // TO-DO: Fix formations + { + switch (group->GetId()) + { + case CREATURE_FORMATION_MILLHOUSE_EVENT_TRASH: + millhouseTrashGUIDs.push_back(creature->GetGUID()); + break; + case CREATURE_FORMATION_MILLHOUSE_EVENT_LAST_GROUP: + millhouseLastGroupGUIDs.push_back(creature->GetGUID()); + creature->SetReactState(REACT_PASSIVE); + creature->SetMeleeAnimKitId(ANIM_READY2H); + break; + } + } + } + + bool SetBossState(uint32 type, EncounterState state) override + { + switch (type) + { + case DATA_SLABHIDE: + // Open rock walls (Slabhide AI handles closing because it must be delayed) + if (state != IN_PROGRESS) + SetData(DATA_SLABHIDE_ROCK_WALL, true); + + // Activate teleporters + if (state == DONE) + { + for (int8 i = 0; i < MAX_STONECORE_TELEPORTERS; i++) + { + if (Creature* teleporter = instance->GetCreature(stonecoreTeleporterGUID[i])) + { + teleporter->CastSpell(teleporter, SPELL_TELEPORTER_ACTIVE_VISUAL, true); + teleporter->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); + } + } + } + + break; + default: + break; + } + + return InstanceScript::SetBossState(type, state); + } + + uint32 GetData(uint32 type) const override + { + switch (type) + { + case DATA_SLABHIDE_INTRO: + return slabhideIntro; + default: + break; + } + + return 0; + } + + void SetData(uint32 type, uint32 data) override + { + switch (type) + { + case DATA_MILLHOUSE_EVENT_FACE: + MillhouseEvent_Face(); + break; + case DATA_MILLHOUSE_EVENT_KNOCKBACK: + MillhouseEvent_Knockback(); + break; + case DATA_MILLHOUSE_EVENT_DESPAWN: + MillhouseEvent_Despawn(); + break; + case DATA_SLABHIDE_INTRO: + slabhideIntro = EncounterState(data); + break; + case DATA_SLABHIDE_ROCK_WALL: // Handles rock walls + for (std::vector<ObjectGuid>::iterator itr = slabhideRockWallGUIDs.begin(); itr != slabhideRockWallGUIDs.end(); ++itr) + HandleGameObject((*itr), data ? true : false); + break; + default: + break; + } + } + + ObjectGuid GetGuidData(uint32 type) const override + { + switch (type) + { + case DATA_MILLHOUSE_MANASTORM: + return millhouseGUID; + case GAMEOBJECT_CORBORUS_ROCKDOOR: + return corborusRockDoorGUID; + case DATA_CORBORUS: + return corobrusGUID; + case DATA_SLABHIDE: + return slabhideGUID; + case DATA_HIGH_PRIESTESS_AZIL: + return highPriestessAzilGUID; + case NPC_STONECORE_TELEPORTER: + case NPC_STONECORE_TELEPORTER_2: + return stonecoreTeleporterGUID[type - NPC_STONECORE_TELEPORTER]; + default: + break; + } + + return ObjectGuid::Empty; + } + + private: + // Face Millhouse and other nearby mobs to Corborus + void MillhouseEvent_Face() + { + if (Creature* Millhouse = instance->GetCreature(millhouseGUID)) + Millhouse->SetFacingTo(1.570796f); + for (GuidVector::const_iterator i = millhouseLastGroupGUIDs.begin(); i != millhouseLastGroupGUIDs.end(); ++i) + if (Creature* creature = instance->GetCreature(*i)) + creature->SetFacingTo(1.570796f); + } + + // Knock back Millhouse and other mobs + void MillhouseEvent_Knockback() + { + if (Creature* Millhouse = instance->GetCreature(millhouseGUID)) + Millhouse->CastSpell(Millhouse, SPELL_RING_WYRM_KNOCKBACK, true); + for (GuidVector::const_iterator itr = millhouseLastGroupGUIDs.begin(); itr != millhouseLastGroupGUIDs.end(); ++itr) + if (Creature* creature = instance->GetCreature(*itr)) + creature->CastSpell(creature, SPELL_RING_WYRM_KNOCKBACK, true); + } + + // Despawn all mobs + void MillhouseEvent_Despawn() + { + if (Creature* Millhouse = instance->GetCreature(millhouseGUID)) + Millhouse->DespawnOrUnsummon(3000); + for (GuidVector::const_iterator itr = millhouseTrashGUIDs.begin(); itr != millhouseTrashGUIDs.end(); ++itr) + if (Creature* creature = instance->GetCreature(*itr)) + creature->DespawnOrUnsummon(3000); + for (GuidVector::const_iterator itr = millhouseLastGroupGUIDs.begin(); itr != millhouseLastGroupGUIDs.end(); ++itr) + if (Creature* creature = instance->GetCreature(*itr)) + creature->DespawnOrUnsummon(3000); + } + + ObjectGuid millhouseGUID; + GuidVector millhouseTrashGUIDs; + GuidVector millhouseLastGroupGUIDs; + ObjectGuid corborusRockDoorGUID; + ObjectGuid corobrusGUID; + ObjectGuid slabhideGUID; + ObjectGuid highPriestessAzilGUID; + ObjectGuid stonecoreTeleporterGUID[2]; + GuidVector slabhideRockWallGUIDs; + + EncounterState slabhideIntro; + }; + + InstanceScript* GetInstanceScript(InstanceMap* map) const override + { + return new instance_stonecore_InstanceScript(map); + } +}; + +void AddSC_instance_stonecore() +{ + new instance_stonecore(); +} diff --git a/src/server/scripts/Maelstrom/Stonecore/stonecore.cpp b/src/server/scripts/Maelstrom/Stonecore/stonecore.cpp new file mode 100644 index 00000000000..4ed84732eff --- /dev/null +++ b/src/server/scripts/Maelstrom/Stonecore/stonecore.cpp @@ -0,0 +1,442 @@ +/* + * Copyright (C) 2008-2014 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 "ObjectGuid.h" +#include "ObjectMgr.h" +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "SpellScript.h" +#include "Player.h" +#include "stonecore.h" + +enum Texts +{ + // Millhouse Manastorm + SAY_MILLHOUSE_EVENT_1 = 0, + SAY_MILLHOUSE_EVENT_2 = 1, +}; + +enum NPCs +{ + NPC_GENERIC_TRIGGER_LAB = 40350, +}; + +enum Spells +{ + // Millhouse Manastorm + SPELL_SHADOW_BOLT = 81439, + SPELL_FROSTBOLT_VOLLEY = 81440, + SPELL_SHADOWFURY = 81441, + SPELL_FEAR = 81442, +// SPELL_MILLHOUSE_SAFE_CHECK = 81213, // unknown purpose + SPELL_CLEAR_ALL_DEBUFFS = 34098, + SPELL_BLUR = 81216, + SPELL_ANCHOR_HERE = 45313, + SPELL_TIGULE_AND_FORORS_SPECIAL_BLEND = 81220, + SPELL_IMPENDING_DOOM = 86838, + SPELL_IMPENDING_DOOM_CHANNEL = 86830, + +// SPELL_PORTAL_VISUAL = 79754, +}; + +enum Events +{ + EVENT_NONE, + + // Millhouse Manastorm + EVENT_FROSTBOLT_VOLLEY, + EVENT_SHADOWFURY, + EVENT_FEAR, + + EVENT_READY_FOR_COMBAT, + EVENT_CAST_IMPENDING_DOOM, + EVENT_INTERRUPT_IMPENDING_DOOM, +}; + +enum Phase +{ + PHASE_NONE, + + PHASE_MILLHOUSE_GROUP_1, + PHASE_MILLHOUSE_GROUP_2, + PHASE_MILLHOUSE_GROUP_3, + PHASE_MILLHOUSE_GROUP_4, + + PHASE_MASK_MILLHOUSE_GROUP_1 = (1 << (PHASE_MILLHOUSE_GROUP_1 - 1)), + PHASE_MASK_MILLHOUSE_GROUP_2 = (1 << (PHASE_MILLHOUSE_GROUP_2 - 1)), + PHASE_MASK_MILLHOUSE_GROUP_3 = (1 << (PHASE_MILLHOUSE_GROUP_3 - 1)), + PHASE_MASK_MILLHOUSE_GROUP_4 = (1 << (PHASE_MILLHOUSE_GROUP_4 - 1)), +}; + +enum MovementPoints +{ + POINT_NONE, + + POINT_MILLHOUSE_GROUP_2, + POINT_MILLHOUSE_GROUP_3, + POINT_MILLHOUSE_GROUP_4, +}; + +// Millhouse trash groups +Position const MillhousePointGroup2 = { 977.3045f, 895.2347f, 306.3298f }; +Position const MillhousePointGroup3 = { 1049.823f, 871.4349f, 295.006f }; +Position const MillhousePointGroup4 = { 1149.04f, 884.431f, 284.9406f }; + +// 43391 - Millhouse Manastorm +class npc_sc_millhouse_manastorm : public CreatureScript +{ + public: + npc_sc_millhouse_manastorm() : CreatureScript("npc_sc_millhouse_manastorm") { } + + struct npc_sc_millhouse_manastormAI : public ScriptedAI + { + npc_sc_millhouse_manastormAI(Creature* creature) : ScriptedAI(creature), + _instance(creature->GetInstanceScript()) + { + events.SetPhase(PHASE_MILLHOUSE_GROUP_1); + } + + void ScheduleEvents() + { + events.ScheduleEvent(EVENT_SHADOWFURY, 3000); + events.ScheduleEvent(EVENT_FROSTBOLT_VOLLEY, 5000); + events.ScheduleEvent(EVENT_FEAR, 8000); + } + + void DamageTaken(Unit* /*attacker*/, uint32& damage) override + { + if (damage >= me->GetHealth()) + damage = me->GetHealth() - 1; + + if (!HealthBelowPct(50) || me->HasAura(SPELL_BLUR)) + return; + + switch (events.GetPhaseMask()) + { + case PHASE_MASK_MILLHOUSE_GROUP_1: + events.Reset(); + events.SetPhase(PHASE_MILLHOUSE_GROUP_2); + me->SetReactState(REACT_PASSIVE); + me->InterruptNonMeleeSpells(true); + DoCast(me, SPELL_CLEAR_ALL_DEBUFFS); + DoCast(me, SPELL_BLUR); + Talk(SAY_MILLHOUSE_EVENT_1); + me->GetMotionMaster()->MovePoint(POINT_MILLHOUSE_GROUP_2, MillhousePointGroup2); + break; + case PHASE_MASK_MILLHOUSE_GROUP_2: + events.Reset(); + events.SetPhase(PHASE_MILLHOUSE_GROUP_3); + me->SetReactState(REACT_PASSIVE); + me->InterruptNonMeleeSpells(true); + DoCast(me, SPELL_CLEAR_ALL_DEBUFFS); + DoCast(me, SPELL_BLUR); + Talk(SAY_MILLHOUSE_EVENT_1); + me->GetMotionMaster()->MovePoint(POINT_MILLHOUSE_GROUP_3, MillhousePointGroup3); + break; + case PHASE_MASK_MILLHOUSE_GROUP_3: + events.Reset(); + events.SetPhase(PHASE_MILLHOUSE_GROUP_4); + me->SetReactState(REACT_PASSIVE); + me->InterruptNonMeleeSpells(true); + DoCast(me, SPELL_CLEAR_ALL_DEBUFFS); + DoCast(me, SPELL_BLUR); + me->GetMotionMaster()->MovePoint(POINT_MILLHOUSE_GROUP_4, MillhousePointGroup4); + break; + default: + break; + } + + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT); + } + + void MovementInform(uint32 type, uint32 pointId) override + { + if (type != POINT_MOTION_TYPE) + return; + + if (pointId < POINT_MILLHOUSE_GROUP_2 || pointId > POINT_MILLHOUSE_GROUP_4) + return; + + me->RemoveAllAuras(); + me->CombatStop(true); + me->DeleteThreatList(); + + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT); + me->SetReactState(REACT_AGGRESSIVE); + + switch (pointId) + { + case POINT_MILLHOUSE_GROUP_2: + if (Creature* worldtrigger = me->FindNearestCreature(NPC_WORLDTRIGGER, 150.0f)) + me->SetFacingToObject(worldtrigger); // o: 5.497359f (sniff data) + me->CastSpell(me, SPELL_ANCHOR_HERE, true); + me->AddAura(SPELL_TIGULE_AND_FORORS_SPECIAL_BLEND, me); + events.ScheduleEvent(EVENT_READY_FOR_COMBAT, 10000); + break; + case POINT_MILLHOUSE_GROUP_3: + me->SetFacingTo(5.931499f); + me->CastSpell(me, SPELL_ANCHOR_HERE, true); + me->AddAura(SPELL_TIGULE_AND_FORORS_SPECIAL_BLEND, me); + events.ScheduleEvent(EVENT_READY_FOR_COMBAT, 10000); + break; + case POINT_MILLHOUSE_GROUP_4: + me->SetFacingTo(3.455752f); + me->CastSpell(me, SPELL_ANCHOR_HERE, true); + Talk(SAY_MILLHOUSE_EVENT_2); + events.ScheduleEvent(EVENT_CAST_IMPENDING_DOOM, 1000); + break; + default: + break; + } + } + + void UpdateAI(uint32 diff) override + { + // Only update events if Millhouse is aggressive + if (me->GetReactState() != REACT_AGGRESSIVE) + return; + + events.Update(diff); + + // Impending Doom is exception because it needs to be interrupted. + if (me->HasUnitState(UNIT_STATE_CASTING) && !me->GetCurrentSpell(SPELL_IMPENDING_DOOM)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_FROSTBOLT_VOLLEY: + DoCast(SPELL_FROSTBOLT_VOLLEY); + events.ScheduleEvent(EVENT_FROSTBOLT_VOLLEY, 7000); + break; + case EVENT_SHADOWFURY: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true)) + DoCast(target, SPELL_SHADOWFURY); + events.ScheduleEvent(EVENT_SHADOWFURY, 7000); + break; + case EVENT_FEAR: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true)) + DoCast(target, SPELL_FEAR); + events.ScheduleEvent(EVENT_FEAR, 18000); + break; + case EVENT_READY_FOR_COMBAT: + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT); + me->SetReactState(REACT_AGGRESSIVE); + ScheduleEvents(); + break; + case EVENT_CAST_IMPENDING_DOOM: + DoCast(SPELL_IMPENDING_DOOM); + DoCast(SPELL_IMPENDING_DOOM_CHANNEL); + events.ScheduleEvent(EVENT_INTERRUPT_IMPENDING_DOOM, urand(15000,20000)); + break; + case EVENT_INTERRUPT_IMPENDING_DOOM: + me->InterruptNonMeleeSpells(true); + me->RemoveAllAuras(); + me->HandleEmoteCommand(EMOTE_ONESHOT_KNOCKDOWN); + events.ScheduleEvent(EVENT_CAST_IMPENDING_DOOM, 3000); + break; + default: + break; + } + } + + DoSpellAttackIfReady(SPELL_SHADOW_BOLT); + } + + private: + InstanceScript* _instance; + EventMap events; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetInstanceAI<npc_sc_millhouse_manastormAI>(creature); + } +}; + +// 81459 - Force of Earth +class spell_force_of_earth : public SpellScriptLoader +{ + public: + spell_force_of_earth() : SpellScriptLoader("spell_force_of_earth") { } + + class spell_force_of_earth_SpellScript : public SpellScript + { + PrepareSpellScript(spell_force_of_earth_SpellScript); + + void DummyEffect(SpellEffIndex /*effIndex*/) + { + GetCaster()->SetDisplayId(26693); // can be moved to SAI part, need sniffs to see what this dummy does (note: npc 43552) + } + + void Register() + { + OnEffectLaunch += SpellEffectFn(spell_force_of_earth_SpellScript::DummyEffect, EFFECT_0, SPELL_EFFECT_DUMMY); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_force_of_earth_SpellScript(); + } +}; + +// 45313 - Anchor Here +class spell_sc_anchor_here : public SpellScriptLoader +{ +public: + spell_sc_anchor_here() : SpellScriptLoader("spell_sc_anchor_here") { } + + class spell_sc_anchor_here_SpellScript : public SpellScript + { + PrepareSpellScript(spell_sc_anchor_here_SpellScript); + + void HandleScript(SpellEffIndex /*effIndex*/) + { + if (Creature* creature = GetHitUnit()->ToCreature()) + creature->SetHomePosition(creature->GetPositionX(), creature->GetPositionY(), creature->GetPositionZ(), creature->GetOrientation()); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_sc_anchor_here_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_sc_anchor_here_SpellScript(); + } +}; + +// 93167 - Twilight Documents +class spell_sc_twilight_documents : public SpellScriptLoader +{ + public: + spell_sc_twilight_documents() : SpellScriptLoader("spell_sc_twilight_documents") { } + + class spell_sc_twilight_documents_SpellScript : public SpellScript + { + PrepareSpellScript(spell_sc_twilight_documents_SpellScript); + + bool Validate(SpellInfo const* /*spell*/) override + { + if (!sObjectMgr->GetGameObjectTemplate(GAMEOBJECT_TWILIGHT_DOCUMENTS)) + return false; + return true; + } + + void SetTarget(WorldObject*& target) + { + target = GetCaster()->FindNearestCreature(NPC_GENERIC_TRIGGER_LAB, 100.0f); + } + + void SpawnGameObject(SpellEffIndex /*effIndex*/) + { + if (WorldLocation* loc = GetHitDest()) + GetCaster()->SummonGameObject(GAMEOBJECT_TWILIGHT_DOCUMENTS, loc->GetPositionX(), loc->GetPositionY(), loc->GetPositionZ(), loc->GetOrientation(), 0, 0, 0, 0, 7200); + } + + void Register() override + { + OnObjectTargetSelect += SpellObjectTargetSelectFn(spell_sc_twilight_documents_SpellScript::SetTarget, EFFECT_0, TARGET_DEST_NEARBY_ENTRY); + OnEffectHit += SpellEffectFn(spell_sc_twilight_documents_SpellScript::SpawnGameObject, EFFECT_0, SPELL_EFFECT_DUMMY); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_sc_twilight_documents_SpellScript(); + } +}; + +// 81008 - Quake +class JumpCheck +{ + public: + bool operator()(WorldObject* object) const + { + Player* player = object->ToPlayer(); + return (player && player->HasUnitState(UNIT_STATE_JUMPING)); + } +}; + +class spell_sc_quake : public SpellScriptLoader +{ + public: + spell_sc_quake() : SpellScriptLoader("spell_sc_quake") { } + + class spell_sc_quake_SpellScript : public SpellScript + { + PrepareSpellScript(spell_sc_quake_SpellScript); + + void FilterTargets(std::list<WorldObject*>& unitList) + { + unitList.remove_if(JumpCheck()); + } + + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_sc_quake_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_sc_quake_SpellScript(); + } +}; + +class at_sc_corborus_intro : public AreaTriggerScript +{ +public: + at_sc_corborus_intro() : AreaTriggerScript("at_sc_corborus_intro") { } + + bool OnTrigger(Player* player, AreaTriggerEntry const* /*areaTrigger*/) override + { + if (InstanceScript* instance = player->GetInstanceScript()) + if (Creature* corborus = ObjectAccessor::GetCreature(*player, instance->GetGuidData(DATA_CORBORUS))) + corborus->AI()->DoAction(ACTION_CORBORUS_INTRO); + return true; + } +}; + +class at_sc_slabhide_intro : public AreaTriggerScript +{ +public: + at_sc_slabhide_intro() : AreaTriggerScript("at_sc_slabhide_intro") { } + + bool OnTrigger(Player* player, AreaTriggerEntry const* /*areaTrigger*/) override + { + if (InstanceScript* instance = player->GetInstanceScript()) + if (Creature* slabhide = ObjectAccessor::GetCreature(*player, instance->GetGuidData(DATA_SLABHIDE))) + slabhide->AI()->DoAction(ACTION_SLABHIDE_INTRO); + return true; + } +}; + +void AddSC_stonecore() +{ + new npc_sc_millhouse_manastorm(); + new spell_force_of_earth(); + new spell_sc_anchor_here(); + new spell_sc_twilight_documents(); + new spell_sc_quake(); + new at_sc_corborus_intro(); + new at_sc_slabhide_intro(); +} diff --git a/src/server/scripts/Maelstrom/Stonecore/stonecore.h b/src/server/scripts/Maelstrom/Stonecore/stonecore.h new file mode 100644 index 00000000000..98a9878e0d3 --- /dev/null +++ b/src/server/scripts/Maelstrom/Stonecore/stonecore.h @@ -0,0 +1,72 @@ +/* +* Copyright (C) 2008-2014 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 DEF_STONECORE_H +#define DEF_STONECORE_H + +#define SCScriptName "instance_stonecore" +#define DataHeader "SC" + +enum DataTypes +{ + // Encounter States/Boss GUIDs + DATA_CORBORUS, + DATA_SLABHIDE, + DATA_OZRUK, + DATA_HIGH_PRIESTESS_AZIL, + + // Additional Data + DATA_MILLHOUSE_MANASTORM, + DATA_MILLHOUSE_EVENT_FACE, + DATA_MILLHOUSE_EVENT_KNOCKBACK, + DATA_MILLHOUSE_EVENT_DESPAWN, + + DATA_SLABHIDE_INTRO, + DATA_SLABHIDE_ROCK_WALL, +}; + +enum Misc +{ + ACTION_CORBORUS_INTRO, + ACTION_SLABHIDE_INTRO, + + NPC_WORLDTRIGGER = 22515, + NPC_MILLHOUSE_MANASTORM = 43391, + + NPC_CORBORUS = 43438, + NPC_SLABHIDE = 43214, + NPC_OZRUK = 42188, + NPC_HIGH_PRIESTESS_AZIL = 42333, + + // Stonecore Teleporter misc + MAX_STONECORE_TELEPORTERS = 2, + NPC_STONECORE_TELEPORTER = 51396, // Entrance teleporter + NPC_STONECORE_TELEPORTER_2 = 51397, // Slabhide teleporter + SPELL_TELEPORTER_ACTIVE_VISUAL = 95298, + + GAMEOBJECT_TWILIGHT_DOCUMENTS = 207415, + GAMEOBJECT_CORBORUS_ROCKDOOR = 207343, + GAMEOBJECT_SLABHIDE_ROCK_WALL = 204381, + + SPELL_RING_WYRM_KNOCKBACK = 81235, + + // Creature Formation IDs + CREATURE_FORMATION_MILLHOUSE_EVENT_TRASH = 340418, + CREATURE_FORMATION_MILLHOUSE_EVENT_LAST_GROUP = 340492, +}; + +#endif // DEF_STONECORE diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp index 072dbd81fd8..69dc25892c1 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp @@ -205,10 +205,7 @@ class boss_anubarak_trial : public CreatureScript void KilledUnit(Unit* who) override { if (who->GetTypeId() == TYPEID_PLAYER) - { Talk(SAY_KILL_PLAYER); - instance->SetData(DATA_TRIBUTE_TO_IMMORTALITY_ELIGIBLE, 0); - } } void MoveInLineOfSight(Unit* /*who*/) override @@ -611,9 +608,7 @@ class npc_frost_sphere : public CreatureScript struct npc_frost_sphereAI : public ScriptedAI { - npc_frost_sphereAI(Creature* creature) : ScriptedAI(creature) - { - } + npc_frost_sphereAI(Creature* creature) : ScriptedAI(creature) { } void Reset() override { @@ -766,7 +761,6 @@ class npc_anubarak_spike : public CreatureScript } void MoveInLineOfSight(Unit* pWho) override - { if (!pWho) return; diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_faction_champions.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_faction_champions.cpp index 562e67f4b6a..2b541e4b972 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_faction_champions.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_faction_champions.cpp @@ -647,8 +647,6 @@ struct boss_faction_championsAI : public BossAI if (Creature* temp = ObjectAccessor::GetCreature(*me, instance->GetGuidData(NPC_GARROSH))) temp->AI()->Talk(SAY_KILL_PLAYER); - - instance->SetData(DATA_TRIBUTE_TO_IMMORTALITY_ELIGIBLE, 0); } } diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_lord_jaraxxus.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_lord_jaraxxus.cpp index f26ccd6bf25..7e8653c4a55 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_lord_jaraxxus.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_lord_jaraxxus.cpp @@ -122,10 +122,7 @@ class boss_jaraxxus : public CreatureScript void KilledUnit(Unit* who) override { if (who->GetTypeId() == TYPEID_PLAYER) - { Talk(SAY_KILL_PLAYER); - instance->SetData(DATA_TRIBUTE_TO_IMMORTALITY_ELIGIBLE, 0); - } } void JustDied(Unit* /*killer*/) override diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp index 021cae3e623..f7bee426012 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp @@ -540,12 +540,6 @@ struct boss_jormungarAI : public BossAI me->DespawnOrUnsummon(); } - void KilledUnit(Unit* who) override - { - if (who->GetTypeId() == TYPEID_PLAYER) - instance->SetData(DATA_TRIBUTE_TO_IMMORTALITY_ELIGIBLE, 0); - } - void EnterCombat(Unit* /*who*/) override { _EnterCombat(); @@ -943,14 +937,6 @@ class boss_icehowl : public CreatureScript me->DespawnOrUnsummon(); } - void KilledUnit(Unit* who) override - { - if (who->GetTypeId() == TYPEID_PLAYER) - { - instance->SetData(DATA_TRIBUTE_TO_IMMORTALITY_ELIGIBLE, 0); - } - } - void EnterCombat(Unit* /*who*/) override { _EnterCombat(); diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp index 4c118f44e8e..dec2f44745d 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp @@ -212,10 +212,7 @@ struct boss_twin_baseAI : public BossAI void KilledUnit(Unit* who) override { if (who->GetTypeId() == TYPEID_PLAYER) - { Talk(SAY_KILL_PLAYER); - instance->SetData(DATA_TRIBUTE_TO_IMMORTALITY_ELIGIBLE, 0); - } } void SummonedCreatureDespawn(Creature* summoned) override diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/instance_trial_of_the_crusader.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/instance_trial_of_the_crusader.cpp index e3ad891fdc7..cb7e58cfe16 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/instance_trial_of_the_crusader.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/instance_trial_of_the_crusader.cpp @@ -190,6 +190,13 @@ class instance_trial_of_the_crusader : public InstanceMapScript } } + void OnUnitDeath(Unit* unit) override + { + if (unit->GetTypeId() == TYPEID_PLAYER && IsEncounterInProgress()) + TributeToImmortalityEligible = false; + + } + bool SetBossState(uint32 type, EncounterState state) override { if (!InstanceScript::SetBossState(type, state)) @@ -427,9 +434,6 @@ class instance_trial_of_the_crusader : public InstanceMapScript else if (data == DECREASE) --MistressOfPainCount; break; - case DATA_TRIBUTE_TO_IMMORTALITY_ELIGIBLE: - TributeToImmortalityEligible = false; - break; default: break; } diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.h b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.h index e37148aa508..90b9781954f 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.h +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.h @@ -24,9 +24,8 @@ enum DataTypes TYPE_EVENT_NPC = 102, TYPE_NORTHREND_BEASTS = 103, - DATA_SNOBOLD_COUNT = 301, - DATA_MISTRESS_OF_PAIN_COUNT = 302, - DATA_TRIBUTE_TO_IMMORTALITY_ELIGIBLE = 303, + DATA_SNOBOLD_COUNT = 301, + DATA_MISTRESS_OF_PAIN_COUNT = 302, INCREASE = 501, DECREASE = 502, diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp index 5e8273dce67..cdbbf755390 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp @@ -83,6 +83,7 @@ class instance_ulduar : public InstanceMapScript IsDriveMeCrazyEligible = true; _algalonSummoned = false; _summonAlgalon = false; + _CoUAchivePlayerDeathMask = 0; memset(_summonObservationRingKeeper, 0, sizeof(_summonObservationRingKeeper)); memset(_summonYSKeeper, 0, sizeof(_summonYSKeeper)); @@ -592,6 +593,19 @@ class instance_ulduar : public InstanceMapScript void OnUnitDeath(Unit* unit) override { + // Champion/Conqueror of Ulduar + if (unit->GetTypeId() == TYPEID_PLAYER) + { + for (uint8 i = 0; i < BOSS_ALGALON; i++) + { + if (GetBossState(i) == IN_PROGRESS) + { + _CoUAchivePlayerDeathMask |= (1 << i); + SaveToDB(); + } + } + } + Creature* creature = unit->ToCreature(); if (!creature) return; @@ -1007,6 +1021,45 @@ class instance_ulduar : public InstanceMapScript case CRITERIA_ALONE_IN_THE_DARKNESS_10: case CRITERIA_ALONE_IN_THE_DARKNESS_25: return keepersCount == 0; + case CRITERIA_C_O_U_LEVIATHAN_10: + case CRITERIA_C_O_U_LEVIATHAN_25: + return (_CoUAchivePlayerDeathMask & (1 << BOSS_LEVIATHAN)) == 0; + case CRITERIA_C_O_U_IGNIS_10: + case CRITERIA_C_O_U_IGNIS_25: + return (_CoUAchivePlayerDeathMask & (1 << BOSS_IGNIS)) == 0; + case CRITERIA_C_O_U_RAZORSCALE_10: + case CRITERIA_C_O_U_RAZORSCALE_25: + return (_CoUAchivePlayerDeathMask & (1 << BOSS_RAZORSCALE)) == 0; + case CRITERIA_C_O_U_XT002_10: + case CRITERIA_C_O_U_XT002_25: + return (_CoUAchivePlayerDeathMask & (1 << BOSS_XT002)) == 0; + case CRITERIA_C_O_U_IRON_COUNCIL_10: + case CRITERIA_C_O_U_IRON_COUNCIL_25: + return (_CoUAchivePlayerDeathMask & (1 << BOSS_ASSEMBLY_OF_IRON)) == 0; + case CRITERIA_C_O_U_KOLOGARN_10: + case CRITERIA_C_O_U_KOLOGARN_25: + return (_CoUAchivePlayerDeathMask & (1 << BOSS_KOLOGARN)) == 0; + case CRITERIA_C_O_U_AURIAYA_10: + case CRITERIA_C_O_U_AURIAYA_25: + return (_CoUAchivePlayerDeathMask & (1 << BOSS_AURIAYA)) == 0; + case CRITERIA_C_O_U_HODIR_10: + case CRITERIA_C_O_U_HODIR_25: + return (_CoUAchivePlayerDeathMask & (1 << BOSS_HODIR)) == 0; + case CRITERIA_C_O_U_THORIM_10: + case CRITERIA_C_O_U_THORIM_25: + return (_CoUAchivePlayerDeathMask & (1 << BOSS_THORIM)) == 0; + case CRITERIA_C_O_U_FREYA_10: + case CRITERIA_C_O_U_FREYA_25: + return (_CoUAchivePlayerDeathMask & (1 << BOSS_FREYA)) == 0; + case CRITERIA_C_O_U_MIMIRON_10: + case CRITERIA_C_O_U_MIMIRON_25: + return (_CoUAchivePlayerDeathMask & (1 << BOSS_MIMIRON)) == 0; + case CRITERIA_C_O_U_VEZAX_10: + case CRITERIA_C_O_U_VEZAX_25: + return (_CoUAchivePlayerDeathMask & (1 << BOSS_VEZAX)) == 0; + case CRITERIA_C_O_U_YOGG_SARON_10: + case CRITERIA_C_O_U_YOGG_SARON_25: + return (_CoUAchivePlayerDeathMask & (1 << BOSS_YOGG_SARON)) == 0; } return false; @@ -1018,6 +1071,8 @@ class instance_ulduar : public InstanceMapScript for (uint8 i = 0; i < 4; ++i) data << ' ' << uint32(!KeeperGUIDs[i].IsEmpty() ? 1 : 0); + + data << ' ' << _CoUAchivePlayerDeathMask; } void ReadSaveDataMore(std::istringstream& data) override @@ -1056,6 +1111,8 @@ class instance_ulduar : public InstanceMapScript _summonObservationRingKeeper[2] = true; if (GetBossState(BOSS_MIMIRON) == DONE && !_summonYSKeeper[3]) _summonObservationRingKeeper[3] = true; + + data >> _CoUAchivePlayerDeathMask; } void Update(uint32 diff) override @@ -1095,6 +1152,7 @@ class instance_ulduar : public InstanceMapScript bool _summonYSKeeper[4]; uint32 _maxArmorItemLevel; uint32 _maxWeaponItemLevel; + uint32 _CoUAchivePlayerDeathMask; }; InstanceScript* GetInstanceScript(InstanceMap* map) const override diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h b/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h index 82c4ef140f1..1b4330b0faf 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h @@ -36,16 +36,16 @@ enum UlduarBosses BOSS_ASSEMBLY_OF_IRON = 4, BOSS_KOLOGARN = 5, BOSS_AURIAYA = 6, - BOSS_MIMIRON = 7, - BOSS_HODIR = 8, - BOSS_THORIM = 9, - BOSS_FREYA = 10, - BOSS_BRIGHTLEAF = 11, - BOSS_IRONBRANCH = 12, - BOSS_STONEBARK = 13, - BOSS_VEZAX = 14, - BOSS_YOGG_SARON = 15, - BOSS_ALGALON = 16, + BOSS_HODIR = 7, + BOSS_THORIM = 8, + BOSS_FREYA = 9, + BOSS_MIMIRON = 10, + BOSS_VEZAX = 11, + BOSS_YOGG_SARON = 12, + BOSS_ALGALON = 13, + BOSS_BRIGHTLEAF = 14, + BOSS_IRONBRANCH = 15, + BOSS_STONEBARK = 16, }; enum UlduarNPCs @@ -295,6 +295,35 @@ enum UlduarAchievementCriteriaIds CRITERIA_ALONE_IN_THE_DARKNESS_10 = 10412, CRITERIA_ALONE_IN_THE_DARKNESS_25 = 10417, CRITERIA_HERALD_OF_TITANS = 10678, + + // Champion of Ulduar + CRITERIA_C_O_U_LEVIATHAN_10 = 10042, + CRITERIA_C_O_U_IGNIS_10 = 10342, + CRITERIA_C_O_U_RAZORSCALE_10 = 10340, + CRITERIA_C_O_U_XT002_10 = 10341, + CRITERIA_C_O_U_IRON_COUNCIL_10 = 10598, + CRITERIA_C_O_U_KOLOGARN_10 = 10348, + CRITERIA_C_O_U_AURIAYA_10 = 10351, + CRITERIA_C_O_U_HODIR_10 = 10439, + CRITERIA_C_O_U_THORIM_10 = 10403, + CRITERIA_C_O_U_FREYA_10 = 10582, + CRITERIA_C_O_U_MIMIRON_10 = 10347, + CRITERIA_C_O_U_VEZAX_10 = 10349, + CRITERIA_C_O_U_YOGG_SARON_10 = 10350, + // Conqueror of Ulduar + CRITERIA_C_O_U_LEVIATHAN_25 = 10352, + CRITERIA_C_O_U_IGNIS_25 = 10355, + CRITERIA_C_O_U_RAZORSCALE_25 = 10353, + CRITERIA_C_O_U_XT002_25 = 10354, + CRITERIA_C_O_U_IRON_COUNCIL_25 = 10599, + CRITERIA_C_O_U_KOLOGARN_25 = 10357, + CRITERIA_C_O_U_AURIAYA_25 = 10363, + CRITERIA_C_O_U_HODIR_25 = 10719, + CRITERIA_C_O_U_THORIM_25 = 10404, + CRITERIA_C_O_U_FREYA_25 = 10583, + CRITERIA_C_O_U_MIMIRON_25 = 10361, + CRITERIA_C_O_U_VEZAX_25 = 10362, + CRITERIA_C_O_U_YOGG_SARON_25 = 10364 }; enum UlduarData diff --git a/src/server/shared/CMakeLists.txt b/src/server/shared/CMakeLists.txt index 7a02e415d69..1ad85acb601 100644 --- a/src/server/shared/CMakeLists.txt +++ b/src/server/shared/CMakeLists.txt @@ -20,6 +20,7 @@ file(GLOB_RECURSE sources_Dynamic Dynamic/*.cpp Dynamic/*.h) file(GLOB_RECURSE sources_Logging Logging/*.cpp Logging/*.h) file(GLOB_RECURSE sources_Networking Networking/*.cpp Networking/*.h) file(GLOB_RECURSE sources_Packets Packets/*.cpp Packets/*.h) +file(GLOB_RECURSE sources_Realm Realm/*.cpp Realm/*.h) file(GLOB_RECURSE sources_Threading Threading/*.cpp Threading/*.h) file(GLOB_RECURSE sources_Utilities Utilities/*.cpp Utilities/*.h) @@ -50,6 +51,7 @@ set(shared_STAT_SRCS ${sources_Logging} ${sources_Networking} ${sources_Packets} + ${sources_Realm} ${sources_Threading} ${sources_Utilities} ${sources_localdir} @@ -72,6 +74,7 @@ include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/Logging ${CMAKE_CURRENT_SOURCE_DIR}/Networking ${CMAKE_CURRENT_SOURCE_DIR}/Packets + ${CMAKE_CURRENT_SOURCE_DIR}/Realm ${CMAKE_CURRENT_SOURCE_DIR}/Threading ${CMAKE_CURRENT_SOURCE_DIR}/Utilities ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Object diff --git a/src/server/shared/Cryptography/Authentication/WorldPacketCrypt.cpp b/src/server/shared/Cryptography/Authentication/WorldPacketCrypt.cpp index 69198c18df0..b84de24741c 100644 --- a/src/server/shared/Cryptography/Authentication/WorldPacketCrypt.cpp +++ b/src/server/shared/Cryptography/Authentication/WorldPacketCrypt.cpp @@ -29,12 +29,17 @@ WorldPacketCrypt::WorldPacketCrypt() : PacketCrypt(SHA_DIGEST_LENGTH) void WorldPacketCrypt::Init(BigNumber* K) { uint8 ServerEncryptionKey[SEED_KEY_SIZE] = { 0x08, 0xF1, 0x95, 0x9F, 0x47, 0xE5, 0xD2, 0xDB, 0xA1, 0x3D, 0x77, 0x8F, 0x3F, 0x3E, 0xE7, 0x00 }; - HmacSha1 serverEncryptHmac(SEED_KEY_SIZE, (uint8*)ServerEncryptionKey); - uint8 *encryptHash = serverEncryptHmac.ComputeHash(K); - uint8 ServerDecryptionKey[SEED_KEY_SIZE] = { 0x40, 0xAA, 0xD3, 0x92, 0x26, 0x71, 0x43, 0x47, 0x3A, 0x31, 0x08, 0xA6, 0xE7, 0xDC, 0x98, 0x2A }; - HmacSha1 clientDecryptHmac(SEED_KEY_SIZE, (uint8*)ServerDecryptionKey); - uint8 *decryptHash = clientDecryptHmac.ComputeHash(K); + Init(K, ServerEncryptionKey, ServerDecryptionKey); +} + +void WorldPacketCrypt::Init(BigNumber* k, uint8 const* serverKey, uint8 const* clientKey) +{ + HmacSha1 serverEncryptHmac(SEED_KEY_SIZE, (uint8*)serverKey); + uint8 *encryptHash = serverEncryptHmac.ComputeHash(k); + + HmacSha1 clientDecryptHmac(SEED_KEY_SIZE, (uint8*)clientKey); + uint8 *decryptHash = clientDecryptHmac.ComputeHash(k); _clientDecrypt.Init(decryptHash); _serverEncrypt.Init(encryptHash); diff --git a/src/server/shared/Cryptography/Authentication/WorldPacketCrypt.h b/src/server/shared/Cryptography/Authentication/WorldPacketCrypt.h index 7ccca11f09d..58c4003418e 100644 --- a/src/server/shared/Cryptography/Authentication/WorldPacketCrypt.h +++ b/src/server/shared/Cryptography/Authentication/WorldPacketCrypt.h @@ -29,6 +29,7 @@ class WorldPacketCrypt : public PacketCrypt WorldPacketCrypt(); void Init(BigNumber* K) override; + void Init(BigNumber* k, uint8 const* serverKey, uint8 const* clientKey); }; #endif // _WORLDPACKETCRYPT_H diff --git a/src/server/shared/Cryptography/BigNumber.cpp b/src/server/shared/Cryptography/BigNumber.cpp index b68c91001ae..eae92a58ee3 100644 --- a/src/server/shared/Cryptography/BigNumber.cpp +++ b/src/server/shared/Cryptography/BigNumber.cpp @@ -164,11 +164,16 @@ uint32 BigNumber::AsDword() return (uint32)BN_get_word(_bn); } -bool BigNumber::isZero() const +bool BigNumber::IsZero() const { return BN_is_zero(_bn); } +bool BigNumber::IsNegative() const +{ + return BN_is_negative(_bn); +} + std::unique_ptr<uint8[]> BigNumber::AsByteArray(int32 minSize, bool littleEndian) { int length = (minSize >= GetNumBytes()) ? minSize : GetNumBytes(); diff --git a/src/server/shared/Cryptography/BigNumber.h b/src/server/shared/Cryptography/BigNumber.h index df19ba60b71..aebe16021d6 100644 --- a/src/server/shared/Cryptography/BigNumber.h +++ b/src/server/shared/Cryptography/BigNumber.h @@ -77,7 +77,8 @@ class BigNumber return t %= bn; } - bool isZero() const; + bool IsZero() const; + bool IsNegative() const; BigNumber ModExp(BigNumber const& bn1, BigNumber const& bn2); BigNumber Exp(BigNumber const&); diff --git a/src/server/shared/Cryptography/HmacHash.cpp b/src/server/shared/Cryptography/HmacHash.cpp index 2913b9fa79a..a870fab4aa9 100644 --- a/src/server/shared/Cryptography/HmacHash.cpp +++ b/src/server/shared/Cryptography/HmacHash.cpp @@ -21,7 +21,7 @@ #include "Common.h" template<HashCreateFn HashCreator, uint32 DigestLength> -HmacHash<HashCreator, DigestLength>::HmacHash(uint32 len, uint8 *seed) +HmacHash<HashCreator, DigestLength>::HmacHash(uint32 len, uint8 const* seed) { HMAC_CTX_init(&_ctx); HMAC_Init_ex(&_ctx, seed, len, HashCreator(), NULL); diff --git a/src/server/shared/Cryptography/HmacHash.h b/src/server/shared/Cryptography/HmacHash.h index 56ee55edda2..c8a63fe742f 100644 --- a/src/server/shared/Cryptography/HmacHash.h +++ b/src/server/shared/Cryptography/HmacHash.h @@ -34,7 +34,7 @@ template<HashCreateFn HashCreator, uint32 DigestLength> class HmacHash { public: - HmacHash(uint32 len, uint8 *seed); + HmacHash(uint32 len, uint8 const* seed); ~HmacHash(); void UpdateData(std::string const& str); void UpdateData(uint8 const* data, size_t len); diff --git a/src/server/shared/Database/Field.cpp b/src/server/shared/Database/Field.cpp index f1741f98cc3..da547d3a151 100644 --- a/src/server/shared/Database/Field.cpp +++ b/src/server/shared/Database/Field.cpp @@ -46,7 +46,7 @@ void Field::SetByteValue(const void* newValue, const size_t newSize, enum_field_ data.raw = true; } -void Field::SetStructuredValue(char* newValue, enum_field_types newType, uint32 length, bool isBinary) +void Field::SetStructuredValue(char* newValue, enum_field_types newType, uint32 length) { if (data.value) CleanUp(); @@ -54,15 +54,9 @@ void Field::SetStructuredValue(char* newValue, enum_field_types newType, uint32 // This value stores somewhat structured data that needs function style casting if (newValue) { - if (!isBinary) - { - data.value = new char[length + 1]; - *(reinterpret_cast<char*>(data.value) + length) = '\0'; - } - else - data.value = new char[length]; - + data.value = new char[length + 1]; memcpy(data.value, newValue, length); + *(reinterpret_cast<char*>(data.value) + length) = '\0'; data.length = length; } diff --git a/src/server/shared/Database/Field.h b/src/server/shared/Database/Field.h index 99f98572a56..352db10c539 100644 --- a/src/server/shared/Database/Field.h +++ b/src/server/shared/Database/Field.h @@ -239,9 +239,11 @@ class Field { char const* string = GetCString(); if (!string) - string = ""; + return ""; + return std::string(string, data.length); } + return std::string((char*)data.value, data.length); } @@ -284,7 +286,7 @@ class Field #endif void SetByteValue(void const* newValue, size_t const newSize, enum_field_types newType, uint32 length); - void SetStructuredValue(char* newValue, enum_field_types newType, uint32 length, bool isBinary); + void SetStructuredValue(char* newValue, enum_field_types newType, uint32 length); void CleanUp() { diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.cpp b/src/server/shared/Database/Implementation/CharacterDatabase.cpp index 796b5d27a1e..51b5bf1d30b 100644 --- a/src/server/shared/Database/Implementation/CharacterDatabase.cpp +++ b/src/server/shared/Database/Implementation/CharacterDatabase.cpp @@ -567,7 +567,7 @@ void CharacterDatabaseConnection::DoPrepareStatements() PrepareStatement(CHAR_DEL_CHAR_TALENT_BY_SPELL_SPEC, "DELETE FROM character_talent WHERE guid = ? and spell = ? and spec = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_INS_CHAR_TALENT, "INSERT INTO character_talent (guid, spell, spec) VALUES (?, ?, ?)", CONNECTION_ASYNC); PrepareStatement(CHAR_DEL_CHAR_ACTION_EXCEPT_SPEC, "DELETE FROM character_action WHERE spec<>? AND guid = ?", CONNECTION_ASYNC); - PrepareStatement(CHAR_UPD_CHAR_LIST_SLOT, "UPDATE characters SET slot = ? WHERE guid = ?", CONNECTION_ASYNC); + PrepareStatement(CHAR_UPD_CHAR_LIST_SLOT, "UPDATE characters SET slot = ? WHERE guid = ? AND account = ?", CONNECTION_ASYNC); // Void Storage PrepareStatement(CHAR_SEL_CHAR_VOID_STORAGE, "SELECT itemId, itemEntry, slot, creatorGuid, randomProperty, suffixFactor FROM character_void_storage WHERE playerGuid = ?", CONNECTION_ASYNC); diff --git a/src/server/shared/Database/Implementation/LoginDatabase.cpp b/src/server/shared/Database/Implementation/LoginDatabase.cpp index c0c9751a804..4d0d4df2003 100644 --- a/src/server/shared/Database/Implementation/LoginDatabase.cpp +++ b/src/server/shared/Database/Implementation/LoginDatabase.cpp @@ -35,6 +35,7 @@ void LoginDatabaseConnection::DoPrepareStatements() PrepareStatement(LOGIN_INS_ACCOUNT_AUTO_BANNED, "INSERT INTO account_banned VALUES (?, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()+?, 'Trinity Auth', 'Failed login autoban', 1)", CONNECTION_ASYNC); PrepareStatement(LOGIN_DEL_ACCOUNT_BANNED, "DELETE FROM account_banned WHERE id = ?", CONNECTION_ASYNC); PrepareStatement(LOGIN_SEL_SESSIONKEY, "SELECT a.sessionkey, a.id, aa.gmlevel FROM account a LEFT JOIN account_access aa ON (a.id = aa.id) WHERE username = ?", CONNECTION_SYNCH); + PrepareStatement(LOGIN_SEL_ACCOUNT_INFO_CONTINUED_SESSION, "SELECT username, sessionkey FROM account WHERE id = ?", CONNECTION_SYNCH); PrepareStatement(LOGIN_UPD_VS, "UPDATE account SET v = ?, s = ? WHERE username = ?", CONNECTION_ASYNC); PrepareStatement(LOGIN_UPD_LOGONPROOF, "UPDATE account SET sessionkey = ?, last_ip = ?, last_login = NOW(), locale = ?, failed_logins = 0, os = ? WHERE username = ?", CONNECTION_SYNCH); PrepareStatement(LOGIN_SEL_LOGONCHALLENGE, "SELECT a.sha_pass_hash, a.id, a.locked, a.lock_country, a.last_ip, aa.gmlevel, a.v, a.s, a.token_key, a.battlenet_account FROM account a LEFT JOIN account_access aa ON (a.id = aa.id) WHERE a.username = ?", CONNECTION_SYNCH); @@ -56,7 +57,7 @@ void LoginDatabaseConnection::DoPrepareStatements() PrepareStatement(LOGIN_DEL_REALM_CHARACTERS, "DELETE FROM realmcharacters WHERE acctid = ?", CONNECTION_ASYNC); PrepareStatement(LOGIN_INS_REALM_CHARACTERS, "INSERT INTO realmcharacters (numchars, acctid, realmid) VALUES (?, ?, ?)", CONNECTION_ASYNC); PrepareStatement(LOGIN_SEL_SUM_REALM_CHARACTERS, "SELECT SUM(numchars) FROM realmcharacters WHERE acctid = ?", CONNECTION_ASYNC); - PrepareStatement(LOGIN_INS_ACCOUNT, "INSERT INTO account(username, sha_pass_hash, reg_mail, email, joindate) VALUES(?, ?, ?, ?, NOW())", CONNECTION_SYNCH); + PrepareStatement(LOGIN_INS_ACCOUNT, "INSERT INTO account(username, sha_pass_hash, reg_mail, email, joindate, battlenet_account, battlenet_index) VALUES(?, ?, ?, ?, NOW(), ?, ?)", CONNECTION_SYNCH); PrepareStatement(LOGIN_INS_REALM_CHARACTERS_INIT, "INSERT INTO realmcharacters (realmid, acctid, numchars) SELECT realmlist.id, account.id, 0 FROM realmlist, account LEFT JOIN realmcharacters ON acctid=account.id WHERE acctid IS NULL", CONNECTION_ASYNC); PrepareStatement(LOGIN_UPD_EXPANSION, "UPDATE account SET expansion = ? WHERE id = ?", CONNECTION_ASYNC); PrepareStatement(LOGIN_UPD_ACCOUNT_LOCK, "UPDATE account SET locked = ? WHERE id = ?", CONNECTION_ASYNC); @@ -128,7 +129,7 @@ void LoginDatabaseConnection::DoPrepareStatements() PrepareStatement(LOGIN_UPD_BNET_FAILED_LOGINS, "UPDATE battlenet_accounts SET failed_logins = failed_logins + 1 WHERE email = ?", CONNECTION_ASYNC); PrepareStatement(LOGIN_UPD_BNET_LAST_LOGIN_INFO, "UPDATE battlenet_accounts SET last_ip = ?, last_login = NOW(), locale = ?, failed_logins = 0, os = ? WHERE id = ?", CONNECTION_ASYNC); PrepareStatement(LOGIN_SEL_BNET_CHARACTER_COUNTS, "SELECT rc.numchars, r.id, r.Region, r.Battlegroup, r.gamebuild FROM realmcharacters rc INNER JOIN realmlist r ON rc.realmid = r.id WHERE rc.acctid = ?", CONNECTION_SYNCH); - PrepareStatement(LOGIN_INS_BNET_ACCOUNT, "INSERT INTO battlenet_accounts (`email`,`sha_pass_hash`) VALUES (?, ?)", CONNECTION_ASYNC); + PrepareStatement(LOGIN_INS_BNET_ACCOUNT, "INSERT INTO battlenet_accounts (`email`,`sha_pass_hash`) VALUES (?, ?)", CONNECTION_SYNCH); PrepareStatement(LOGIN_SEL_BNET_ACCOUNT_EMAIL_BY_ID, "SELECT email FROM battlenet_accounts WHERE id = ?", CONNECTION_SYNCH); PrepareStatement(LOGIN_SEL_BNET_ACCOUNT_ID_BY_EMAIL, "SELECT id FROM battlenet_accounts WHERE email = ?", CONNECTION_SYNCH); PrepareStatement(LOGIN_UPD_BNET_PASSWORD, "UPDATE battlenet_accounts SET v = '', s = '', sha_pass_hash = ? WHERE id = ?", CONNECTION_ASYNC); @@ -136,6 +137,8 @@ void LoginDatabaseConnection::DoPrepareStatements() PrepareStatement(LOGIN_UPD_BNET_ACCOUNT_LOCK, "UPDATE battlenet_accounts SET locked = ? WHERE id = ?", CONNECTION_ASYNC); PrepareStatement(LOGIN_UPD_BNET_ACCOUNT_LOCK_CONTRY, "UPDATE battlenet_accounts SET lock_country = ? WHERE id = ?", CONNECTION_ASYNC); PrepareStatement(LOGIN_SEL_BNET_ACCOUNT_ID_BY_GAME_ACCOUNT, "SELECT battlenet_account FROM account WHERE id = ?", CONNECTION_SYNCH); + PrepareStatement(LOGIN_UPD_BNET_GAME_ACCOUNT_LINK, "UPDATE account SET battlenet_account = ?, battlenet_index = ? WHERE id = ?", CONNECTION_ASYNC); + PrepareStatement(LOGIN_SEL_BNET_MAX_ACCOUNT_INDEX, "SELECT MAX(battlenet_index) FROM account WHERE battlenet_account = ?", CONNECTION_SYNCH); PrepareStatement(LOGIN_SEL_LAST_CHAR_UNDELETE, "SELECT LastCharacterUndelete FROM battlenet_accounts WHERE Id = ?", CONNECTION_ASYNC); PrepareStatement(LOGIN_UPD_LAST_CHAR_UNDELETE, "UPDATE battlenet_accounts SET LastCharacterUndelete = UNIX_TIMESTAMP() WHERE Id = ?", CONNECTION_ASYNC); diff --git a/src/server/shared/Database/Implementation/LoginDatabase.h b/src/server/shared/Database/Implementation/LoginDatabase.h index bf4b8511e67..3667b65e885 100644 --- a/src/server/shared/Database/Implementation/LoginDatabase.h +++ b/src/server/shared/Database/Implementation/LoginDatabase.h @@ -53,6 +53,7 @@ enum LoginDatabaseStatements LOGIN_INS_ACCOUNT_AUTO_BANNED, LOGIN_DEL_ACCOUNT_BANNED, LOGIN_SEL_SESSIONKEY, + LOGIN_SEL_ACCOUNT_INFO_CONTINUED_SESSION, LOGIN_UPD_VS, LOGIN_UPD_LOGONPROOF, LOGIN_SEL_LOGONCHALLENGE, @@ -152,6 +153,8 @@ enum LoginDatabaseStatements LOGIN_UPD_BNET_ACCOUNT_LOCK, LOGIN_UPD_BNET_ACCOUNT_LOCK_CONTRY, LOGIN_SEL_BNET_ACCOUNT_ID_BY_GAME_ACCOUNT, + LOGIN_UPD_BNET_GAME_ACCOUNT_LINK, + LOGIN_SEL_BNET_MAX_ACCOUNT_INDEX, LOGIN_SEL_LAST_CHAR_UNDELETE, LOGIN_UPD_LAST_CHAR_UNDELETE, diff --git a/src/server/shared/Database/PreparedStatement.cpp b/src/server/shared/Database/PreparedStatement.cpp index 1f036b5bf0a..3ea3c969a4c 100644 --- a/src/server/shared/Database/PreparedStatement.cpp +++ b/src/server/shared/Database/PreparedStatement.cpp @@ -72,6 +72,7 @@ void PreparedStatement::BindParameters() break; case TYPE_BINARY: m_stmt->setBinary(i, statement_data[i].binary, false); + break; case TYPE_NULL: m_stmt->setNull(i); break; @@ -357,7 +358,7 @@ void MySQLPreparedStatement::setBinary(const uint8 index, const std::vector<uint m_paramsSet[index] = true; MYSQL_BIND* param = &m_bind[index]; size_t len = value.size(); - param->buffer_type = MYSQL_TYPE_VAR_STRING; + param->buffer_type = MYSQL_TYPE_BLOB; delete [] static_cast<char *>(param->buffer); param->buffer = new char[len]; param->buffer_length = len; @@ -365,7 +366,10 @@ void MySQLPreparedStatement::setBinary(const uint8 index, const std::vector<uint delete param->length; param->length = new unsigned long(len); if (isString) + { *param->length -= 1; + param->buffer_type = MYSQL_TYPE_VAR_STRING; + } memcpy(param->buffer, value.data(), len); } diff --git a/src/server/shared/Database/QueryResult.cpp b/src/server/shared/Database/QueryResult.cpp index a6d9c64622a..154cf5cda41 100644 --- a/src/server/shared/Database/QueryResult.cpp +++ b/src/server/shared/Database/QueryResult.cpp @@ -172,7 +172,7 @@ bool ResultSet::NextRow() } for (uint32 i = 0; i < _fieldCount; i++) - _currentRow[i].SetStructuredValue(row[i], _fields[i].type, lengths[i], (_fields[i].flags & BINARY_FLAG) != 0); + _currentRow[i].SetStructuredValue(row[i], _fields[i].type, lengths[i]); return true; } diff --git a/src/server/shared/Networking/SocketMgr.h b/src/server/shared/Networking/SocketMgr.h index dbe2b8ec902..92c16d96882 100644 --- a/src/server/shared/Networking/SocketMgr.h +++ b/src/server/shared/Networking/SocketMgr.h @@ -33,6 +33,7 @@ class SocketMgr public: virtual ~SocketMgr() { + delete _acceptor; delete[] _threads; } diff --git a/src/server/shared/Realm/Realm.cpp b/src/server/shared/Realm/Realm.cpp new file mode 100644 index 00000000000..79b10843773 --- /dev/null +++ b/src/server/shared/Realm/Realm.cpp @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2008-2014 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 "Realm.h" + +ip::tcp::endpoint Realm::GetAddressForClient(ip::address const& clientAddr) const +{ + ip::address realmIp; + + // Attempt to send best address for client + if (clientAddr.is_loopback()) + { + // Try guessing if realm is also connected locally + if (LocalAddress.is_loopback() || ExternalAddress.is_loopback()) + realmIp = clientAddr; + else + { + // Assume that user connecting from the machine that bnetserver is located on + // has all realms available in his local network + realmIp = LocalAddress; + } + } + else + { + if (clientAddr.is_v4() && + (clientAddr.to_v4().to_ulong() & LocalSubnetMask.to_v4().to_ulong()) == + (LocalAddress.to_v4().to_ulong() & LocalSubnetMask.to_v4().to_ulong())) + { + realmIp = LocalAddress; + } + else + realmIp = ExternalAddress; + } + + ip::tcp::endpoint endpoint(realmIp, Port); + + // Return external IP + return endpoint; +} diff --git a/src/server/shared/Realm/Realm.h b/src/server/shared/Realm/Realm.h new file mode 100644 index 00000000000..9476f137947 --- /dev/null +++ b/src/server/shared/Realm/Realm.h @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2008-2014 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 Realm_h__ +#define Realm_h__ + +#include "Common.h" +#include <boost/asio/ip/address.hpp> +#include <boost/asio/ip/tcp.hpp> + +using namespace boost::asio; + +enum RealmFlags +{ + REALM_FLAG_NONE = 0x00, + REALM_FLAG_INVALID = 0x01, + REALM_FLAG_OFFLINE = 0x02, + REALM_FLAG_SPECIFYBUILD = 0x04, + REALM_FLAG_UNK1 = 0x08, + REALM_FLAG_UNK2 = 0x10, + REALM_FLAG_RECOMMENDED = 0x20, + REALM_FLAG_NEW = 0x40, + REALM_FLAG_FULL = 0x80 +}; + +#pragma pack(push, 1) + +namespace Battlenet +{ + struct RealmHandle; + + struct RealmId + { + RealmId() : Region(0), Battlegroup(0), Index(0), Build(0) { } + RealmId(uint8 region, uint8 battlegroup, uint32 index, uint32 build) + : Region(region), Battlegroup(battlegroup), Index(index), Build(build) { } + + uint8 Region; + uint8 Battlegroup; + uint32 Index; + uint32 Build; + + bool operator<(RealmId const& r) const + { + return memcmp(this, &r, sizeof(RealmId) - sizeof(Build)) < 0; + } + }; +} + +#pragma pack(pop) + +// Storage object for a realm +struct Realm +{ + Battlenet::RealmId Id; + ip::address ExternalAddress; + ip::address LocalAddress; + ip::address LocalSubnetMask; + uint16 Port; + std::string Name; + uint8 Type; + RealmFlags Flags; + uint8 Timezone; + AccountTypes AllowedSecurityLevel; + float PopulationLevel; + bool Updated; + bool Keep; + + ip::tcp::endpoint GetAddressForClient(ip::address const& clientAddr) const; +}; + +#endif // Realm_h__ diff --git a/src/server/worldserver/Main.cpp b/src/server/worldserver/Main.cpp index c5127b8f3e2..821e1f5bd83 100644 --- a/src/server/worldserver/Main.cpp +++ b/src/server/worldserver/Main.cpp @@ -30,7 +30,6 @@ #include "OpenSSLCrypto.h" #include "ProcessPriority.h" #include "BigNumber.h" -#include "RealmList.h" #include "World.h" #include "MapManager.h" #include "InstanceSaveMgr.h" @@ -44,6 +43,7 @@ #include "WorldSocket.h" #include "WorldSocketMgr.h" #include "BattlenetServerManager.h" +#include "Realm/Realm.h" #include <openssl/opensslv.h> #include <openssl/crypto.h> #include <boost/asio/io_service.hpp> @@ -82,6 +82,7 @@ WorldDatabaseWorkerPool WorldDatabase; ///< Accessor to the CharacterDatabaseWorkerPool CharacterDatabase; ///< Accessor to the character database LoginDatabaseWorkerPool LoginDatabase; ///< Accessor to the realm/login database Battlenet::RealmHandle realmHandle; ///< Id of the realm +Realm realm; void SignalHandler(const boost::system::error_code& error, int signalNumber); void FreezeDetectorHandler(const boost::system::error_code& error); @@ -92,6 +93,7 @@ void WorldUpdateLoop(); void ClearOnlineAccounts(); void ShutdownCLIThread(std::thread* cliThread); void ShutdownThreadPool(std::vector<std::thread>& threadPool); +bool LoadRealmInfo(); variables_map GetConsoleArguments(int argc, char** argv, std::string& cfg_file, std::string& cfg_service); /// Launch the Trinity server @@ -192,6 +194,8 @@ extern int main(int argc, char** argv) // Set server offline (not connectable) LoginDatabase.DirectPExecute("UPDATE realmlist SET flag = (flag & ~%u) | %u WHERE id = '%d'", REALM_FLAG_OFFLINE, REALM_FLAG_INVALID, realmHandle.Index); + LoadRealmInfo(); + // Initialize the World sWorld->SetInitialWorldSettings(); @@ -226,6 +230,8 @@ extern int main(int argc, char** argv) // Set server online (allow connecting now) LoginDatabase.DirectPExecute("UPDATE realmlist SET flag = flag & ~%u, population = 0 WHERE id = '%u'", REALM_FLAG_INVALID, realmHandle.Index); + realm.PopulationLevel = 0.0f; + realm.Flags = RealmFlags(realm.Flags & ~uint32(REALM_FLAG_INVALID)); // Start the freeze check callback cycle in 5 seconds (cycle itself is 1 sec) if (int coreStuckTime = sConfigMgr->GetIntDefault("MaxCoreStuckTime", 0)) @@ -452,6 +458,62 @@ AsyncAcceptor* StartRaSocketAcceptor(boost::asio::io_service& ioService) return acceptor; } +bool LoadRealmInfo() +{ + boost::asio::ip::tcp::resolver resolver(_ioService); + boost::asio::ip::tcp::resolver::iterator end; + + QueryResult result = LoginDatabase.PQuery("SELECT id, name, address, localAddress, localSubnetMask, port, icon, flag, timezone, allowedSecurityLevel, population, gamebuild, Region, Battlegroup FROM realmlist WHERE id = %u", realmHandle.Index); + if (!result) + return false; + + Field* fields = result->Fetch(); + realm.Name = fields[1].GetString(); + boost::asio::ip::tcp::resolver::query externalAddressQuery(ip::tcp::v4(), fields[2].GetString(), ""); + + boost::system::error_code ec; + boost::asio::ip::tcp::resolver::iterator endPoint = resolver.resolve(externalAddressQuery, ec); + if (endPoint == end || ec) + { + TC_LOG_ERROR("server.worldserver", "Could not resolve address %s", fields[2].GetString().c_str()); + return false; + } + + realm.ExternalAddress = (*endPoint).endpoint().address(); + + boost::asio::ip::tcp::resolver::query localAddressQuery(ip::tcp::v4(), fields[3].GetString(), ""); + endPoint = resolver.resolve(localAddressQuery, ec); + if (endPoint == end || ec) + { + TC_LOG_ERROR("server.worldserver", "Could not resolve address %s", fields[3].GetString().c_str()); + return false; + } + + realm.LocalAddress = (*endPoint).endpoint().address(); + + boost::asio::ip::tcp::resolver::query localSubmaskQuery(ip::tcp::v4(), fields[4].GetString(), ""); + endPoint = resolver.resolve(localSubmaskQuery, ec); + if (endPoint == end || ec) + { + TC_LOG_ERROR("server.worldserver", "Could not resolve address %s", fields[4].GetString().c_str()); + return false; + } + + realm.LocalSubnetMask = (*endPoint).endpoint().address(); + + realm.Port = fields[5].GetUInt16(); + realm.Type = fields[6].GetUInt8(); + realm.Flags = RealmFlags(fields[7].GetUInt8()); + realm.Timezone = fields[8].GetUInt8(); + realm.AllowedSecurityLevel = AccountTypes(fields[9].GetUInt8()); + realm.PopulationLevel = fields[10].GetFloat(); + realm.Id.Index = fields[0].GetUInt32(); + realm.Id.Build = fields[11].GetUInt32(); + realm.Id.Region = fields[12].GetUInt8(); + realm.Id.Battlegroup = fields[13].GetUInt8(); + return true; +} + /// Initialize connection to the databases bool StartDB() { diff --git a/src/server/worldserver/RemoteAccess/RASession.cpp b/src/server/worldserver/RemoteAccess/RASession.cpp index c2b89cc0076..65ba3d4cbd9 100644 --- a/src/server/worldserver/RemoteAccess/RASession.cpp +++ b/src/server/worldserver/RemoteAccess/RASession.cpp @@ -73,7 +73,9 @@ void RASession::Start() TC_LOG_INFO("commands.ra", "User %s (IP: %s) authenticated correctly to RA", username.c_str(), GetRemoteIpAddress().c_str()); // Authentication successful, send the motd - Send(std::string(std::string(sWorld->GetMotd()) + "\r\n").c_str()); + for (std::string const& line : sWorld->GetMotd()) + Send(line.c_str()); + Send("\r\n"); // Read commands for (;;) diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist index 4d40365451e..e4406e7ecce 100644 --- a/src/server/worldserver/worldserver.conf.dist +++ b/src/server/worldserver/worldserver.conf.dist @@ -141,6 +141,13 @@ MaxPingTime = 30 WorldServerPort = 8085 # +# InstanceServerPort +# Description: TCP port to for second world connection. +# Default: 8086 + +InstanceServerPort = 8086 + +# # BindIP # Description: Bind world server to IP/hostname. # Default: "0.0.0.0" - (Bind to all IPs on the system) @@ -2258,9 +2265,9 @@ Arena.QueueAnnouncer.Enable = 0 # # Arena.ArenaSeason.ID # Description: Current arena season id shown in clients. -# Default: 8 +# Default: 15 -Arena.ArenaSeason.ID = 8 +Arena.ArenaSeason.ID = 15 # # Arena.ArenaSeason.InProgress diff --git a/src/tools/connection_patcher/CMakeLists.txt b/src/tools/connection_patcher/CMakeLists.txt index 7af523589f7..fca159ff978 100644 --- a/src/tools/connection_patcher/CMakeLists.txt +++ b/src/tools/connection_patcher/CMakeLists.txt @@ -21,8 +21,10 @@ set(HEADER_FILES Helper.hpp Patcher.hpp Constants/BinaryTypes.hpp + Patches/Common.hpp Patches/Mac.hpp Patches/Windows.hpp + Patterns/Common.hpp Patterns/Mac.hpp Patterns/Windows.hpp ) @@ -35,6 +37,10 @@ set(SRC_FILES add_executable(connection_patcher ${HEADER_FILES} ${SRC_FILES}) +if (MSVC) + set_target_properties(connection_patcher PROPERTIES LINK_FLAGS "/level='requireAdministrator' /uiAccess='false'") +endif () + target_link_libraries(connection_patcher shared ${OPENSSL_LIBRARIES} diff --git a/src/tools/connection_patcher/Patcher.cpp b/src/tools/connection_patcher/Patcher.cpp index 65cf1704472..92d9dacedf3 100644 --- a/src/tools/connection_patcher/Patcher.cpp +++ b/src/tools/connection_patcher/Patcher.cpp @@ -24,6 +24,7 @@ #include <fstream> #include <iostream> #include <iterator> +#include <set> #include <stdexcept> namespace @@ -50,17 +51,15 @@ namespace std::copy(data.begin(), data.end(), std::ostream_iterator<unsigned char>(ofs)); } - size_t SearchOffset (std::vector<unsigned char> const& binary, std::vector<unsigned char> const& pattern) + std::set<size_t> SearchOffset (std::vector<unsigned char> const& binary, std::vector<unsigned char> const& pattern) { - for (size_t i = 0; i < binary.size(); i++) + std::set<size_t> offsets; + for (size_t i = 0; (i + pattern.size()) < binary.size(); i++) { size_t matches = 0; for (size_t j = 0; j < pattern.size(); j++) { - if (pattern.size() > (binary.size() - i)) - throw std::runtime_error("unable to find pattern"); - if (pattern[j] == 0) { matches++; @@ -74,10 +73,13 @@ namespace } if (matches == pattern.size()) - return i; + { + offsets.insert(i); + i += matches; + } } - throw std::runtime_error("unable to find pattern"); + return offsets.empty() ? throw std::runtime_error("unable to find pattern") : offsets; } } @@ -96,12 +98,14 @@ namespace Connection_Patcher if (pattern.empty()) return; - size_t const offset(SearchOffset(binary, pattern)); - std::cout << "Found offset " << offset << std::endl; + for (size_t const offset : SearchOffset(binary, pattern)) + { + std::cout << "Found offset " << offset << std::endl; - if (offset != 0 && binary.size() >= bytes.size()) - for (size_t i = 0; i < bytes.size(); i++) - binary[offset + i] = bytes[i]; + if (offset != 0 && binary.size() >= bytes.size()) + for (size_t i = 0; i < bytes.size(); i++) + binary[offset + i] = bytes[i]; + } } void Patcher::Finish(boost::filesystem::path out) diff --git a/src/tools/connection_patcher/Patches/Common.hpp b/src/tools/connection_patcher/Patches/Common.hpp new file mode 100644 index 00000000000..9741e61f5a9 --- /dev/null +++ b/src/tools/connection_patcher/Patches/Common.hpp @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2012-2014 Arctium Emulation <http://arctium.org> + * Copyright (C) 2008-2014 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 3 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 CONNECTION_PATCHER_PATCHES_COMMON_HPP +#define CONNECTION_PATCHER_PATCHES_COMMON_HPP + +#include <vector> + +namespace Connection_Patcher +{ + namespace Patches + { + struct Common + { + static const std::vector<unsigned char> Portal() { return { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; } + static const std::vector<unsigned char> Modulus() + { + return + { + 0x5F, 0xD6, 0x80, 0x0B, 0xA7, 0xFF, 0x01, 0x40, 0xC7, 0xBC, 0x8E, 0xF5, 0x6B, 0x27, 0xB0, 0xBF, + 0xF0, 0x1D, 0x1B, 0xFE, 0xDD, 0x0B, 0x1F, 0x3D, 0xB6, 0x6F, 0x1A, 0x48, 0x0D, 0xFB, 0x51, 0x08, + 0x65, 0x58, 0x4F, 0xDB, 0x5C, 0x6E, 0xCF, 0x64, 0xCB, 0xC1, 0x6B, 0x2E, 0xB8, 0x0F, 0x5D, 0x08, + 0x5D, 0x89, 0x06, 0xA9, 0x77, 0x8B, 0x9E, 0xAA, 0x04, 0xB0, 0x83, 0x10, 0xE2, 0x15, 0x4D, 0x08, + 0x77, 0xD4, 0x7A, 0x0E, 0x5A, 0xB0, 0xBB, 0x00, 0x61, 0xD7, 0xA6, 0x75, 0xDF, 0x06, 0x64, 0x88, + 0xBB, 0xB9, 0xCA, 0xB0, 0x18, 0x8B, 0x54, 0x13, 0xE2, 0xCB, 0x33, 0xDF, 0x17, 0xD8, 0xDA, 0xA9, + 0xA5, 0x60, 0xA3, 0x1F, 0x4E, 0x27, 0x05, 0x98, 0x6F, 0xAA, 0xEE, 0x14, 0x3B, 0xF3, 0x97, 0xA8, + 0x12, 0x02, 0x94, 0x0D, 0x84, 0xDC, 0x0E, 0xF1, 0x76, 0x23, 0x95, 0x36, 0x13, 0xF9, 0xA9, 0xC5, + 0x48, 0xDB, 0xDA, 0x86, 0xBE, 0x29, 0x22, 0x54, 0x44, 0x9D, 0x9F, 0x80, 0x7B, 0x07, 0x80, 0x30, + 0xEA, 0xD2, 0x83, 0xCC, 0xCE, 0x37, 0xD1, 0xD1, 0xCF, 0x85, 0xBE, 0x91, 0x25, 0xCE, 0xC0, 0xCC, + 0x55, 0xC8, 0xC0, 0xFB, 0x38, 0xC5, 0x49, 0x03, 0x6A, 0x02, 0xA9, 0x9F, 0x9F, 0x86, 0xFB, 0xC7, + 0xCB, 0xC6, 0xA5, 0x82, 0xA2, 0x30, 0xC2, 0xAC, 0xE6, 0x98, 0xDA, 0x83, 0x64, 0x43, 0x7F, 0x0D, + 0x13, 0x18, 0xEB, 0x90, 0x53, 0x5B, 0x37, 0x6B, 0xE6, 0x0D, 0x80, 0x1E, 0xEF, 0xED, 0xC7, 0xB8, + 0x68, 0x9B, 0x4C, 0x09, 0x7B, 0x60, 0xB2, 0x57, 0xD8, 0x59, 0x8D, 0x7F, 0xEA, 0xCD, 0xEB, 0xC4, + 0x60, 0x9F, 0x45, 0x7A, 0xA9, 0x26, 0x8A, 0x2F, 0x85, 0x0C, 0xF2, 0x19, 0xC6, 0x53, 0x92, 0xF7, + 0xF0, 0xB8, 0x32, 0xCB, 0x5B, 0x66, 0xCE, 0x51, 0x54, 0xB4, 0xC3, 0xD3, 0xD4, 0xDC, 0xB3, 0xEE + }; + } + }; + } +} + +#endif diff --git a/src/tools/connection_patcher/Patches/Mac.hpp b/src/tools/connection_patcher/Patches/Mac.hpp index 4080dc937d6..9fad02e3ec6 100644 --- a/src/tools/connection_patcher/Patches/Mac.hpp +++ b/src/tools/connection_patcher/Patches/Mac.hpp @@ -30,10 +30,8 @@ namespace Connection_Patcher struct x64 { static const std::vector<unsigned char> BNet () { return { 0xB8, 0xD5, 0xF8, 0x7F, 0x82, 0x89, 0x47, 0x0C, 0x5D, 0xC3, 0x90, 0x90, 0x90 }; } - static const std::vector<unsigned char> Portal () { return { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; } - static const std::vector<unsigned char> Connect () { return { }; } static const std::vector<unsigned char> Password () { return { 0x0F, 0x85 }; } - static const std::vector<unsigned char> Signature() { return { 0x45, 0x31, 0xED, 0x4D, 0x89, 0xFC, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0xEB }; } + static const std::vector<unsigned char> Signature() { return { 0x41, 0xB6, 0x01, 0x41, 0xBF, 0x02, 0x00, 0x00, 0x00, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 }; } }; }; } diff --git a/src/tools/connection_patcher/Patches/Windows.hpp b/src/tools/connection_patcher/Patches/Windows.hpp index deb2041352a..0f4ffb93dac 100644 --- a/src/tools/connection_patcher/Patches/Windows.hpp +++ b/src/tools/connection_patcher/Patches/Windows.hpp @@ -30,8 +30,6 @@ namespace Connection_Patcher struct x86 { static const std::vector<unsigned char> BNet () { return { 0xC7, 0x40, 0x0C, 0xD5, 0xF8, 0x7F, 0x82 }; } - static const std::vector<unsigned char> Portal () { return { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; } - static const std::vector<unsigned char> Connect () { return { 0xEB }; } static const std::vector<unsigned char> Password () { return { 0x75 }; } static const std::vector<unsigned char> Signature() { return { 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0xEB }; } }; @@ -39,8 +37,6 @@ namespace Connection_Patcher struct x64 { static const std::vector<unsigned char> BNet () { return { 0xB8, 0xD5, 0xF8, 0x7F, 0x82, 0x89, 0x41, 0x0C, 0x48, 0x8B, 0xC1, 0xC3 }; } - static const std::vector<unsigned char> Portal () { return { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; } - static const std::vector<unsigned char> Connect () { return { 0xEB }; } static const std::vector<unsigned char> Password () { return { 0x75 }; } static const std::vector<unsigned char> Signature() { return { 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0xE9 }; } }; diff --git a/src/tools/connection_patcher/Patterns/Common.hpp b/src/tools/connection_patcher/Patterns/Common.hpp new file mode 100644 index 00000000000..94c4a220a57 --- /dev/null +++ b/src/tools/connection_patcher/Patterns/Common.hpp @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2012-2014 Arctium Emulation <http://arctium.org> + * Copyright (C) 2008-2014 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 3 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 CONNECTION_PATCHER_PATTERNS_COMMON_HPP +#define CONNECTION_PATCHER_PATTERNS_COMMON_HPP + +#include <vector> + +namespace Connection_Patcher +{ + namespace Patterns + { + struct Common + { + static const std::vector<unsigned char> Portal() { return { '.', 'l', 'o', 'g', 'o', 'n', '.', 'b', 'a', 't', 't', 'l', 'e', '.', 'n', 'e', 't', 0x00 }; } + static const std::vector<unsigned char> Modulus() { return { 0x91, 0xD5, 0x9B, 0xB7, 0xD4, 0xE1, 0x83, 0xA5 }; } + }; + } +} + +#endif diff --git a/src/tools/connection_patcher/Patterns/Mac.hpp b/src/tools/connection_patcher/Patterns/Mac.hpp index b4cbacd8a7c..6f13cdda5c7 100644 --- a/src/tools/connection_patcher/Patterns/Mac.hpp +++ b/src/tools/connection_patcher/Patterns/Mac.hpp @@ -30,10 +30,8 @@ namespace Connection_Patcher struct x64 { static const std::vector<unsigned char> BNet () { return { 0x8B, 0x06, 0x89, 0x47, 0x0C, 0x5D, 0xC3 }; } - static const std::vector<unsigned char> Portal () { return { '.', 'l', 'o', 'g', 'o', 'n', '.', 'b', 'a', 't', 't', 'l', 'e', '.', 'n', 'e', 't', 0x00 }; } - static const std::vector<unsigned char> Connect () { return { }; } static const std::vector<unsigned char> Password () { return { 0x0F, 0x84, 0x00, 0xFF, 0xFF, 0xFF, 0x49, 0x8B, 0x45, 0x00, 0xB9, 0x40 }; } - static const std::vector<unsigned char> Signature() { return { 0xE8, 0x00, 0x00, 0x00, 0x00, 0x45, 0x31, 0xED, 0x4D, 0x89, 0xFC, 0x84, 0xC0, 0x75 }; } + static const std::vector<unsigned char> Signature() { return { 0x45, 0x31, 0xF6, 0x31, 0xF6, 0x31, 0xD2, 0x4C, 0x89, 0xE7, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x41, 0xBF, 0x04, 0x00, 0x00, 0x00 }; } }; }; } diff --git a/src/tools/connection_patcher/Patterns/Windows.hpp b/src/tools/connection_patcher/Patterns/Windows.hpp index 9a8b14e137b..2cad97541e3 100644 --- a/src/tools/connection_patcher/Patterns/Windows.hpp +++ b/src/tools/connection_patcher/Patterns/Windows.hpp @@ -30,8 +30,6 @@ namespace Connection_Patcher struct x86 { static const std::vector<unsigned char> BNet () { return { 0x8B, 0x75, 0x08, 0x8D, 0x78, 0x0C }; } - static const std::vector<unsigned char> Portal () { return { '.', 'l', 'o', 'g', 'o', 'n', '.', 'b', 'a', 't', 't', 'l', 'e', '.', 'n', 'e', 't', 0x00 }; } - static const std::vector<unsigned char> Connect () { return { 0x74, 0x33, 0x6A, 0x04, 0xFF, 0x75, 0xF8 }; } static const std::vector<unsigned char> Password () { return { 0x74, 0x89, 0x8B, 0x16, 0x8B, 0x42, 0x04 }; } static const std::vector<unsigned char> Signature() { return { 0xE8, 0x00, 0x00, 0x00, 0x00, 0x84, 0xC0, 0x75, 0x5F, 0x33, 0xC0 }; } }; @@ -39,8 +37,6 @@ namespace Connection_Patcher struct x64 { static const std::vector<unsigned char> BNet () { return { 0x8B, 0x02, 0x89, 0x41, 0x0C, 0x48, 0x8B, 0xC1, 0xC3 }; } - static const std::vector<unsigned char> Portal () { return { '.', 'l', 'o', 'g', 'o', 'n', '.', 'b', 'a', 't', 't', 'l', 'e', '.', 'n', 'e', 't', 0x00 }; } - static const std::vector<unsigned char> Connect () { return { 0x74, 0x2C, 0x48, 0x8D, 0x4C, 0x24, 0x78 }; } static const std::vector<unsigned char> Password () { return { 0x74, 0x84, 0x48, 0x8B, 0x03 }; } static const std::vector<unsigned char> Signature() { return { 0xE8, 0x00, 0x00, 0x00, 0x00, 0x84, 0xC0, 0x0F, 0x85, 0x88, 0x00, 0x00, 0x00, 0x45, 0x33, 0xC0 }; } }; diff --git a/src/tools/connection_patcher/Program.cpp b/src/tools/connection_patcher/Program.cpp index 539c6093d53..56007232d20 100644 --- a/src/tools/connection_patcher/Program.cpp +++ b/src/tools/connection_patcher/Program.cpp @@ -18,8 +18,10 @@ #include "Helper.hpp" #include "Patcher.hpp" +#include "Patches/Common.hpp" #include "Patches/Mac.hpp" #include "Patches/Windows.hpp" +#include "Patterns/Common.hpp" #include "Patterns/Mac.hpp" #include "Patterns/Windows.hpp" @@ -41,20 +43,27 @@ namespace Connection_Patcher template<typename PATCH, typename PATTERN> void PatchModule(boost::filesystem::path file, boost::filesystem::path path) { + namespace fs = boost::filesystem; + std::cout << "Patching module...\n"; Patcher patcher(file); + std::cout << "patching Password\n"; + // if (Authentication::ServerSignature::ClientValidateProof(x)) to if (true) patcher.Patch(PATCH::Password(), PATTERN::Password()); std::string const moduleName(Helper::GetFileChecksum(patcher.binary) + ".auth"); - boost::filesystem::path const modulePath + fs::path const modulePath (path / std::string(&moduleName[0], 2) / std::string(&moduleName[2], 2)); - if (!boost::filesystem::exists(modulePath)) - boost::filesystem::create_directories(modulePath); + if (!fs::exists(modulePath)) + fs::create_directories(modulePath); + if (fs::exists(modulePath / modulePath)) + fs::permissions(modulePath / moduleName, fs::add_perms | fs::others_write | fs::group_write | fs::owner_write); patcher.Finish(modulePath / moduleName); + fs::permissions(modulePath / moduleName, fs::remove_perms | fs::others_write | fs::group_write | fs::owner_write); std::cout << "Patching module finished.\n"; } @@ -75,18 +84,28 @@ namespace Connection_Patcher template<typename PATCH, typename PATTERN> void do_patches(Patcher* patcher, boost::filesystem::path output) { + std::cout << "patching Portal\n"; + // '.logon.battle.net' -> '' to allow for set portal 'host' + patcher->Patch(Patches::Common::Portal(), Patterns::Common::Portal()); + + std::cout << "patching redirect RSA Modulus\n"; + // public component of connection signing key to use known key pair + patcher->Patch(Patches::Common::Modulus(), Patterns::Common::Modulus()); + std::cout << "patching BNet\n"; + // hardcode 213.248.127.130 in IP6::Address::Address(IP4::Address::Address const&) + // used in Creep::Layer::Authentication::Online(), which overwrites GameStream::Connection::GetAddressRemote() + // to avoid CRYPT_SERVER_ADDRESS_IPV6 check in module patcher->Patch(PATCH::BNet(), PATTERN::BNet()); - std::cout << "patching Portal\n"; - patcher->Patch(PATCH::Portal(), PATTERN::Portal()); - std::cout << "patching Connect\n"; - patcher->Patch(PATCH::Connect(), PATTERN::Connect()); + std::cout << "patching Signature\n"; + // if (Authentication::ModuleSignature::Validator::IsValid(x)) to if (true) in + // Creep::Instance::LoadModule() to allow for unsigned auth module patcher->Patch(PATCH::Signature(), PATTERN::Signature()); + patcher->Finish(output); std::cout << "Patching done.\n"; - } } @@ -175,7 +194,7 @@ int main(int argc, char** argv) do_patches<Patches::Mac::x64, Patterns::Mac::x64> (&patcher, renamed_binary_path); - do_module<Patches::Windows::x64, Patterns::Windows::x64> + do_module<Patches::Mac::x64, Patterns::Mac::x64> ( "97eeb2e28e9e56ed6a22d09f44e2ff43c93315e006bbad43bafc0defaa6f50ae.auth" , "/Users/Shared/Blizzard/Battle.net/Cache/" ); diff --git a/src/tools/map_extractor/loadlib/DBFilesClientList.h b/src/tools/map_extractor/loadlib/DBFilesClientList.h index 0520e63912b..aadfe7a3666 100644 --- a/src/tools/map_extractor/loadlib/DBFilesClientList.h +++ b/src/tools/map_extractor/loadlib/DBFilesClientList.h @@ -526,6 +526,7 @@ char const* DBFilesClientList[] = "DBFilesClient\\ModelFileData.dbc", "DBFilesClient\\ManifestMP3.dbc", "DBFilesClient\\FileData.dbc", + "DBFilesClient\\WorldSafeLocs.dbc", nullptr // terminator }; |