diff --git a/CMakeLists.txt b/CMakeLists.txt index 90922cd77e2..c6ec8e9d95b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -61,7 +61,6 @@ find_package(Threads REQUIRED) find_package(ZMQ REQUIRED) include(ConfigureBoost) -find_package(MySQL REQUIRED) if( UNIX ) find_package(Readline) diff --git a/cmake/genrev.cmake b/cmake/genrev.cmake index 1f5f02ceeec..db722f9fdb8 100644 --- a/cmake/genrev.cmake +++ b/cmake/genrev.cmake @@ -66,11 +66,11 @@ else() endif() endif() -# Create the actual revision.h file from the above params -if(NOT "${rev_hash_cached}" MATCHES "${rev_hash}" OR NOT "${rev_branch_cached}" MATCHES "${rev_branch}" OR NOT EXISTS "${BUILDDIR}/revision.h") +# Create the actual revision_data.h file from the above params +if(NOT "${rev_hash_cached}" MATCHES "${rev_hash}" OR NOT "${rev_branch_cached}" MATCHES "${rev_branch}" OR NOT EXISTS "${BUILDDIR}/revision_data.h") configure_file( - "${CMAKE_SOURCE_DIR}/revision.h.in.cmake" - "${BUILDDIR}/revision.h" + "${CMAKE_SOURCE_DIR}/revision_data.h.in.cmake" + "${BUILDDIR}/revision_data.h" @ONLY ) set(rev_hash_cached "${rev_hash}" CACHE INTERNAL "Cached commit-hash") diff --git a/revision.h.in.cmake b/revision_data.h.in.cmake similarity index 77% rename from revision.h.in.cmake rename to revision_data.h.in.cmake index eab0437c600..de70f7e7ec8 100644 --- a/revision.h.in.cmake +++ b/revision_data.h.in.cmake @@ -1,5 +1,5 @@ -#ifndef __REVISION_H__ -#define __REVISION_H__ +#ifndef __REVISION_DATA_H__ +#define __REVISION_DATA_H__ #define _HASH "@rev_hash@" #define _DATE "@rev_date@" #define _BRANCH "@rev_branch@" @@ -12,4 +12,6 @@ #define VER_FILEVERSION_STR "@rev_hash@ @rev_date@ (@rev_branch@ branch)" #define VER_PRODUCTVERSION VER_FILEVERSION #define VER_PRODUCTVERSION_STR VER_FILEVERSION_STR -#endif // __REVISION_H__ + #define COMPILER_C_FLAGS "@CMAKE_C_FLAGS@" + #define COMPILER_CXX_FLAGS "@CMAKE_CXX_FLAGS@" +#endif // __REVISION_DATA_H__ diff --git a/sql/base/auth_database.sql b/sql/base/auth_database.sql index 86f21acad26..14feed913a4 100644 --- a/sql/base/auth_database.sql +++ b/sql/base/auth_database.sql @@ -537,7 +537,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),(192,835),(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); /*!40000 ALTER TABLE `rbac_linked_permissions` ENABLE KEYS */; UNLOCK TABLES; @@ -561,7 +561,7 @@ CREATE TABLE `rbac_permissions` ( LOCK TABLES `rbac_permissions` WRITE; /*!40000 ALTER TABLE `rbac_permissions` DISABLE KEYS */; -INSERT INTO `rbac_permissions` VALUES (1,'Instant logout'),(2,'Skip Queue'),(3,'Join Normal Battleground'),(4,'Join Random Battleground'),(5,'Join Arenas'),(6,'Join Dungeon Finder'),(11,'Log GM trades'),(13,'Skip Instance required bosses check'),(14,'Skip character creation team mask check'),(15,'Skip character creation class mask check'),(16,'Skip character creation race mask check'),(17,'Skip character creation reserved name check'),(18,'Skip character creation heroic min level check'),(19,'Skip needed requirements to use channel check'),(20,'Skip disable map check'),(21,'Skip reset talents when used more than allowed check'),(22,'Skip spam chat check'),(23,'Skip over-speed ping check'),(24,'Two side faction characters on the same account'),(25,'Allow say chat between factions'),(26,'Allow channel chat between factions'),(27,'Two side mail interaction'),(28,'See two side who list'),(29,'Add friends of other faction'),(30,'Save character without delay with .save command'),(31,'Use params with .unstuck command'),(32,'Can be assigned tickets with .assign ticket command'),(33,'Notify if a command was not found'),(34,'Check if should appear in list using .gm ingame command'),(35,'See all security levels with who command'),(36,'Filter whispers'),(37,'Use staff badge in chat'),(38,'Resurrect with full Health Points'),(39,'Restore saved gm setting states'),(40,'Allows to add a gm to friend list'),(41,'Use Config option START_GM_LEVEL to assign new character level'),(42,'Allows to use CMSG_WORLD_TELEPORT opcode'),(43,'Allows to use CMSG_WHOIS opcode'),(44,'Receive global GM messages/texts'),(45,'Join channels without announce'),(46,'Change channel settings without being channel moderator'),(47,'Enables lower security than target check'),(48,'Enable IP, Last Login and EMail output in pinfo'),(49,'Forces to enter the email for confirmation on password change'),(50,'Allow user to check his own email with .account'),(192,'Role: Sec Level Administrator'),(193,'Role: Sec Level Gamemaster'),(194,'Role: Sec Level Moderator'),(195,'Role: Sec Level Player'),(196,'Role: Administrator Commands'),(197,'Role: Gamemaster Commands'),(198,'Role: Moderator Commands'),(199,'Role: Player Commands'),(200,'Command: rbac'),(201,'Command: rbac account'),(202,'Command: rbac account list'),(203,'Command: rbac account grant'),(204,'Command: rbac account deny'),(205,'Command: rbac account revoke'),(206,'Command: rbac list'),(207,'Command: battlenetaccount'),(208,'Command: battlenetaccount create'),(209,'Command: battlenetaccount lock country'),(210,'Command: battlenetaccount lock ip'),(211,'Command: battlenetaccount password'),(212,'Command: battlenetaccount set'),(213,'Command: battlenetaccount set password'),(217,'Command: account'),(218,'Command: account addon'),(219,'Command: account create'),(220,'Command: account delete'),(221,'Command: account lock'),(222,'Command: account lock country'),(223,'Command: account lock ip'),(224,'Command: account onlinelist'),(225,'Command: account password'),(226,'Command: account set'),(227,'Command: account set addon'),(228,'Command: account set gmlevel'),(229,'Command: account set password'),(230,'Command: achievement'),(231,'Command: achievement add'),(232,'Command: arena'),(233,'Command: arena captain'),(234,'Command: arena create'),(235,'Command: arena disband'),(236,'Command: arena info'),(237,'Command: arena lookup'),(238,'Command: arena rename'),(239,'Command: ban'),(240,'Command: ban account'),(241,'Command: ban character'),(242,'Command: ban ip'),(243,'Command: ban playeraccount'),(244,'Command: baninfo'),(245,'Command: baninfo account'),(246,'Command: baninfo character'),(247,'Command: baninfo ip'),(248,'Command: banlist'),(249,'Command: banlist account'),(250,'Command: banlist character'),(251,'Command: banlist ip'),(252,'Command: unban'),(253,'Command: unban account'),(254,'Command: unban character'),(255,'Command: unban ip'),(256,'Command: unban playeraccount'),(257,'Command: bf'),(258,'Command: bf start'),(259,'Command: bf stop'),(260,'Command: bf switch'),(261,'Command: bf timer'),(262,'Command: bf enable'),(263,'Command: account email'),(264,'Command: account set sec'),(265,'Command: account set sec email'),(266,'Command: account set sec regmail'),(267,'Command: cast'),(268,'Command: cast back'),(269,'Command: cast dist'),(270,'Command: cast self'),(271,'Command: cast target'),(272,'Command: cast dest'),(273,'Command: character'),(274,'Command: character customize'),(275,'Command: character changefaction'),(276,'Command: character changerace'),(277,'Command: character deleted'),(279,'Command: character deleted list'),(280,'Command: character deleted restore'),(283,'Command: character level'),(284,'Command: character rename'),(285,'Command: character reputation'),(286,'Command: character titles'),(287,'Command: levelup'),(288,'Command: pdump'),(289,'Command: pdump load'),(290,'Command: pdump write'),(291,'Command: cheat'),(292,'Command: cheat casttime'),(293,'Command: cheat cooldown'),(294,'Command: cheat explore'),(295,'Command: cheat god'),(296,'Command: cheat power'),(297,'Command: cheat status'),(298,'Command: cheat taxi'),(299,'Command: cheat waterwalk'),(300,'Command: debug'),(301,'Command: debug anim'),(302,'Command: debug areatriggers'),(303,'Command: debug arena'),(304,'Command: debug bg'),(305,'Command: debug entervehicle'),(306,'Command: debug getitemstate'),(307,'Command: debug getitemvalue'),(308,'Command: debug getvalue'),(309,'Command: debug hostil'),(310,'Command: debug itemexpire'),(311,'Command: debug lootrecipient'),(312,'Command: debug los'),(313,'Command: debug mod32value'),(314,'Command: debug moveflags'),(315,'Command: debug play'),(316,'Command: debug play cinematics'),(317,'Command: debug play movie'),(318,'Command: debug play sound'),(319,'Command: debug send'),(320,'Command: debug send buyerror'),(321,'Command: debug send channelnotify'),(322,'Command: debug send chatmessage'),(323,'Command: debug send equiperror'),(324,'Command: debug send largepacket'),(325,'Command: debug send opcode'),(326,'Command: debug send qinvalidmsg'),(327,'Command: debug send qpartymsg'),(328,'Command: debug send sellerror'),(329,'Command: debug send setphaseshift'),(330,'Command: debug send spellfail'),(331,'Command: debug setaurastate'),(332,'Command: debug setbit'),(333,'Command: debug setitemvalue'),(334,'Command: debug setvalue'),(335,'Command: debug setvid'),(336,'Command: debug spawnvehicle'),(337,'Command: debug threat'),(338,'Command: debug update'),(339,'Command: debug uws'),(340,'Command: wpgps'),(341,'Command: deserter'),(342,'Command: deserter bg'),(343,'Command: deserter bg add'),(344,'Command: deserter bg remove'),(345,'Command: deserter instance'),(346,'Command: deserter instance add'),(347,'Command: deserter instance remove'),(348,'Command: disable'),(349,'Command: disable add'),(350,'Command: disable add achievement_criteria'),(351,'Command: disable add battleground'),(352,'Command: disable add map'),(353,'Command: disable add mmap'),(354,'Command: disable add outdoorpvp'),(355,'Command: disable add quest'),(356,'Command: disable add spell'),(357,'Command: disable add vmap'),(358,'Command: disable remove'),(359,'Command: disable remove achievement_criteria'),(360,'Command: disable remove battleground'),(361,'Command: disable remove map'),(362,'Command: disable remove mmap'),(363,'Command: disable remove outdoorpvp'),(364,'Command: disable remove quest'),(365,'Command: disable remove spell'),(366,'Command: disable remove vmap'),(367,'Command: event'),(368,'Command: event activelist'),(369,'Command: event start'),(370,'Command: event stop'),(371,'Command: gm'),(372,'Command: gm chat'),(373,'Command: gm fly'),(374,'Command: gm ingame'),(375,'Command: gm list'),(376,'Command: gm visible'),(377,'Command: go'),(378,'Command: go creature'),(379,'Command: go graveyard'),(380,'Command: go grid'),(381,'Command: go object'),(382,'Command: go taxinode'),(383,'Command: go ticket'),(384,'Command: go trigger'),(385,'Command: go xyz'),(386,'Command: go zonexy'),(387,'Command: gobject'),(388,'Command: gobject activate'),(389,'Command: gobject add'),(390,'Command: gobject add temp'),(391,'Command: gobject delete'),(392,'Command: gobject info'),(393,'Command: gobject move'),(394,'Command: gobject near'),(395,'Command: gobject set'),(396,'Command: gobject set phase'),(397,'Command: gobject set state'),(398,'Command: gobject target'),(399,'Command: gobject turn'),(400,'debug transport'),(401,'Command: guild'),(402,'Command: guild create'),(403,'Command: guild delete'),(404,'Command: guild invite'),(405,'Command: guild uninvite'),(406,'Command: guild rank'),(407,'Command: guild rename'),(408,'Command: honor'),(409,'Command: honor add'),(410,'Command: honor add kill'),(411,'Command: honor update'),(412,'Command: instance'),(413,'Command: instance listbinds'),(414,'Command: instance unbind'),(415,'Command: instance stats'),(416,'Command: instance savedata'),(417,'Command: learn'),(418,'Command: learn all'),(419,'Command: learn all my'),(420,'Command: learn all my class'),(421,'Command: learn all my pettalents'),(422,'Command: learn all my spells'),(423,'Command: learn all my talents'),(424,'Command: learn all gm'),(425,'Command: learn all crafts'),(426,'Command: learn all default'),(427,'Command: learn all lang'),(428,'Command: learn all recipes'),(429,'Command: unlearn'),(430,'Command: lfg'),(431,'Command: lfg player'),(432,'Command: lfg group'),(433,'Command: lfg queue'),(434,'Command: lfg clean'),(435,'Command: lfg options'),(436,'Command: list'),(437,'Command: list creature'),(438,'Command: list item'),(439,'Command: list object'),(440,'Command: list auras'),(441,'Command: list mail'),(442,'Command: lookup'),(443,'Command: lookup area'),(444,'Command: lookup creature'),(445,'Command: lookup event'),(446,'Command: lookup faction'),(447,'Command: lookup item'),(448,'Command: lookup itemset'),(449,'Command: lookup object'),(450,'Command: lookup quest'),(451,'Command: lookup player'),(452,'Command: lookup player ip'),(453,'Command: lookup player account'),(454,'Command: lookup player email'),(455,'Command: lookup skill'),(456,'Command: lookup spell'),(457,'Command: lookup spell id'),(458,'Command: lookup taxinode'),(459,'Command: lookup tele'),(460,'Command: lookup title'),(461,'Command: lookup map'),(462,'Command: announce'),(463,'Command: channel'),(464,'Command: channel set'),(465,'Command: channel set ownership'),(466,'Command: gmannounce'),(467,'Command: gmnameannounce'),(468,'Command: gmnotify'),(469,'Command: nameannounce'),(470,'Command: notify'),(471,'Command: whispers'),(472,'Command: group'),(473,'Command: group leader'),(474,'Command: group disband'),(475,'Command: group remove'),(476,'Command: group join'),(477,'Command: group list'),(478,'Command: group summon'),(479,'Command: pet'),(480,'Command: pet create'),(481,'Command: pet learn'),(482,'Command: pet unlearn'),(483,'Command: send'),(484,'Command: send items'),(485,'Command: send mail'),(486,'Command: send message'),(487,'Command: send money'),(488,'Command: additem'),(489,'Command: additemset'),(490,'Command: appear'),(491,'Command: aura'),(492,'Command: bank'),(493,'Command: bindsight'),(494,'Command: combatstop'),(495,'Command: cometome'),(496,'Command: commands'),(497,'Command: cooldown'),(498,'Command: damage'),(499,'Command: dev'),(500,'Command: die'),(501,'Command: dismount'),(502,'Command: distance'),(503,'Command: flusharenapoints'),(504,'Command: freeze'),(505,'Command: gps'),(506,'Command: guid'),(507,'Command: help'),(508,'Command: hidearea'),(509,'Command: itemmove'),(510,'Command: kick'),(511,'Command: linkgrave'),(512,'Command: listfreeze'),(513,'Command: maxskill'),(514,'Command: movegens'),(515,'Command: mute'),(516,'Command: neargrave'),(517,'Command: pinfo'),(518,'Command: playall'),(519,'Command: possess'),(520,'Command: recall'),(521,'Command: repairitems'),(522,'Command: respawn'),(523,'Command: revive'),(524,'Command: saveall'),(525,'Command: save'),(526,'Command: setskill'),(527,'Command: showarea'),(528,'Command: summon'),(529,'Command: unaura'),(530,'Command: unbindsight'),(531,'Command: unfreeze'),(532,'Command: unmute'),(533,'Command: unpossess'),(534,'Command: unstuck'),(535,'Command: wchange'),(536,'Command: mmap'),(537,'Command: mmap loadedtiles'),(538,'Command: mmap loc'),(539,'Command: mmap path'),(540,'Command: mmap stats'),(541,'Command: mmap testarea'),(542,'Command: morph'),(543,'Command: demorph'),(544,'Command: modify'),(545,'Command: modify arenapoints'),(546,'Command: modify bit'),(547,'Command: modify drunk'),(548,'Command: modify energy'),(549,'Command: modify faction'),(550,'Command: modify gender'),(551,'Command: modify honor'),(552,'Command: modify hp'),(553,'Command: modify mana'),(554,'Command: modify money'),(555,'Command: modify mount'),(556,'Command: modify phase'),(557,'Command: modify rage'),(558,'Command: modify reputation'),(559,'Command: modify runicpower'),(560,'Command: modify scale'),(561,'Command: modify speed'),(562,'Command: modify speed all'),(563,'Command: modify speed backwalk'),(564,'Command: modify speed fly'),(565,'Command: modify speed walk'),(566,'Command: modify speed swim'),(567,'Command: modify spell'),(568,'Command: modify standstate'),(569,'Command: modify talentpoints'),(570,'Command: npc'),(571,'Command: npc add'),(572,'Command: npc add formation'),(573,'Command: npc add item'),(574,'Command: npc add move'),(575,'Command: npc add temp'),(576,'Command: npc add delete'),(577,'Command: npc add delete item'),(578,'Command: npc add follow'),(579,'Command: npc add follow stop'),(580,'Command: npc set'),(581,'Command: npc set allowmove'),(582,'Command: npc set entry'),(583,'Command: npc set factionid'),(584,'Command: npc set flag'),(585,'Command: npc set level'),(586,'Command: npc set link'),(587,'Command: npc set model'),(588,'Command: npc set movetype'),(589,'Command: npc set phase'),(590,'Command: npc set spawndist'),(591,'Command: npc set spawntime'),(592,'Command: npc set data'),(593,'Command: npc info'),(594,'Command: npc near'),(595,'Command: npc move'),(596,'Command: npc playemote'),(597,'Command: npc say'),(598,'Command: npc textemote'),(599,'Command: npc whisper'),(600,'Command: npc yell'),(601,'Command: npc tame'),(602,'Command: quest'),(603,'Command: quest add'),(604,'Command: quest complete'),(605,'Command: quest remove'),(606,'Command: quest reward'),(607,'Command: reload'),(608,'Command: reload access_requirement'),(609,'Command: reload achievement_criteria_data'),(610,'Command: reload achievement_reward'),(611,'Command: reload all'),(612,'Command: reload all achievement'),(613,'Command: reload all area'),(614,'Command: broadcast_text'),(615,'Command: reload all gossips'),(616,'Command: reload all item'),(617,'Command: reload all locales'),(618,'Command: reload all loot'),(619,'Command: reload all npc'),(620,'Command: reload all quest'),(621,'Command: reload all scripts'),(622,'Command: reload all spell'),(623,'Command: reload areatrigger_involvedrelation'),(624,'Command: reload areatrigger_tavern'),(625,'Command: reload areatrigger_teleport'),(626,'Command: reload auctions'),(627,'Command: reload autobroadcast'),(628,'Command: reload command'),(629,'Command: reload conditions'),(630,'Command: reload config'),(631,'Command: reload battleground_template'),(632, 'Command: .mutehistory'),(633,'Command: reload creature_linked_respawn'),(634,'Command: reload creature_loot_template'),(635,'Command: reload creature_onkill_reputation'),(636,'Command: reload creature_questender'),(637,'Command: reload creature_queststarter'),(638,'Command: reload creature_summon_groups'),(639,'Command: reload creature_template'),(640,'Command: reload creature_text'),(641,'Command: reload disables'),(642,'Command: reload disenchant_loot_template'),(643,'Command: reload event_scripts'),(644,'Command: reload fishing_loot_template'),(645,'Command: reload game_graveyard_zone'),(646,'Command: reload game_tele'),(647,'Command: reload gameobject_questender'),(648,'Command: reload gameobject_loot_template'),(649,'Command: reload gameobject_queststarter'),(650,'Command: reload gm_tickets'),(651,'Command: reload gossip_menu'),(652,'Command: reload gossip_menu_option'),(653,'Command: reload item_enchantment_template'),(654,'Command: reload item_loot_template'),(655,'Command: reload item_set_names'),(656,'Command: reload lfg_dungeon_rewards'),(657,'Command: reload locales_achievement_reward'),(658,'Command: reload locales_creature'),(659,'Command: reload locales_creature_text'),(660,'Command: reload locales_gameobject'),(661,'Command: reload locales_gossip_menu_option'),(662,'Command: reload locales_item'),(663,'Command: reload locales_item_set_name'),(664,'Command: reload locales_npc_text'),(665,'Command: reload locales_page_text'),(666,'Command: reload locales_points_of_interest'),(667,'Command: reload locales_quest'),(668,'Command: reload mail_level_reward'),(669,'Command: reload mail_loot_template'),(670,'Command: reload milling_loot_template'),(671,'Command: reload npc_spellclick_spells'),(672,'Command: reload npc_trainer'),(673,'Command: reload npc_vendor'),(674,'Command: reload page_text'),(675,'Command: reload pickpocketing_loot_template'),(676,'Command: reload points_of_interest'),(677,'Command: reload prospecting_loot_template'),(678,'Command: reload quest_poi'),(679,'Command: reload quest_template'),(680,'Command: reload rbac'),(681,'Command: reload reference_loot_template'),(682,'Command: reload reserved_name'),(683,'Command: reload reputation_reward_rate'),(684,'Command: reload reputation_spillover_template'),(685,'Command: reload skill_discovery_template'),(686,'Command: reload skill_extra_item_template'),(687,'Command: reload skill_fishing_base_level'),(688,'Command: reload skinning_loot_template'),(689,'Command: reload smart_scripts'),(690,'Command: reload spell_required'),(691,'Command: reload spell_area'),(692,'Command: reload spell_bonus_data'),(693,'Command: reload spell_group'),(694,'Command: reload spell_learn_spell'),(695,'Command: reload spell_loot_template'),(696,'Command: reload spell_linked_spell'),(697,'Command: reload spell_pet_auras'),(698,'Command: reload spell_proc_event'),(699,'Command: reload spell_proc'),(700,'Command: reload spell_scripts'),(701,'Command: reload spell_target_position'),(702,'Command: reload spell_threats'),(703,'Command: reload spell_group_stack_rules'),(704,'Command: reload trinity_string'),(705,'Command: reload warden_action'),(706,'Command: reload waypoint_scripts'),(707,'Command: reload waypoint_data'),(708,'Command: reload vehicle_accessory'),(709,'Command: reload vehicle_template_accessory'),(710,'Command: reset'),(711,'Command: reset achievements'),(712,'Command: reset honor'),(713,'Command: reset level'),(714,'Command: reset spells'),(715,'Command: reset stats'),(716,'Command: reset talents'),(717,'Command: reset all'),(718,'Command: server'),(719,'Command: server corpses'),(720,'Command: server exit'),(721,'Command: server idlerestart'),(722,'Command: server idlerestart cancel'),(723,'Command: server idleshutdown'),(724,'Command: server idleshutdown cancel'),(725,'Command: server info'),(726,'Command: server plimit'),(727,'Command: server restart'),(728,'Command: server restart cancel'),(729,'Command: server set'),(730,'Command: server set closed'),(731,'Command: server set difftime'),(732,'Command: server set loglevel'),(733,'Command: server set motd'),(734,'Command: server shutdown'),(735,'Command: server shutdown cancel'),(736,'Command: server motd'),(737,'Command: tele'),(738,'Command: tele add'),(739,'Command: tele del'),(740,'Command: tele name'),(741,'Command: tele group'),(742,'Command: ticket'),(743,'Command: ticket assign'),(744,'Command: ticket close'),(745,'Command: ticket closedlist'),(746,'Command: ticket comment'),(747,'Command: ticket complete'),(748,'Command: ticket delete'),(749,'Command: ticket escalate'),(750,'Command: ticket escalatedlist'),(751,'Command: ticket list'),(752,'Command: ticket onlinelist'),(753,'Command: ticket reset'),(754,'Command: ticket response'),(755,'Command: ticket response append'),(756,'Command: ticket response appendln'),(757,'Command: ticket togglesystem'),(758,'Command: ticket unassign'),(759,'Command: ticket viewid'),(760,'Command: ticket viewname'),(761,'Command: titles'),(762,'Command: titles add'),(763,'Command: titles current'),(764,'Command: titles remove'),(765,'Command: titles set'),(766,'Command: titles set mask'),(767,'Command: wp'),(768,'Command: wp add'),(769,'Command: wp event'),(770,'Command: wp load'),(771,'Command: wp modify'),(772,'Command: wp unload'),(773,'Command: wp reload'),(774,'Command: wp show'),(777,'Command: mailbox'),(778,'Command: ahbot'),(779,'Command: ahbot items'),(780,'Command: ahbot items gray'),(781,'Command: ahbot items white'),(782,'Command: ahbot items green'),(783,'Command: ahbot items blue'),(784,'Command: ahbot items purple'),(785,'Command: ahbot items orange'),(786,'Command: ahbot items yellow'),(787,'Command: ahbot ratio'),(788,'Command: ahbot ratio alliance'),(789,'Command: ahbot ratio horde'),(790,'Command: ahbot ratio neutral'),(791,'Command: ahbot rebuild'),(792,'Command: ahbot reload'),(793,'Command: ahbot status'),(794,'Command: .guild info'); +INSERT INTO `rbac_permissions` VALUES (1,'Instant logout'),(2,'Skip Queue'),(3,'Join Normal Battleground'),(4,'Join Random Battleground'),(5,'Join Arenas'),(6,'Join Dungeon Finder'),(11,'Log GM trades'),(13,'Skip Instance required bosses check'),(14,'Skip character creation team mask check'),(15,'Skip character creation class mask check'),(16,'Skip character creation race mask check'),(17,'Skip character creation reserved name check'),(18,'Skip character creation heroic min level check'),(19,'Skip needed requirements to use channel check'),(20,'Skip disable map check'),(21,'Skip reset talents when used more than allowed check'),(22,'Skip spam chat check'),(23,'Skip over-speed ping check'),(24,'Two side faction characters on the same account'),(25,'Allow say chat between factions'),(26,'Allow channel chat between factions'),(27,'Two side mail interaction'),(28,'See two side who list'),(29,'Add friends of other faction'),(30,'Save character without delay with .save command'),(31,'Use params with .unstuck command'),(32,'Can be assigned tickets with .assign ticket command'),(33,'Notify if a command was not found'),(34,'Check if should appear in list using .gm ingame command'),(35,'See all security levels with who command'),(36,'Filter whispers'),(37,'Use staff badge in chat'),(38,'Resurrect with full Health Points'),(39,'Restore saved gm setting states'),(40,'Allows to add a gm to friend list'),(41,'Use Config option START_GM_LEVEL to assign new character level'),(42,'Allows to use CMSG_WORLD_TELEPORT opcode'),(43,'Allows to use CMSG_WHOIS opcode'),(44,'Receive global GM messages/texts'),(45,'Join channels without announce'),(46,'Change channel settings without being channel moderator'),(47,'Enables lower security than target check'),(48,'Enable IP, Last Login and EMail output in pinfo'),(49,'Forces to enter the email for confirmation on password change'),(50,'Allow user to check his own email with .account'),(192,'Role: Sec Level Administrator'),(193,'Role: Sec Level Gamemaster'),(194,'Role: Sec Level Moderator'),(195,'Role: Sec Level Player'),(196,'Role: Administrator Commands'),(197,'Role: Gamemaster Commands'),(198,'Role: Moderator Commands'),(199,'Role: Player Commands'),(200,'Command: rbac'),(201,'Command: rbac account'),(202,'Command: rbac account list'),(203,'Command: rbac account grant'),(204,'Command: rbac account deny'),(205,'Command: rbac account revoke'),(206,'Command: rbac list'),(207,'Command: battlenetaccount'),(208,'Command: battlenetaccount create'),(209,'Command: battlenetaccount lock country'),(210,'Command: battlenetaccount lock ip'),(211,'Command: battlenetaccount password'),(212,'Command: battlenetaccount set'),(213,'Command: battlenetaccount set password'),(217,'Command: account'),(218,'Command: account addon'),(219,'Command: account create'),(220,'Command: account delete'),(221,'Command: account lock'),(222,'Command: account lock country'),(223,'Command: account lock ip'),(224,'Command: account onlinelist'),(225,'Command: account password'),(226,'Command: account set'),(227,'Command: account set addon'),(228,'Command: account set gmlevel'),(229,'Command: account set password'),(230,'Command: achievement'),(231,'Command: achievement add'),(232,'Command: arena'),(233,'Command: arena captain'),(234,'Command: arena create'),(235,'Command: arena disband'),(236,'Command: arena info'),(237,'Command: arena lookup'),(238,'Command: arena rename'),(239,'Command: ban'),(240,'Command: ban account'),(241,'Command: ban character'),(242,'Command: ban ip'),(243,'Command: ban playeraccount'),(244,'Command: baninfo'),(245,'Command: baninfo account'),(246,'Command: baninfo character'),(247,'Command: baninfo ip'),(248,'Command: banlist'),(249,'Command: banlist account'),(250,'Command: banlist character'),(251,'Command: banlist ip'),(252,'Command: unban'),(253,'Command: unban account'),(254,'Command: unban character'),(255,'Command: unban ip'),(256,'Command: unban playeraccount'),(257,'Command: bf'),(258,'Command: bf start'),(259,'Command: bf stop'),(260,'Command: bf switch'),(261,'Command: bf timer'),(262,'Command: bf enable'),(263,'Command: account email'),(264,'Command: account set sec'),(265,'Command: account set sec email'),(266,'Command: account set sec regmail'),(267,'Command: cast'),(268,'Command: cast back'),(269,'Command: cast dist'),(270,'Command: cast self'),(271,'Command: cast target'),(272,'Command: cast dest'),(273,'Command: character'),(274,'Command: character customize'),(275,'Command: character changefaction'),(276,'Command: character changerace'),(277,'Command: character deleted'),(279,'Command: character deleted list'),(280,'Command: character deleted restore'),(283,'Command: character level'),(284,'Command: character rename'),(285,'Command: character reputation'),(286,'Command: character titles'),(287,'Command: levelup'),(288,'Command: pdump'),(289,'Command: pdump load'),(290,'Command: pdump write'),(291,'Command: cheat'),(292,'Command: cheat casttime'),(293,'Command: cheat cooldown'),(294,'Command: cheat explore'),(295,'Command: cheat god'),(296,'Command: cheat power'),(297,'Command: cheat status'),(298,'Command: cheat taxi'),(299,'Command: cheat waterwalk'),(300,'Command: debug'),(301,'Command: debug anim'),(302,'Command: debug areatriggers'),(303,'Command: debug arena'),(304,'Command: debug bg'),(305,'Command: debug entervehicle'),(306,'Command: debug getitemstate'),(307,'Command: debug getitemvalue'),(308,'Command: debug getvalue'),(309,'Command: debug hostil'),(310,'Command: debug itemexpire'),(311,'Command: debug lootrecipient'),(312,'Command: debug los'),(313,'Command: debug mod32value'),(314,'Command: debug moveflags'),(315,'Command: debug play'),(316,'Command: debug play cinematics'),(317,'Command: debug play movie'),(318,'Command: debug play sound'),(319,'Command: debug send'),(320,'Command: debug send buyerror'),(321,'Command: debug send channelnotify'),(322,'Command: debug send chatmessage'),(323,'Command: debug send equiperror'),(324,'Command: debug send largepacket'),(325,'Command: debug send opcode'),(326,'Command: debug send qinvalidmsg'),(327,'Command: debug send qpartymsg'),(328,'Command: debug send sellerror'),(329,'Command: debug send setphaseshift'),(330,'Command: debug send spellfail'),(331,'Command: debug setaurastate'),(332,'Command: debug setbit'),(333,'Command: debug setitemvalue'),(334,'Command: debug setvalue'),(335,'Command: debug setvid'),(336,'Command: debug spawnvehicle'),(337,'Command: debug threat'),(338,'Command: debug update'),(339,'Command: debug uws'),(340,'Command: wpgps'),(341,'Command: deserter'),(342,'Command: deserter bg'),(343,'Command: deserter bg add'),(344,'Command: deserter bg remove'),(345,'Command: deserter instance'),(346,'Command: deserter instance add'),(347,'Command: deserter instance remove'),(348,'Command: disable'),(349,'Command: disable add'),(350,'Command: disable add achievement_criteria'),(351,'Command: disable add battleground'),(352,'Command: disable add map'),(353,'Command: disable add mmap'),(354,'Command: disable add outdoorpvp'),(355,'Command: disable add quest'),(356,'Command: disable add spell'),(357,'Command: disable add vmap'),(358,'Command: disable remove'),(359,'Command: disable remove achievement_criteria'),(360,'Command: disable remove battleground'),(361,'Command: disable remove map'),(362,'Command: disable remove mmap'),(363,'Command: disable remove outdoorpvp'),(364,'Command: disable remove quest'),(365,'Command: disable remove spell'),(366,'Command: disable remove vmap'),(367,'Command: event'),(368,'Command: event activelist'),(369,'Command: event start'),(370,'Command: event stop'),(371,'Command: gm'),(372,'Command: gm chat'),(373,'Command: gm fly'),(374,'Command: gm ingame'),(375,'Command: gm list'),(376,'Command: gm visible'),(377,'Command: go'),(378,'Command: go creature'),(379,'Command: go graveyard'),(380,'Command: go grid'),(381,'Command: go object'),(382,'Command: go taxinode'),(383,'Command: go ticket'),(384,'Command: go trigger'),(385,'Command: go xyz'),(386,'Command: go zonexy'),(387,'Command: gobject'),(388,'Command: gobject activate'),(389,'Command: gobject add'),(390,'Command: gobject add temp'),(391,'Command: gobject delete'),(392,'Command: gobject info'),(393,'Command: gobject move'),(394,'Command: gobject near'),(395,'Command: gobject set'),(396,'Command: gobject set phase'),(397,'Command: gobject set state'),(398,'Command: gobject target'),(399,'Command: gobject turn'),(400,'debug transport'),(401,'Command: guild'),(402,'Command: guild create'),(403,'Command: guild delete'),(404,'Command: guild invite'),(405,'Command: guild uninvite'),(406,'Command: guild rank'),(407,'Command: guild rename'),(408,'Command: honor'),(409,'Command: honor add'),(410,'Command: honor add kill'),(411,'Command: honor update'),(412,'Command: instance'),(413,'Command: instance listbinds'),(414,'Command: instance unbind'),(415,'Command: instance stats'),(416,'Command: instance savedata'),(417,'Command: learn'),(418,'Command: learn all'),(419,'Command: learn all my'),(420,'Command: learn all my class'),(421,'Command: learn all my pettalents'),(422,'Command: learn all my spells'),(423,'Command: learn all my talents'),(424,'Command: learn all gm'),(425,'Command: learn all crafts'),(426,'Command: learn all default'),(427,'Command: learn all lang'),(428,'Command: learn all recipes'),(429,'Command: unlearn'),(430,'Command: lfg'),(431,'Command: lfg player'),(432,'Command: lfg group'),(433,'Command: lfg queue'),(434,'Command: lfg clean'),(435,'Command: lfg options'),(436,'Command: list'),(437,'Command: list creature'),(438,'Command: list item'),(439,'Command: list object'),(440,'Command: list auras'),(441,'Command: list mail'),(442,'Command: lookup'),(443,'Command: lookup area'),(444,'Command: lookup creature'),(445,'Command: lookup event'),(446,'Command: lookup faction'),(447,'Command: lookup item'),(448,'Command: lookup itemset'),(449,'Command: lookup object'),(450,'Command: lookup quest'),(451,'Command: lookup player'),(452,'Command: lookup player ip'),(453,'Command: lookup player account'),(454,'Command: lookup player email'),(455,'Command: lookup skill'),(456,'Command: lookup spell'),(457,'Command: lookup spell id'),(458,'Command: lookup taxinode'),(459,'Command: lookup tele'),(460,'Command: lookup title'),(461,'Command: lookup map'),(462,'Command: announce'),(463,'Command: channel'),(464,'Command: channel set'),(465,'Command: channel set ownership'),(466,'Command: gmannounce'),(467,'Command: gmnameannounce'),(468,'Command: gmnotify'),(469,'Command: nameannounce'),(470,'Command: notify'),(471,'Command: whispers'),(472,'Command: group'),(473,'Command: group leader'),(474,'Command: group disband'),(475,'Command: group remove'),(476,'Command: group join'),(477,'Command: group list'),(478,'Command: group summon'),(479,'Command: pet'),(480,'Command: pet create'),(481,'Command: pet learn'),(482,'Command: pet unlearn'),(483,'Command: send'),(484,'Command: send items'),(485,'Command: send mail'),(486,'Command: send message'),(487,'Command: send money'),(488,'Command: additem'),(489,'Command: additemset'),(490,'Command: appear'),(491,'Command: aura'),(492,'Command: bank'),(493,'Command: bindsight'),(494,'Command: combatstop'),(495,'Command: cometome'),(496,'Command: commands'),(497,'Command: cooldown'),(498,'Command: damage'),(499,'Command: dev'),(500,'Command: die'),(501,'Command: dismount'),(502,'Command: distance'),(503,'Command: flusharenapoints'),(504,'Command: freeze'),(505,'Command: gps'),(506,'Command: guid'),(507,'Command: help'),(508,'Command: hidearea'),(509,'Command: itemmove'),(510,'Command: kick'),(511,'Command: linkgrave'),(512,'Command: listfreeze'),(513,'Command: maxskill'),(514,'Command: movegens'),(515,'Command: mute'),(516,'Command: neargrave'),(517,'Command: pinfo'),(518,'Command: playall'),(519,'Command: possess'),(520,'Command: recall'),(521,'Command: repairitems'),(522,'Command: respawn'),(523,'Command: revive'),(524,'Command: saveall'),(525,'Command: save'),(526,'Command: setskill'),(527,'Command: showarea'),(528,'Command: summon'),(529,'Command: unaura'),(530,'Command: unbindsight'),(531,'Command: unfreeze'),(532,'Command: unmute'),(533,'Command: unpossess'),(534,'Command: unstuck'),(535,'Command: wchange'),(536,'Command: mmap'),(537,'Command: mmap loadedtiles'),(538,'Command: mmap loc'),(539,'Command: mmap path'),(540,'Command: mmap stats'),(541,'Command: mmap testarea'),(542,'Command: morph'),(543,'Command: demorph'),(544,'Command: modify'),(545,'Command: modify arenapoints'),(546,'Command: modify bit'),(547,'Command: modify drunk'),(548,'Command: modify energy'),(549,'Command: modify faction'),(550,'Command: modify gender'),(551,'Command: modify honor'),(552,'Command: modify hp'),(553,'Command: modify mana'),(554,'Command: modify money'),(555,'Command: modify mount'),(556,'Command: modify phase'),(557,'Command: modify rage'),(558,'Command: modify reputation'),(559,'Command: modify runicpower'),(560,'Command: modify scale'),(561,'Command: modify speed'),(562,'Command: modify speed all'),(563,'Command: modify speed backwalk'),(564,'Command: modify speed fly'),(565,'Command: modify speed walk'),(566,'Command: modify speed swim'),(567,'Command: modify spell'),(568,'Command: modify standstate'),(569,'Command: modify talentpoints'),(570,'Command: npc'),(571,'Command: npc add'),(572,'Command: npc add formation'),(573,'Command: npc add item'),(574,'Command: npc add move'),(575,'Command: npc add temp'),(576,'Command: npc add delete'),(577,'Command: npc add delete item'),(578,'Command: npc add follow'),(579,'Command: npc add follow stop'),(580,'Command: npc set'),(581,'Command: npc set allowmove'),(582,'Command: npc set entry'),(583,'Command: npc set factionid'),(584,'Command: npc set flag'),(585,'Command: npc set level'),(586,'Command: npc set link'),(587,'Command: npc set model'),(588,'Command: npc set movetype'),(589,'Command: npc set phase'),(590,'Command: npc set spawndist'),(591,'Command: npc set spawntime'),(592,'Command: npc set data'),(593,'Command: npc info'),(594,'Command: npc near'),(595,'Command: npc move'),(596,'Command: npc playemote'),(597,'Command: npc say'),(598,'Command: npc textemote'),(599,'Command: npc whisper'),(600,'Command: npc yell'),(601,'Command: npc tame'),(602,'Command: quest'),(603,'Command: quest add'),(604,'Command: quest complete'),(605,'Command: quest remove'),(606,'Command: quest reward'),(607,'Command: reload'),(608,'Command: reload access_requirement'),(609,'Command: reload achievement_criteria_data'),(610,'Command: reload achievement_reward'),(611,'Command: reload all'),(612,'Command: reload all achievement'),(613,'Command: reload all area'),(614,'Command: broadcast_text'),(615,'Command: reload all gossips'),(616,'Command: reload all item'),(617,'Command: reload all locales'),(618,'Command: reload all loot'),(619,'Command: reload all npc'),(620,'Command: reload all quest'),(621,'Command: reload all scripts'),(622,'Command: reload all spell'),(623,'Command: reload areatrigger_involvedrelation'),(624,'Command: reload areatrigger_tavern'),(625,'Command: reload areatrigger_teleport'),(626,'Command: reload auctions'),(627,'Command: reload autobroadcast'),(628,'Command: reload command'),(629,'Command: reload conditions'),(630,'Command: reload config'),(631,'Command: reload battleground_template'),(632, 'Command: .mutehistory'),(633,'Command: reload creature_linked_respawn'),(634,'Command: reload creature_loot_template'),(635,'Command: reload creature_onkill_reputation'),(636,'Command: reload creature_questender'),(637,'Command: reload creature_queststarter'),(638,'Command: reload creature_summon_groups'),(639,'Command: reload creature_template'),(640,'Command: reload creature_text'),(641,'Command: reload disables'),(642,'Command: reload disenchant_loot_template'),(643,'Command: reload event_scripts'),(644,'Command: reload fishing_loot_template'),(645,'Command: reload game_graveyard_zone'),(646,'Command: reload game_tele'),(647,'Command: reload gameobject_questender'),(648,'Command: reload gameobject_loot_template'),(649,'Command: reload gameobject_queststarter'),(650,'Command: reload gm_tickets'),(651,'Command: reload gossip_menu'),(652,'Command: reload gossip_menu_option'),(653,'Command: reload item_enchantment_template'),(654,'Command: reload item_loot_template'),(655,'Command: reload item_set_names'),(656,'Command: reload lfg_dungeon_rewards'),(657,'Command: reload locales_achievement_reward'),(658,'Command: reload locales_creature'),(659,'Command: reload locales_creature_text'),(660,'Command: reload locales_gameobject'),(661,'Command: reload locales_gossip_menu_option'),(662,'Command: reload locales_item'),(663,'Command: reload locales_item_set_name'),(664,'Command: reload locales_npc_text'),(665,'Command: reload locales_page_text'),(666,'Command: reload locales_points_of_interest'),(667,'Command: reload locales_quest'),(668,'Command: reload mail_level_reward'),(669,'Command: reload mail_loot_template'),(670,'Command: reload milling_loot_template'),(671,'Command: reload npc_spellclick_spells'),(672,'Command: reload npc_trainer'),(673,'Command: reload npc_vendor'),(674,'Command: reload page_text'),(675,'Command: reload pickpocketing_loot_template'),(676,'Command: reload points_of_interest'),(677,'Command: reload prospecting_loot_template'),(678,'Command: reload quest_poi'),(679,'Command: reload quest_template'),(680,'Command: reload rbac'),(681,'Command: reload reference_loot_template'),(682,'Command: reload reserved_name'),(683,'Command: reload reputation_reward_rate'),(684,'Command: reload reputation_spillover_template'),(685,'Command: reload skill_discovery_template'),(686,'Command: reload skill_extra_item_template'),(687,'Command: reload skill_fishing_base_level'),(688,'Command: reload skinning_loot_template'),(689,'Command: reload smart_scripts'),(690,'Command: reload spell_required'),(691,'Command: reload spell_area'),(692,'Command: reload spell_bonus_data'),(693,'Command: reload spell_group'),(694,'Command: reload spell_learn_spell'),(695,'Command: reload spell_loot_template'),(696,'Command: reload spell_linked_spell'),(697,'Command: reload spell_pet_auras'),(698,'Command: reload spell_proc_event'),(699,'Command: reload spell_proc'),(700,'Command: reload spell_scripts'),(701,'Command: reload spell_target_position'),(702,'Command: reload spell_threats'),(703,'Command: reload spell_group_stack_rules'),(704,'Command: reload trinity_string'),(705,'Command: reload warden_action'),(706,'Command: reload waypoint_scripts'),(707,'Command: reload waypoint_data'),(708,'Command: reload vehicle_accessory'),(709,'Command: reload vehicle_template_accessory'),(710,'Command: reset'),(711,'Command: reset achievements'),(712,'Command: reset honor'),(713,'Command: reset level'),(714,'Command: reset spells'),(715,'Command: reset stats'),(716,'Command: reset talents'),(717,'Command: reset all'),(718,'Command: server'),(719,'Command: server corpses'),(720,'Command: server exit'),(721,'Command: server idlerestart'),(722,'Command: server idlerestart cancel'),(723,'Command: server idleshutdown'),(724,'Command: server idleshutdown cancel'),(725,'Command: server info'),(726,'Command: server plimit'),(727,'Command: server restart'),(728,'Command: server restart cancel'),(729,'Command: server set'),(730,'Command: server set closed'),(731,'Command: server set difftime'),(732,'Command: server set loglevel'),(733,'Command: server set motd'),(734,'Command: server shutdown'),(735,'Command: server shutdown cancel'),(736,'Command: server motd'),(737,'Command: tele'),(738,'Command: tele add'),(739,'Command: tele del'),(740,'Command: tele name'),(741,'Command: tele group'),(742,'Command: ticket'),(743,'Command: ticket assign'),(744,'Command: ticket close'),(745,'Command: ticket closedlist'),(746,'Command: ticket comment'),(747,'Command: ticket complete'),(748,'Command: ticket delete'),(749,'Command: ticket escalate'),(750,'Command: ticket escalatedlist'),(751,'Command: ticket list'),(752,'Command: ticket onlinelist'),(753,'Command: ticket reset'),(754,'Command: ticket response'),(755,'Command: ticket response append'),(756,'Command: ticket response appendln'),(757,'Command: ticket togglesystem'),(758,'Command: ticket unassign'),(759,'Command: ticket viewid'),(760,'Command: ticket viewname'),(761,'Command: titles'),(762,'Command: titles add'),(763,'Command: titles current'),(764,'Command: titles remove'),(765,'Command: titles set'),(766,'Command: titles set mask'),(767,'Command: wp'),(768,'Command: wp add'),(769,'Command: wp event'),(770,'Command: wp load'),(771,'Command: wp modify'),(772,'Command: wp unload'),(773,'Command: wp reload'),(774,'Command: wp show'),(777,'Command: mailbox'),(778,'Command: ahbot'),(779,'Command: ahbot items'),(780,'Command: ahbot items gray'),(781,'Command: ahbot items white'),(782,'Command: ahbot items green'),(783,'Command: ahbot items blue'),(784,'Command: ahbot items purple'),(785,'Command: ahbot items orange'),(786,'Command: ahbot items yellow'),(787,'Command: ahbot ratio'),(788,'Command: ahbot ratio alliance'),(789,'Command: ahbot ratio horde'),(790,'Command: ahbot ratio neutral'),(791,'Command: ahbot rebuild'),(792,'Command: ahbot reload'),(793,'Command: ahbot status'),(794,'Command: .guild info'),(835,'Command: debug loadcells'); /*!40000 ALTER TABLE `rbac_permissions` ENABLE KEYS */; UNLOCK TABLES; diff --git a/sql/updates/world/2015_09_15_xx_world.sql b/sql/updates/world/2015_09_15_xx_world.sql new file mode 100644 index 00000000000..8a2272044a3 --- /dev/null +++ b/sql/updates/world/2015_09_15_xx_world.sql @@ -0,0 +1,147 @@ +-- RewardItem(s) and RewardAmount(s) [4x2 fields] +ALTER TABLE `quest_template` + CHANGE COLUMN `RewardAmount1` `RewardAmount1` SMALLINT(5) UNSIGNED NOT NULL DEFAULT '0' AFTER `RewardItem1`, + CHANGE COLUMN `RewardAmount2` `RewardAmount2` SMALLINT(5) UNSIGNED NOT NULL DEFAULT '0' AFTER `RewardItem2`, + CHANGE COLUMN `RewardAmount3` `RewardAmount3` SMALLINT(5) UNSIGNED NOT NULL DEFAULT '0' AFTER `RewardItem3`, + CHANGE COLUMN `RewardAmount4` `RewardAmount4` SMALLINT(5) UNSIGNED NOT NULL DEFAULT '0' AFTER `RewardItem4`; + +-- RewardChoiceItemID(s) and RewardChoiceItemQuantity(s) [6x2 fields] +ALTER TABLE `quest_template` + CHANGE COLUMN `RewardChoiceItemQuantity1` `RewardChoiceItemQuantity1` SMALLINT(5) UNSIGNED NOT NULL DEFAULT '0' AFTER `RewardChoiceItemID1`, + CHANGE COLUMN `RewardChoiceItemQuantity2` `RewardChoiceItemQuantity2` SMALLINT(5) UNSIGNED NOT NULL DEFAULT '0' AFTER `RewardChoiceItemID2`, + CHANGE COLUMN `RewardChoiceItemQuantity3` `RewardChoiceItemQuantity3` SMALLINT(5) UNSIGNED NOT NULL DEFAULT '0' AFTER `RewardChoiceItemID3`, + CHANGE COLUMN `RewardChoiceItemQuantity4` `RewardChoiceItemQuantity4` SMALLINT(5) UNSIGNED NOT NULL DEFAULT '0' AFTER `RewardChoiceItemID4`, + CHANGE COLUMN `RewardChoiceItemQuantity5` `RewardChoiceItemQuantity5` SMALLINT(5) UNSIGNED NOT NULL DEFAULT '0' AFTER `RewardChoiceItemID5`, + CHANGE COLUMN `RewardChoiceItemQuantity6` `RewardChoiceItemQuantity6` SMALLINT(5) UNSIGNED NOT NULL DEFAULT '0' AFTER `RewardChoiceItemID6`; + +-- RewardFactionID(s), RewardFactionValue(s) and RewardFactionOverride(s) [5x3 fields] +ALTER TABLE `quest_template` + CHANGE COLUMN `RewardFactionValue1` `RewardFactionValue1` MEDIUMINT(8) NOT NULL DEFAULT '0' AFTER `RewardFactionID1`, + CHANGE COLUMN `RewardFactionOverride1` `RewardFactionOverride1` MEDIUMINT(8) NOT NULL DEFAULT '0' AFTER `RewardFactionValue1`, + CHANGE COLUMN `RewardFactionValue2` `RewardFactionValue2` MEDIUMINT(8) NOT NULL DEFAULT '0' AFTER `RewardFactionID2`, + CHANGE COLUMN `RewardFactionOverride2` `RewardFactionOverride2` MEDIUMINT(8) NOT NULL DEFAULT '0' AFTER `RewardFactionValue2`, + CHANGE COLUMN `RewardFactionValue3` `RewardFactionValue3` MEDIUMINT(8) NOT NULL DEFAULT '0' AFTER `RewardFactionID3`, + CHANGE COLUMN `RewardFactionOverride3` `RewardFactionOverride3` MEDIUMINT(8) NOT NULL DEFAULT '0' AFTER `RewardFactionValue3`, + CHANGE COLUMN `RewardFactionValue4` `RewardFactionValue4` MEDIUMINT(8) NOT NULL DEFAULT '0' AFTER `RewardFactionID4`, + CHANGE COLUMN `RewardFactionOverride4` `RewardFactionOverride4` MEDIUMINT(8) NOT NULL DEFAULT '0' AFTER `RewardFactionValue4`, + CHANGE COLUMN `RewardFactionValue5` `RewardFactionValue5` MEDIUMINT(8) NOT NULL DEFAULT '0' AFTER `RewardFactionID5`, + CHANGE COLUMN `RewardFactionOverride5` `RewardFactionOverride5` MEDIUMINT(8) NOT NULL DEFAULT '0' AFTER `RewardFactionValue5`; + + -- quest_details +DROP TABLE IF EXISTS `quest_details`; +CREATE TABLE `quest_details` ( + `ID` MEDIUMINT(8) UNSIGNED NOT NULL DEFAULT '0', + `Emote1` SMALLINT(5) UNSIGNED NOT NULL DEFAULT '0', + `Emote2` SMALLINT(5) UNSIGNED NOT NULL DEFAULT '0', + `Emote3` SMALLINT(5) UNSIGNED NOT NULL DEFAULT '0', + `Emote4` SMALLINT(5) UNSIGNED NOT NULL DEFAULT '0', + `EmoteDelay1` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `EmoteDelay2` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `EmoteDelay3` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `EmoteDelay4` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `VerifiedBuild` SMALLINT(5) NOT NULL DEFAULT '0', + PRIMARY KEY (`ID`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +INSERT INTO `quest_details` (`ID`, `Emote1`, `Emote2`, `Emote3`, `Emote4`, `EmoteDelay1`, `EmoteDelay2`, `EmoteDelay3`, `EmoteDelay4`, `VerifiedBuild`) +SELECT `ID`, `DetailsEmote1`, `DetailsEmote2`, `DetailsEmote3`, `DetailsEmote4`, `DetailsEmoteDelay1`, `DetailsEmoteDelay2`, `DetailsEmoteDelay3`, `DetailsEmoteDelay4`, `VerifiedBuild` FROM `quest_template` +WHERE `DetailsEmote1`!=0 OR `DetailsEmote2`!=0 OR `DetailsEmote3`!=0 OR `DetailsEmote4`!=0 OR `DetailsEmoteDelay1`!=0 OR `DetailsEmoteDelay2`!=0 OR `DetailsEmoteDelay3`!=0 OR `DetailsEmoteDelay4`!=0; + + +-- quest_request_items +DROP TABLE IF EXISTS `quest_request_items`; +CREATE TABLE `quest_request_items` ( + `ID` MEDIUMINT(8) UNSIGNED NOT NULL DEFAULT '0', + `EmoteOnComplete` SMALLINT(5) UNSIGNED NOT NULL DEFAULT '0', + `EmoteOnIncomplete` SMALLINT(5) UNSIGNED NOT NULL DEFAULT '0', + `CompletionText` TEXT, + `VerifiedBuild` SMALLINT(5) NOT NULL DEFAULT '0', + PRIMARY KEY (`ID`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +INSERT INTO `quest_request_items` (`ID`, `EmoteOnComplete`, `EmoteOnIncomplete`, `CompletionText`, `VerifiedBuild`) +SELECT `ID`, `EmoteOnComplete`, `EmoteOnIncomplete`, `RequestItemsText`, `VerifiedBuild` FROM `quest_template` +WHERE `EmoteOnComplete`!=0 OR `EmoteOnIncomplete`!=0 OR `RequestItemsText`!=''; + + +-- quest_offer_reward +DROP TABLE IF EXISTS `quest_offer_reward`; +CREATE TABLE `quest_offer_reward` ( + `ID` MEDIUMINT(8) UNSIGNED NOT NULL DEFAULT '0', + `Emote1` SMALLINT(5) UNSIGNED NOT NULL DEFAULT '0', + `Emote2` SMALLINT(5) UNSIGNED NOT NULL DEFAULT '0', + `Emote3` SMALLINT(5) UNSIGNED NOT NULL DEFAULT '0', + `Emote4` SMALLINT(5) UNSIGNED NOT NULL DEFAULT '0', + `EmoteDelay1` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `EmoteDelay2` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `EmoteDelay3` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `EmoteDelay4` INT(10) UNSIGNED NOT NULL DEFAULT '0', + `RewardText` TEXT, + `VerifiedBuild` SMALLINT(5) NOT NULL DEFAULT '0', + PRIMARY KEY (`ID`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +INSERT INTO `quest_offer_reward` (`ID`, `Emote1`, `Emote2`, `Emote3`, `Emote4`, `EmoteDelay1`, `EmoteDelay2`, `EmoteDelay3`, `EmoteDelay4`, `RewardText`, `VerifiedBuild`) +SELECT `ID`, `OfferRewardEmote1`, `OfferRewardEmote2`, `OfferRewardEmote3`, `OfferRewardEmote4`, `OfferRewardEmoteDelay1`, `OfferRewardEmoteDelay2`, `OfferRewardEmoteDelay3`, `OfferRewardEmoteDelay4`, `OfferRewardText`, `VerifiedBuild` FROM `quest_template` +WHERE `OfferRewardEmote1`!=0 OR `OfferRewardEmote2`!=0 OR `OfferRewardEmote3`!=0 OR `OfferRewardEmote4`!=0 OR `OfferRewardEmoteDelay1`!=0 OR `OfferRewardEmoteDelay2`!=0 OR `OfferRewardEmoteDelay3`!=0 OR `OfferRewardEmoteDelay4`!=0 OR `OfferRewardText`!=''; + +-- delete old fields +ALTER TABLE `quest_template` + DROP `DetailsEmote1`, + DROP `DetailsEmote2`, + DROP `DetailsEmote3`, + DROP `DetailsEmote4`, + DROP `DetailsEmoteDelay1`, + DROP `DetailsEmoteDelay2`, + DROP `DetailsEmoteDelay3`, + DROP `DetailsEmoteDelay4`, + DROP `EmoteOnIncomplete`, + DROP `EmoteOnComplete`, + DROP `RequestItemsText`, + DROP `OfferRewardEmote1`, + DROP `OfferRewardEmote2`, + DROP `OfferRewardEmote3`, + DROP `OfferRewardEmote4`, + DROP `OfferRewardEmoteDelay1`, + DROP `OfferRewardEmoteDelay2`, + DROP `OfferRewardEmoteDelay3`, + DROP `OfferRewardEmoteDelay4`, + DROP `OfferRewardText`; + + +ALTER TABLE `quest_template` + CHANGE COLUMN `Method` `QuestType` TINYINT(3) UNSIGNED NOT NULL DEFAULT '2' AFTER `ID`, + CHANGE COLUMN `QuestType` `QuestInfoID` SMALLINT(5) UNSIGNED NOT NULL DEFAULT '0' AFTER `QuestSortID`; + + ALTER TABLE `quest_template` + CHANGE COLUMN `LimitTime` `TimeAllowed` INT(10) UNSIGNED NOT NULL DEFAULT '0' AFTER `PointOption`, + CHANGE COLUMN `RequiredRaces` `RequiredRaces` MEDIUMINT(8) UNSIGNED NOT NULL DEFAULT '0' AFTER `TimeAllowed`, + CHANGE COLUMN `NextQuestIdChain` `RewardNextQuest` MEDIUMINT(8) UNSIGNED NOT NULL DEFAULT '0' AFTER `RequiredFactionValue2`, + CHANGE COLUMN `RewardXPId` `RewardXPDifficulty` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0' AFTER `RewardNextQuest`, + CHANGE COLUMN `RewardOrRequiredMoney` `RewardMoney` INT(11) NOT NULL DEFAULT '0' AFTER `RewardXPDifficulty`, + CHANGE COLUMN `RewardMoneyMaxLevel` `RewardBonusMoney` INT(10) UNSIGNED NOT NULL DEFAULT '0' AFTER `RewardMoney`, + CHANGE COLUMN `RewardSpell` `RewardDisplaySpell` MEDIUMINT(8) UNSIGNED NOT NULL DEFAULT '0' AFTER `RewardBonusMoney`, + CHANGE COLUMN `RewardSpellCast` `RewardSpell` INT(11) NOT NULL DEFAULT '0' AFTER `RewardDisplaySpell`, + CHANGE COLUMN `RewardHonorMultiplier` `RewardKillHonor` FLOAT NOT NULL DEFAULT '0' AFTER `RewardHonor`, + CHANGE COLUMN `SourceItemId` `StartItem` MEDIUMINT(8) UNSIGNED NOT NULL DEFAULT '0' AFTER `RewardKillHonor`, + CHANGE COLUMN `RewardTitle` `RewardTitle` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0' AFTER `RewardChoiceItemQuantity6`, + CHANGE COLUMN `RewardTalents` `RewardTalents` TINYINT(3) UNSIGNED NOT NULL DEFAULT '0' AFTER `RewardTitle`, + CHANGE COLUMN `RewardArenaPoints` `RewardArenaPoints` SMALLINT(5) UNSIGNED NOT NULL DEFAULT '0' AFTER `RewardTalents`; +-- split needed to avoid import errors +ALTER TABLE `quest_template` + CHANGE COLUMN `PointMapId` `POIContinent` SMALLINT(5) UNSIGNED NOT NULL DEFAULT '0' AFTER `RewardChoiceItemQuantity6`, + CHANGE COLUMN `PointX` `POIx` FLOAT NOT NULL DEFAULT '0' AFTER `POIContinent`, + CHANGE COLUMN `PointY` `POIy` FLOAT NOT NULL DEFAULT '0' AFTER `POIx`, + CHANGE COLUMN `PointOption` `POIPriority` MEDIUMINT(8) UNSIGNED NOT NULL DEFAULT '0' AFTER `POIy`, + CHANGE COLUMN `EndText` `AreaDescription` TEXT NULL AFTER `QuestDescription`; + +ALTER TABLE `quest_template` + CHANGE COLUMN `RequiredRaces` `AllowableRaces` MEDIUMINT(8) UNSIGNED NOT NULL DEFAULT '0' AFTER `TimeAllowed`, + CHANGE COLUMN `RequiredSourceItemId1` `ItemDrop1` MEDIUMINT(8) UNSIGNED NOT NULL DEFAULT '0' AFTER `RewardAmount4`, + CHANGE COLUMN `RequiredSourceItemCount1` `ItemDropQuantity1` SMALLINT(5) UNSIGNED NOT NULL DEFAULT '0' AFTER `ItemDrop1`, + CHANGE COLUMN `RequiredSourceItemId2` `ItemDrop2` MEDIUMINT(8) UNSIGNED NOT NULL DEFAULT '0' AFTER `ItemDropQuantity1`, + CHANGE COLUMN `RequiredSourceItemCount2` `ItemDropQuantity2` SMALLINT(5) UNSIGNED NOT NULL DEFAULT '0' AFTER `ItemDrop2`, + CHANGE COLUMN `RequiredSourceItemId3` `ItemDrop3` MEDIUMINT(8) UNSIGNED NOT NULL DEFAULT '0' AFTER `ItemDropQuantity2`, + CHANGE COLUMN `RequiredSourceItemCount3` `ItemDropQuantity3` SMALLINT(5) UNSIGNED NOT NULL DEFAULT '0' AFTER `ItemDrop3`, + CHANGE COLUMN `RequiredSourceItemId4` `ItemDrop4` MEDIUMINT(8) UNSIGNED NOT NULL DEFAULT '0' AFTER `ItemDropQuantity3`, + CHANGE COLUMN `RequiredSourceItemCount4` `ItemDropQuantity4` SMALLINT(5) UNSIGNED NOT NULL DEFAULT '0' AFTER `ItemDrop4`; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e6d31ebbaef..914ad31ad06 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -9,9 +9,12 @@ # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. add_subdirectory(genrev) -add_subdirectory(server) +add_subdirectory(common) + +if(SERVERS) + add_subdirectory(server) +endif(SERVERS) if(TOOLS) add_subdirectory(tools) endif(TOOLS) - diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt new file mode 100644 index 00000000000..2339399e022 --- /dev/null +++ b/src/common/CMakeLists.txt @@ -0,0 +1,89 @@ +# Copyright (C) 2008-2015 TrinityCore +# +# This file is free software; as a special exception the author gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +if( USE_COREPCH ) + include_directories(${CMAKE_CURRENT_BINARY_DIR}) +endif() + +file(GLOB_RECURSE sources_Common Common.cpp Common.h) +file(GLOB_RECURSE sources_Collision Collision/*.cpp Collision/*.h) +file(GLOB_RECURSE sources_Threading Threading/*.cpp Threading/*.h) +file(GLOB_RECURSE sources_Utilities Utilities/*.cpp Utilities/*.h) +file(GLOB_RECURSE sources_Configuration Configuration/*.cpp Configuration/*.h) +file(GLOB_RECURSE sources_Logging Logging/*.cpp Logging/*.h) +if (SERVERS) + file(GLOB_RECURSE sources_Cryptography Cryptography/*.cpp Cryptography/*.h) +endif (SERVERS) + +# Manually set sources for Debugging directory as we don't want to include WheatyExceptionReport in common project +# It needs to be included both in authserver and worldserver for the static global variable to be properly initialized +# and to handle crash logs on windows +set(sources_Debugging Debugging/Errors.cpp Debugging/Errors.h) +file(GLOB sources_localdir *.cpp *.h) + +if (USE_COREPCH) + set(common_STAT_PCH_HDR PrecompiledHeaders/commonPCH.h) + set(common_STAT_PCH_SRC PrecompiledHeaders/commonPCH.cpp) +endif (USE_COREPCH) + +set(common_STAT_SRCS + ${common_STAT_SRCS} + ${sources_Common} + ${sources_Collision} + ${sources_Threading} + ${sources_Utilities} + ${sources_Debugging} + ${sources_Configuration} + ${sources_Logging} + ${sources_Cryptography} + ${sources_localdir} +) + +# Do NOT add any extra include directory here, as we don't want the common +# library to depend on anything else than TC deps, and itself. +# This way we ensure that if either a PR does that without modifying this file, +# a compile error will be generated, either this file will be modified so it +# is detected more easily. +# While it is OK to include files from other libs as long as they don't require +# linkage (enums, defines...) it is discouraged to do so unless necessary, as it will pullute +# include_directories leading to further unnoticed dependency aditions +# Linker Depencency requirements: none +include_directories( + ${CMAKE_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/Collision + ${CMAKE_CURRENT_SOURCE_DIR}/Collision/Management + ${CMAKE_CURRENT_SOURCE_DIR}/Collision/Maps + ${CMAKE_CURRENT_SOURCE_DIR}/Collision/Models + ${CMAKE_CURRENT_SOURCE_DIR}/Configuration + ${CMAKE_CURRENT_SOURCE_DIR}/Cryptography + ${CMAKE_CURRENT_SOURCE_DIR}/Debugging + ${CMAKE_CURRENT_SOURCE_DIR}/Logging + ${CMAKE_CURRENT_SOURCE_DIR}/Utilities + ${CMAKE_SOURCE_DIR}/dep/cppformat + ${CMAKE_SOURCE_DIR}/dep/g3dlite/include + ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour/Include + ${CMAKE_SOURCE_DIR}/dep/SFMT + ${CMAKE_SOURCE_DIR}/dep/utf8cpp + ${OPENSSL_INCLUDE_DIR} + ${VALGRIND_INCLUDE_DIR} +) + +GroupSources(${CMAKE_CURRENT_SOURCE_DIR}) + +add_library(common STATIC + ${common_STAT_SRCS} + ${common_STAT_PCH_SRC} +) + +# Generate precompiled header +if (USE_COREPCH) + add_cxx_pch(common ${common_STAT_PCH_HDR} ${common_STAT_PCH_SRC}) +endif () diff --git a/src/server/collision/BoundingIntervalHierarchy.cpp b/src/common/Collision/BoundingIntervalHierarchy.cpp similarity index 100% rename from src/server/collision/BoundingIntervalHierarchy.cpp rename to src/common/Collision/BoundingIntervalHierarchy.cpp diff --git a/src/server/collision/BoundingIntervalHierarchy.h b/src/common/Collision/BoundingIntervalHierarchy.h similarity index 100% rename from src/server/collision/BoundingIntervalHierarchy.h rename to src/common/Collision/BoundingIntervalHierarchy.h diff --git a/src/server/collision/BoundingIntervalHierarchyWrapper.h b/src/common/Collision/BoundingIntervalHierarchyWrapper.h similarity index 100% rename from src/server/collision/BoundingIntervalHierarchyWrapper.h rename to src/common/Collision/BoundingIntervalHierarchyWrapper.h diff --git a/src/server/collision/DynamicTree.cpp b/src/common/Collision/DynamicTree.cpp similarity index 100% rename from src/server/collision/DynamicTree.cpp rename to src/common/Collision/DynamicTree.cpp diff --git a/src/server/collision/DynamicTree.h b/src/common/Collision/DynamicTree.h similarity index 100% rename from src/server/collision/DynamicTree.h rename to src/common/Collision/DynamicTree.h diff --git a/src/server/collision/Management/IVMapManager.h b/src/common/Collision/Management/IVMapManager.h similarity index 100% rename from src/server/collision/Management/IVMapManager.h rename to src/common/Collision/Management/IVMapManager.h diff --git a/src/server/collision/Management/MMapFactory.cpp b/src/common/Collision/Management/MMapFactory.cpp similarity index 100% rename from src/server/collision/Management/MMapFactory.cpp rename to src/common/Collision/Management/MMapFactory.cpp diff --git a/src/server/collision/Management/MMapFactory.h b/src/common/Collision/Management/MMapFactory.h similarity index 100% rename from src/server/collision/Management/MMapFactory.h rename to src/common/Collision/Management/MMapFactory.h diff --git a/src/server/collision/Management/MMapManager.cpp b/src/common/Collision/Management/MMapManager.cpp similarity index 82% rename from src/server/collision/Management/MMapManager.cpp rename to src/common/Collision/Management/MMapManager.cpp index 3ce454fe4df..673402b08a6 100644 --- a/src/server/collision/Management/MMapManager.cpp +++ b/src/common/Collision/Management/MMapManager.cpp @@ -18,11 +18,16 @@ #include "MMapManager.h" #include "Log.h" -#include "DBCStores.h" #include "MMapFactory.h" +#include "Config.h" +#include "MapDefines.h" namespace MMAP { + + static char const* const MAP_FILE_NAME_FORMAT = "%smmaps/%04i.mmap"; + static char const* const TILE_FILE_NAME_FORMAT = "%smmaps/%03i%02i%02i.mmtile"; + // ######################## MMapManager ######################## MMapManager::~MMapManager() { @@ -33,13 +38,19 @@ namespace MMAP // if we had, tiles in MMapData->mmapLoadedTiles, their actual data is lost! } - void MMapManager::InitializeThreadUnsafe(const std::vector& mapIds) + void MMapManager::InitializeThreadUnsafe(std::unordered_map> const& mapData) { - // the caller must pass the list of all mapIds that will be used in the VMapManager2 lifetime - for (const uint32& mapId : mapIds) - loadedMMaps.insert(MMapDataSet::value_type(mapId, nullptr)); - - thread_safe_environment = false; + // the caller must pass the list of all mapIds that will be used in the MMapManager lifetime + for (auto const& p : mapData) + { + loadedMMaps.insert(MMapDataSet::value_type(p.first, nullptr)); + if (!p.second.empty()) + { + phaseMapData[p.first] = p.second; + for (uint32 phasedMapId : p.second) + _phaseTiles.insert(PhaseTileMap::value_type(phasedMapId, PhaseTileContainer())); + } + } } MMapDataSet::const_iterator MMapManager::GetMMapData(uint32 mapId) const @@ -70,9 +81,10 @@ namespace MMAP } // load and init dtNavMesh - read parameters from file - uint32 pathLen = sWorld->GetDataPath().length() + strlen("mmaps/%03i.mmap") + 1; + std::string dataDir = sConfigMgr->GetStringDefault("DataDir", "./"); + uint32 pathLen = dataDir.length() + strlen("/mmaps/%03i.mmap") + 1; char *fileName = new char[pathLen]; - snprintf(fileName, pathLen, (sWorld->GetDataPath() + "mmaps/%03i.mmap").c_str(), mapId); + snprintf(fileName, pathLen, (dataDir + "/mmaps/%03i.mmap").c_str(), mapId); FILE* file = fopen(fileName, "rb"); if (!file) @@ -118,7 +130,7 @@ namespace MMAP return uint32(x << 16 | y); } - bool MMapManager::loadMap(const std::string& /*basePath*/, uint32 mapId, int32 x, int32 y) + bool MMapManager::loadMap(const std::string& basePath, uint32 mapId, int32 x, int32 y) { // make sure the mmap is loaded and ready to load tiles if (!loadMapData(mapId)) @@ -134,10 +146,10 @@ namespace MMAP return false; // load this tile :: mmaps/MMMXXYY.mmtile - uint32 pathLen = sWorld->GetDataPath().length() + strlen("mmaps/%03i%02i%02i.mmtile") + 1; + uint32 pathLen = basePath.length() + strlen("/%03i%02i%02i.mmtile") + 1; char *fileName = new char[pathLen]; - snprintf(fileName, pathLen, (sWorld->GetDataPath() + "mmaps/%03i%02i%02i.mmtile").c_str(), mapId, x, y); + snprintf(fileName, pathLen, (basePath + "/%03i%02i%02i.mmtile").c_str(), mapId, x, y); FILE* file = fopen(fileName, "rb"); if (!file) @@ -188,7 +200,9 @@ namespace MMAP ++loadedTiles; TC_LOG_DEBUG("maps", "MMAP:loadMap: Loaded mmtile %03i[%02i, %02i] into %03i[%02i, %02i]", mapId, x, y, mapId, header->x, header->y); - LoadPhaseTiles(mapId, x, y); + PhaseChildMapContainer::const_iterator phasedMaps = phaseMapData.find(mapId); + if (phasedMaps != phaseMapData.end()) + LoadPhaseTiles(phasedMaps, x, y); return true; } @@ -203,20 +217,15 @@ namespace MMAP PhasedTile* MMapManager::LoadTile(uint32 mapId, int32 x, int32 y) { // load this tile :: mmaps/MMMXXYY.mmtile - uint32 pathLen = sWorld->GetDataPath().length() + strlen("mmaps/%03i%02i%02i.mmtile") + 1; - char *fileName = new char[pathLen]; + std::string fileName = Trinity::StringFormat(TILE_FILE_NAME_FORMAT, sConfigMgr->GetStringDefault("DataDir", "./").c_str(), mapId, x, y); - snprintf(fileName, pathLen, (sWorld->GetDataPath() + "mmaps/%03i%02i%02i.mmtile").c_str(), mapId, x, y); - - FILE* file = fopen(fileName, "rb"); + FILE* file = fopen(fileName.c_str(), "rb"); if (!file) { // Not all tiles have phased versions, don't flood this msg //TC_LOG_DEBUG("phase", "MMAP:LoadTile: Could not open mmtile file '%s'", fileName); - delete[] fileName; return NULL; } - delete[] fileName; PhasedTile* pTile = new PhasedTile(); @@ -252,45 +261,43 @@ namespace MMAP return pTile; } - void MMapManager::LoadPhaseTiles(uint32 mapId, int32 x, int32 y) + void MMapManager::LoadPhaseTiles(PhaseChildMapContainer::const_iterator phasedMapData, int32 x, int32 y) { - TC_LOG_DEBUG("phase", "MMAP:LoadPhaseTiles: Loading phased mmtiles for map %u, x: %i, y: %i", mapId, x, y); + TC_LOG_DEBUG("phase", "MMAP:LoadPhaseTiles: Loading phased mmtiles for map %u, x: %i, y: %i", phasedMapData->first, x, y); uint32 packedGridPos = packTileID(x, y); - for (uint32 i = 0; i < sMapStore.GetNumRows(); ++i) + for (uint32 phaseMapId : phasedMapData->second) { - if (const MapEntry* const map = sMapStore.LookupEntry(i)) + // only a few tiles have terrain swaps, do not write error for them + if (PhasedTile* data = LoadTile(phaseMapId, x, y)) { - if (map->rootPhaseMap == int32(mapId)) - { - PhasedTile* data = LoadTile(map->MapID, x, y); - // only a few tiles have terrain swaps, do not write error for them - if (data) - { - TC_LOG_DEBUG("phase", "MMAP:LoadPhaseTiles: Loaded phased %03u%02i%02i.mmtile for root phase map %u", map->MapID, x, y, mapId); - _phaseTiles[map->MapID][packedGridPos] = data; - } - } + TC_LOG_DEBUG("phase", "MMAP:LoadPhaseTiles: Loaded phased %03u%02i%02i.mmtile for root phase map %u", phaseMapId, x, y, phasedMapData->first); + _phaseTiles[phaseMapId][packedGridPos] = data; } } } - void MMapManager::UnloadPhaseTile(uint32 mapId, int32 x, int32 y) + void MMapManager::UnloadPhaseTile(PhaseChildMapContainer::const_iterator phasedMapData, int32 x, int32 y) { - TC_LOG_DEBUG("phase", "MMAP:UnloadPhaseTile: Unloading phased mmtile for map %u, x: %i, y: %i", mapId, x, y); + TC_LOG_DEBUG("phase", "MMAP:UnloadPhaseTile: Unloading phased mmtile for map %u, x: %i, y: %i", phasedMapData->first, x, y); uint32 packedGridPos = packTileID(x, y); - const MapEntry* const map = sMapStore.LookupEntry(mapId); // map existence already checked when loading - uint32 rootMapId = map->rootPhaseMap; - - if (_phaseTiles[mapId][packedGridPos]) + for (uint32 phaseMapId : phasedMapData->second) { - TC_LOG_DEBUG("phase", "MMAP:UnloadPhaseTile: Unloaded phased %03u%02i%02i.mmtile for root phase map %u", mapId, x, y, rootMapId); - delete _phaseTiles[mapId][packedGridPos]->data; - delete _phaseTiles[mapId][packedGridPos]; - _phaseTiles[mapId].erase(packedGridPos); + auto phasedTileItr = _phaseTiles.find(phaseMapId); + if (phasedTileItr == _phaseTiles.end()) + continue; + + auto dataItr = phasedTileItr->second.find(packedGridPos); + if (dataItr != phasedTileItr->second.end()) + { + TC_LOG_DEBUG("phase", "MMAP:UnloadPhaseTile: Unloaded phased %04u%02i%02i.mmtile for root phase map %u", phaseMapId, x, y, phasedMapData->first); + delete dataItr->second->data; + delete dataItr->second; + phasedTileItr->second.erase(dataItr); + } } } @@ -333,7 +340,9 @@ namespace MMAP --loadedTiles; TC_LOG_DEBUG("maps", "MMAP:unloadMap: Unloaded mmtile %03i[%02i, %02i] from %03i", mapId, x, y, mapId); - UnloadPhaseTile(mapId, x, y); + PhaseChildMapContainer::const_iterator phasedMaps = phaseMapData.find(mapId); + if (phasedMaps != phaseMapData.end()) + UnloadPhaseTile(phasedMaps, x, y); return true; } @@ -360,7 +369,9 @@ namespace MMAP TC_LOG_ERROR("maps", "MMAP:unloadMap: Could not unload %03u%02i%02i.mmtile from navmesh", mapId, x, y); else { - UnloadPhaseTile(mapId, x, y); + PhaseChildMapContainer::const_iterator phasedMaps = phaseMapData.find(mapId); + if (phasedMaps != phaseMapData.end()) + UnloadPhaseTile(phasedMaps, x, y); --loadedTiles; TC_LOG_DEBUG("maps", "MMAP:unloadMap: Unloaded mmtile %03i[%02i, %02i] from %03i", mapId, x, y, mapId); } @@ -557,13 +568,11 @@ namespace MMAP { for (uint32 swap : _activeSwaps) { - if (swaps.find(swap) == swaps.end()) // swap not active + if (!swaps.count(swap)) // swap not active { - PhaseTileContainer ptc = MMAP::MMapFactory::createOrGetMMapManager()->GetPhaseTileContainer(swap); - for (PhaseTileContainer::const_iterator itr = ptc.begin(); itr != ptc.end(); ++itr) - { - RemoveSwap(itr->second, swap, itr->first); // remove swap - } + if (PhaseTileContainer const* ptc = MMAP::MMapFactory::createOrGetMMapManager()->GetPhaseTileContainer(swap)) + for (PhaseTileContainer::const_iterator itr = ptc->begin(); itr != ptc->end(); ++itr) + RemoveSwap(itr->second, swap, itr->first); // remove swap } } @@ -573,14 +582,9 @@ namespace MMAP for (uint32 swap : swaps) { // for each of the terrain swap's xy tiles - PhaseTileContainer ptc = MMAP::MMapFactory::createOrGetMMapManager()->GetPhaseTileContainer(swap); - for (PhaseTileContainer::const_iterator itr = ptc.begin(); itr != ptc.end(); ++itr) - { - if (_activeSwaps.find(swap) == _activeSwaps.end()) // swap not active - { + if (PhaseTileContainer const* ptc = MMAP::MMapFactory::createOrGetMMapManager()->GetPhaseTileContainer(swap)) + for (PhaseTileContainer::const_iterator itr = ptc->begin(); itr != ptc->end(); ++itr) AddSwap(itr->second, swap, itr->first); // add swap - } - } } } return navMesh; diff --git a/src/server/collision/Management/MMapManager.h b/src/common/Collision/Management/MMapManager.h similarity index 83% rename from src/server/collision/Management/MMapManager.h rename to src/common/Collision/Management/MMapManager.h index ad8f433469e..135b444a1b8 100644 --- a/src/server/collision/Management/MMapManager.h +++ b/src/common/Collision/Management/MMapManager.h @@ -22,7 +22,7 @@ #include "Define.h" #include "DetourNavMesh.h" #include "DetourNavMeshQuery.h" -#include "World.h" +#include "MapDefines.h" #include #include #include @@ -94,7 +94,7 @@ namespace MMAP MMapManager() : loadedTiles(0), thread_safe_environment(true) {} ~MMapManager(); - void InitializeThreadUnsafe(const std::vector& mapIds); + void InitializeThreadUnsafe(std::unordered_map> const& mapData); bool loadMap(const std::string& basePath, uint32 mapId, int32 x, int32 y); bool unloadMap(uint32 mapId, int32 x, int32 y); bool unloadMap(uint32 mapId); @@ -107,9 +107,16 @@ namespace MMAP uint32 getLoadedTilesCount() const { return loadedTiles; } uint32 getLoadedMapsCount() const { return loadedMMaps.size(); } - void LoadPhaseTiles(uint32 mapId, int32 x, int32 y); - void UnloadPhaseTile(uint32 mapId, int32 x, int32 y); - PhaseTileContainer GetPhaseTileContainer(uint32 mapId) { return _phaseTiles[mapId]; } + typedef std::unordered_map> PhaseChildMapContainer; + void LoadPhaseTiles(PhaseChildMapContainer::const_iterator phasedMapData, int32 x, int32 y); + void UnloadPhaseTile(PhaseChildMapContainer::const_iterator phasedMapData, int32 x, int32 y); + PhaseTileContainer const* GetPhaseTileContainer(uint32 mapId) const + { + auto itr = _phaseTiles.find(mapId); + if (itr != _phaseTiles.end()) + return &itr->second; + return nullptr; + } private: bool loadMapData(uint32 mapId); @@ -117,6 +124,7 @@ namespace MMAP MMapDataSet::const_iterator GetMMapData(uint32 mapId) const; MMapDataSet loadedMMaps; + PhaseChildMapContainer phaseMapData; uint32 loadedTiles; bool thread_safe_environment; PhasedTile* LoadTile(uint32 mapId, int32 x, int32 y); diff --git a/src/server/collision/Management/VMapFactory.cpp b/src/common/Collision/Management/VMapFactory.cpp similarity index 100% rename from src/server/collision/Management/VMapFactory.cpp rename to src/common/Collision/Management/VMapFactory.cpp diff --git a/src/server/collision/Management/VMapFactory.h b/src/common/Collision/Management/VMapFactory.h similarity index 100% rename from src/server/collision/Management/VMapFactory.h rename to src/common/Collision/Management/VMapFactory.h diff --git a/src/server/collision/Management/VMapManager2.cpp b/src/common/Collision/Management/VMapManager2.cpp similarity index 98% rename from src/server/collision/Management/VMapManager2.cpp rename to src/common/Collision/Management/VMapManager2.cpp index 9594951196f..2f944706d7a 100644 --- a/src/server/collision/Management/VMapManager2.cpp +++ b/src/common/Collision/Management/VMapManager2.cpp @@ -52,11 +52,11 @@ namespace VMAP } } - void VMapManager2::InitializeThreadUnsafe(const std::vector& mapIds) + void VMapManager2::InitializeThreadUnsafe(std::unordered_map> const& mapData) { // the caller must pass the list of all mapIds that will be used in the VMapManager2 lifetime - for (const uint32& mapId : mapIds) - iInstanceMapTrees.insert(InstanceTreeMap::value_type(mapId, nullptr)); + for (auto const& p : mapData) + iInstanceMapTrees.insert(InstanceTreeMap::value_type(p.first, nullptr)); thread_safe_environment = false; } diff --git a/src/server/collision/Management/VMapManager2.h b/src/common/Collision/Management/VMapManager2.h similarity index 98% rename from src/server/collision/Management/VMapManager2.h rename to src/common/Collision/Management/VMapManager2.h index a5891e9642b..553145cda4b 100644 --- a/src/server/collision/Management/VMapManager2.h +++ b/src/common/Collision/Management/VMapManager2.h @@ -101,7 +101,7 @@ namespace VMAP VMapManager2(); ~VMapManager2(void); - void InitializeThreadUnsafe(const std::vector& mapIds); + void InitializeThreadUnsafe(std::unordered_map> const& mapData); int loadMap(const char* pBasePath, unsigned int mapId, int x, int y) override; void unloadMap(unsigned int mapId, int x, int y) override; diff --git a/src/common/Collision/Maps/MapDefines.h b/src/common/Collision/Maps/MapDefines.h new file mode 100644 index 00000000000..538a78a38d4 --- /dev/null +++ b/src/common/Collision/Maps/MapDefines.h @@ -0,0 +1,36 @@ +#ifndef _MAPDEFINES_H +#define _MAPDEFINES_H + +#include "Define.h" +#include "DetourNavMesh.h" + +const uint32 MMAP_MAGIC = 0x4d4d4150; // 'MMAP' +#define MMAP_VERSION 5 + +struct MmapTileHeader +{ + uint32 mmapMagic; + uint32 dtVersion; + uint32 mmapVersion; + uint32 size; + bool usesLiquids : 1; + + MmapTileHeader() : mmapMagic(MMAP_MAGIC), dtVersion(DT_NAVMESH_VERSION), + mmapVersion(MMAP_VERSION), size(0), usesLiquids(true) { } +}; + +enum NavTerrain +{ + NAV_EMPTY = 0x00, + NAV_GROUND = 0x01, + NAV_MAGMA = 0x02, + NAV_SLIME = 0x04, + NAV_WATER = 0x08, + NAV_UNUSED1 = 0x10, + NAV_UNUSED2 = 0x20, + NAV_UNUSED3 = 0x40, + NAV_UNUSED4 = 0x80 + // we only have 8 bits +}; + +#endif diff --git a/src/server/collision/Maps/MapTree.cpp b/src/common/Collision/Maps/MapTree.cpp similarity index 100% rename from src/server/collision/Maps/MapTree.cpp rename to src/common/Collision/Maps/MapTree.cpp diff --git a/src/server/collision/Maps/MapTree.h b/src/common/Collision/Maps/MapTree.h similarity index 100% rename from src/server/collision/Maps/MapTree.h rename to src/common/Collision/Maps/MapTree.h diff --git a/src/server/collision/Maps/TileAssembler.cpp b/src/common/Collision/Maps/TileAssembler.cpp similarity index 100% rename from src/server/collision/Maps/TileAssembler.cpp rename to src/common/Collision/Maps/TileAssembler.cpp diff --git a/src/server/collision/Maps/TileAssembler.h b/src/common/Collision/Maps/TileAssembler.h similarity index 100% rename from src/server/collision/Maps/TileAssembler.h rename to src/common/Collision/Maps/TileAssembler.h diff --git a/src/server/collision/Models/GameObjectModel.cpp b/src/common/Collision/Models/GameObjectModel.cpp similarity index 100% rename from src/server/collision/Models/GameObjectModel.cpp rename to src/common/Collision/Models/GameObjectModel.cpp diff --git a/src/server/collision/Models/GameObjectModel.h b/src/common/Collision/Models/GameObjectModel.h similarity index 100% rename from src/server/collision/Models/GameObjectModel.h rename to src/common/Collision/Models/GameObjectModel.h diff --git a/src/server/collision/Models/ModelInstance.cpp b/src/common/Collision/Models/ModelInstance.cpp similarity index 100% rename from src/server/collision/Models/ModelInstance.cpp rename to src/common/Collision/Models/ModelInstance.cpp diff --git a/src/server/collision/Models/ModelInstance.h b/src/common/Collision/Models/ModelInstance.h similarity index 100% rename from src/server/collision/Models/ModelInstance.h rename to src/common/Collision/Models/ModelInstance.h diff --git a/src/server/collision/Models/WorldModel.cpp b/src/common/Collision/Models/WorldModel.cpp similarity index 100% rename from src/server/collision/Models/WorldModel.cpp rename to src/common/Collision/Models/WorldModel.cpp diff --git a/src/server/collision/Models/WorldModel.h b/src/common/Collision/Models/WorldModel.h similarity index 100% rename from src/server/collision/Models/WorldModel.h rename to src/common/Collision/Models/WorldModel.h diff --git a/src/server/collision/RegularGrid.h b/src/common/Collision/RegularGrid.h similarity index 100% rename from src/server/collision/RegularGrid.h rename to src/common/Collision/RegularGrid.h diff --git a/src/server/collision/VMapDefinitions.h b/src/common/Collision/VMapDefinitions.h similarity index 100% rename from src/server/collision/VMapDefinitions.h rename to src/common/Collision/VMapDefinitions.h diff --git a/src/server/collision/VMapTools.h b/src/common/Collision/VMapTools.h similarity index 99% rename from src/server/collision/VMapTools.h rename to src/common/Collision/VMapTools.h index fa7bc394ebc..662dc43e9e7 100644 --- a/src/server/collision/VMapTools.h +++ b/src/common/Collision/VMapTools.h @@ -22,8 +22,6 @@ #include #include -#include "NodeValueAccess.h" - /** The Class is mainly taken from G3D/AABSPTree.h but modified to be able to use our internal data structure. This is an iterator that helps us analysing the BSP-Trees. diff --git a/src/server/shared/Common.cpp b/src/common/Common.cpp similarity index 100% rename from src/server/shared/Common.cpp rename to src/common/Common.cpp diff --git a/src/server/shared/Common.h b/src/common/Common.h similarity index 100% rename from src/server/shared/Common.h rename to src/common/Common.h diff --git a/src/server/shared/CompilerDefs.h b/src/common/CompilerDefs.h similarity index 100% rename from src/server/shared/CompilerDefs.h rename to src/common/CompilerDefs.h diff --git a/src/server/shared/Configuration/Config.cpp b/src/common/Configuration/Config.cpp similarity index 100% rename from src/server/shared/Configuration/Config.cpp rename to src/common/Configuration/Config.cpp diff --git a/src/server/shared/Configuration/Config.h b/src/common/Configuration/Config.h similarity index 100% rename from src/server/shared/Configuration/Config.h rename to src/common/Configuration/Config.h diff --git a/src/server/shared/Cryptography/ARC4.cpp b/src/common/Cryptography/ARC4.cpp similarity index 100% rename from src/server/shared/Cryptography/ARC4.cpp rename to src/common/Cryptography/ARC4.cpp diff --git a/src/server/shared/Cryptography/ARC4.h b/src/common/Cryptography/ARC4.h similarity index 100% rename from src/server/shared/Cryptography/ARC4.h rename to src/common/Cryptography/ARC4.h diff --git a/src/server/shared/Cryptography/Authentication/PacketCrypt.cpp b/src/common/Cryptography/Authentication/PacketCrypt.cpp similarity index 100% rename from src/server/shared/Cryptography/Authentication/PacketCrypt.cpp rename to src/common/Cryptography/Authentication/PacketCrypt.cpp diff --git a/src/server/shared/Cryptography/Authentication/PacketCrypt.h b/src/common/Cryptography/Authentication/PacketCrypt.h similarity index 100% rename from src/server/shared/Cryptography/Authentication/PacketCrypt.h rename to src/common/Cryptography/Authentication/PacketCrypt.h diff --git a/src/server/shared/Cryptography/Authentication/WorldPacketCrypt.cpp b/src/common/Cryptography/Authentication/WorldPacketCrypt.cpp similarity index 100% rename from src/server/shared/Cryptography/Authentication/WorldPacketCrypt.cpp rename to src/common/Cryptography/Authentication/WorldPacketCrypt.cpp diff --git a/src/server/shared/Cryptography/Authentication/WorldPacketCrypt.h b/src/common/Cryptography/Authentication/WorldPacketCrypt.h similarity index 100% rename from src/server/shared/Cryptography/Authentication/WorldPacketCrypt.h rename to src/common/Cryptography/Authentication/WorldPacketCrypt.h diff --git a/src/server/shared/Cryptography/BigNumber.cpp b/src/common/Cryptography/BigNumber.cpp similarity index 100% rename from src/server/shared/Cryptography/BigNumber.cpp rename to src/common/Cryptography/BigNumber.cpp diff --git a/src/server/shared/Cryptography/BigNumber.h b/src/common/Cryptography/BigNumber.h similarity index 100% rename from src/server/shared/Cryptography/BigNumber.h rename to src/common/Cryptography/BigNumber.h diff --git a/src/server/shared/Cryptography/HmacHash.cpp b/src/common/Cryptography/HmacHash.cpp similarity index 100% rename from src/server/shared/Cryptography/HmacHash.cpp rename to src/common/Cryptography/HmacHash.cpp diff --git a/src/server/shared/Cryptography/HmacHash.h b/src/common/Cryptography/HmacHash.h similarity index 100% rename from src/server/shared/Cryptography/HmacHash.h rename to src/common/Cryptography/HmacHash.h diff --git a/src/server/shared/Cryptography/OpenSSLCrypto.cpp b/src/common/Cryptography/OpenSSLCrypto.cpp similarity index 100% rename from src/server/shared/Cryptography/OpenSSLCrypto.cpp rename to src/common/Cryptography/OpenSSLCrypto.cpp diff --git a/src/server/shared/Cryptography/OpenSSLCrypto.h b/src/common/Cryptography/OpenSSLCrypto.h similarity index 100% rename from src/server/shared/Cryptography/OpenSSLCrypto.h rename to src/common/Cryptography/OpenSSLCrypto.h diff --git a/src/server/shared/Cryptography/SHA1.cpp b/src/common/Cryptography/SHA1.cpp similarity index 100% rename from src/server/shared/Cryptography/SHA1.cpp rename to src/common/Cryptography/SHA1.cpp diff --git a/src/server/shared/Cryptography/SHA1.h b/src/common/Cryptography/SHA1.h similarity index 100% rename from src/server/shared/Cryptography/SHA1.h rename to src/common/Cryptography/SHA1.h diff --git a/src/server/shared/Cryptography/SHA256.cpp b/src/common/Cryptography/SHA256.cpp similarity index 100% rename from src/server/shared/Cryptography/SHA256.cpp rename to src/common/Cryptography/SHA256.cpp diff --git a/src/server/shared/Cryptography/SHA256.h b/src/common/Cryptography/SHA256.h similarity index 100% rename from src/server/shared/Cryptography/SHA256.h rename to src/common/Cryptography/SHA256.h diff --git a/src/server/shared/Cryptography/WardenKeyGeneration.h b/src/common/Cryptography/WardenKeyGeneration.h similarity index 100% rename from src/server/shared/Cryptography/WardenKeyGeneration.h rename to src/common/Cryptography/WardenKeyGeneration.h diff --git a/src/server/shared/Debugging/Errors.cpp b/src/common/Debugging/Errors.cpp similarity index 100% rename from src/server/shared/Debugging/Errors.cpp rename to src/common/Debugging/Errors.cpp diff --git a/src/server/shared/Debugging/Errors.h b/src/common/Debugging/Errors.h similarity index 100% rename from src/server/shared/Debugging/Errors.h rename to src/common/Debugging/Errors.h diff --git a/src/server/shared/Debugging/WheatyExceptionReport.cpp b/src/common/Debugging/WheatyExceptionReport.cpp similarity index 99% rename from src/server/shared/Debugging/WheatyExceptionReport.cpp rename to src/common/Debugging/WheatyExceptionReport.cpp index 02916ca12d2..7cf109b4070 100644 --- a/src/server/shared/Debugging/WheatyExceptionReport.cpp +++ b/src/common/Debugging/WheatyExceptionReport.cpp @@ -20,8 +20,7 @@ #include "WheatyExceptionReport.h" #include "Common.h" -#include "SystemConfig.h" -#include "revision.h" +#include "GitRevision.h" #define CrashFolder _T("Crashes") #pragma comment(linker, "/DEFAULTLIB:dbghelp.lib") @@ -131,10 +130,10 @@ PEXCEPTION_POINTERS pExceptionInfo) SYSTEMTIME systime; GetLocalTime(&systime); sprintf(m_szDumpFileName, "%s\\%s_%s_[%u-%u_%u-%u-%u].dmp", - crash_folder_path, _HASH, pos, systime.wDay, systime.wMonth, systime.wHour, systime.wMinute, systime.wSecond); + crash_folder_path, GitRevision::GetHash(), pos, systime.wDay, systime.wMonth, systime.wHour, systime.wMinute, systime.wSecond); sprintf(m_szLogFileName, "%s\\%s_%s_[%u-%u_%u-%u-%u].txt", - crash_folder_path, _HASH, pos, systime.wDay, systime.wMonth, systime.wHour, systime.wMinute, systime.wSecond); + crash_folder_path, GitRevision::GetHash(), pos, systime.wDay, systime.wMonth, systime.wHour, systime.wMinute, systime.wSecond); m_hDumpFile = CreateFile(m_szDumpFileName, GENERIC_WRITE, @@ -440,7 +439,7 @@ PEXCEPTION_POINTERS pExceptionInfo) GetLocalTime(&systime); // Start out with a banner - _tprintf(_T("Revision: %s\r\n"), _FULLVERSION); + _tprintf(_T("Revision: %s\r\n"), GitRevision::GetFullVersion()); _tprintf(_T("Date %u:%u:%u. Time %u:%u \r\n"), systime.wDay, systime.wMonth, systime.wYear, systime.wHour, systime.wMinute); PEXCEPTION_RECORD pExceptionRecord = pExceptionInfo->ExceptionRecord; diff --git a/src/server/shared/Debugging/WheatyExceptionReport.h b/src/common/Debugging/WheatyExceptionReport.h similarity index 100% rename from src/server/shared/Debugging/WheatyExceptionReport.h rename to src/common/Debugging/WheatyExceptionReport.h diff --git a/src/server/shared/Define.h b/src/common/Define.h similarity index 100% rename from src/server/shared/Define.h rename to src/common/Define.h diff --git a/src/common/GitRevision.cpp b/src/common/GitRevision.cpp new file mode 100644 index 00000000000..d0719c09959 --- /dev/null +++ b/src/common/GitRevision.cpp @@ -0,0 +1,78 @@ +#include "GitRevision.h" +#include "CompilerDefs.h" +#include "revision_data.h" + +char const* GitRevision::GetHash() +{ + return _HASH; +} + +char const* GitRevision::GetDate() +{ + return _DATE; +} + +char const* GitRevision::GetBranch() +{ + return _BRANCH; +} + +char const* GitRevision::GetSourceDirectory() +{ + return _SOURCE_DIRECTORY; +} + +char const* GitRevision::GetMySQLExecutable() +{ + return _MYSQL_EXECUTABLE; +} + +char const* GitRevision::GetFullDatabase() +{ + return _FULL_DATABASE; +} + +#define _PACKAGENAME "TrinityCore" + +char const* GitRevision::GetFullVersion() +{ +#if PLATFORM == PLATFORM_WINDOWS +# ifdef _WIN64 + return _PACKAGENAME " rev. " VER_PRODUCTVERSION_STR " (Win64, " _BUILD_DIRECTIVE ")"; +# else + return _PACKAGENAME " rev. " VER_PRODUCTVERSION_STR " (Win32, " _BUILD_DIRECTIVE ")"; +# endif +#else + return _PACKAGENAME " rev. " VER_PRODUCTVERSION_STR " (Unix, " _BUILD_DIRECTIVE ")"; +#endif +} + +char const* GitRevision::GetCompanyNameStr() +{ + return VER_COMPANYNAME_STR; +} + +char const* GitRevision::GetLegalCopyrightStr() +{ + return VER_LEGALCOPYRIGHT_STR; +} + +char const* GitRevision::GetFileVersionStr() +{ + return VER_FILEVERSION_STR; +} + +char const* GitRevision::GetProductVersionStr() +{ + return VER_PRODUCTVERSION_STR; +} + +char const* GitRevision::GetCompilerCFlags() +{ + return COMPILER_C_FLAGS; +} + +char const* GitRevision::GetCompilerCXXFlags() +{ + return COMPILER_CXX_FLAGS; +} diff --git a/src/server/shared/SystemConfig.h b/src/common/GitRevision.h similarity index 50% rename from src/server/shared/SystemConfig.h rename to src/common/GitRevision.h index 7c519c7de57..d9b292031f6 100644 --- a/src/server/shared/SystemConfig.h +++ b/src/common/GitRevision.h @@ -1,6 +1,5 @@ /* * Copyright (C) 2008-2015 TrinityCore - * Copyright (C) 2005-2009 MaNGOS * * 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 @@ -16,29 +15,26 @@ * with this program. If not, see . */ -// THIS FILE IS DEPRECATED +#ifndef __GITREVISION_H__ +#define __GITREVISION_H__ -#ifndef TRINITY_SYSTEMCONFIG_H -#define TRINITY_SYSTEMCONFIG_H +#include -#include "Define.h" -#include "revision.h" +namespace GitRevision +{ + char const* GetHash(); + char const* GetDate(); + char const* GetBranch(); + char const* GetSourceDirectory(); + char const* GetMySQLExecutable(); + char const* GetFullDatabase(); + char const* GetFullVersion(); + char const* GetCompanyNameStr(); + char const* GetLegalCopyrightStr(); + char const* GetFileVersionStr(); + char const* GetProductVersionStr(); + char const* GetCompilerCFlags(); + char const* GetCompilerCXXFlags(); +} -#define _PACKAGENAME "TrinityCore" - -#if TRINITY_ENDIAN == TRINITY_BIGENDIAN -# define _ENDIAN_STRING "big-endian" -#else -# define _ENDIAN_STRING "little-endian" -#endif - -#if PLATFORM == PLATFORM_WINDOWS -# ifdef _WIN64 -# define _FULLVERSION _PACKAGENAME " rev. " VER_PRODUCTVERSION_STR " (Win64, " _BUILD_DIRECTIVE ")" -# else -# define _FULLVERSION _PACKAGENAME " rev. " VER_PRODUCTVERSION_STR " (Win32, " _BUILD_DIRECTIVE ")" -# endif -#else -# define _FULLVERSION _PACKAGENAME " rev. " VER_PRODUCTVERSION_STR " (Unix, " _BUILD_DIRECTIVE ")" -#endif #endif diff --git a/src/server/shared/Logging/Appender.cpp b/src/common/Logging/Appender.cpp similarity index 88% rename from src/server/shared/Logging/Appender.cpp rename to src/common/Logging/Appender.cpp index 31db3ae1b86..d19ef8cf96f 100644 --- a/src/server/shared/Logging/Appender.cpp +++ b/src/common/Logging/Appender.cpp @@ -37,8 +37,8 @@ std::string LogMessage::getTimeStr() return getTimeStr(mtime); } -Appender::Appender(uint8 _id, std::string const& _name, AppenderType _type /* = APPENDER_NONE*/, LogLevel _level /* = LOG_LEVEL_DISABLED */, AppenderFlags _flags /* = APPENDER_FLAGS_NONE */): -id(_id), name(_name), type(_type), level(_level), flags(_flags) { } +Appender::Appender(uint8 _id, std::string const& _name, LogLevel _level /* = LOG_LEVEL_DISABLED */, AppenderFlags _flags /* = APPENDER_FLAGS_NONE */): +id(_id), name(_name), level(_level), flags(_flags) { } Appender::~Appender() { } @@ -52,11 +52,6 @@ std::string const& Appender::getName() const return name; } -AppenderType Appender::getType() const -{ - return type; -} - LogLevel Appender::getLogLevel() const { return level; diff --git a/src/server/shared/Logging/Appender.h b/src/common/Logging/Appender.h similarity index 76% rename from src/server/shared/Logging/Appender.h rename to src/common/Logging/Appender.h index 73af351e41d..6382399a0b4 100644 --- a/src/server/shared/Logging/Appender.h +++ b/src/common/Logging/Appender.h @@ -19,9 +19,12 @@ #define APPENDER_H #include +#include #include #include #include +#include +#include #include "Define.h" // Values assigned have their equivalent in enum ACE_Log_Priority @@ -85,29 +88,45 @@ struct LogMessage class Appender { public: - Appender(uint8 _id, std::string const& name, AppenderType type = APPENDER_NONE, LogLevel level = LOG_LEVEL_DISABLED, AppenderFlags flags = APPENDER_FLAGS_NONE); + Appender(uint8 _id, std::string const& name, LogLevel level = LOG_LEVEL_DISABLED, AppenderFlags flags = APPENDER_FLAGS_NONE); virtual ~Appender(); uint8 getId() const; std::string const& getName() const; - AppenderType getType() const; + virtual AppenderType getType() const = 0; LogLevel getLogLevel() const; AppenderFlags getFlags() const; void setLogLevel(LogLevel); void write(LogMessage* message); static const char* getLogLevelString(LogLevel level); + virtual void setRealmId(uint32 /*realmId*/) { } private: virtual void _write(LogMessage const* /*message*/) = 0; uint8 id; std::string name; - AppenderType type; LogLevel level; AppenderFlags flags; }; typedef std::unordered_map AppenderMap; +typedef std::vector ExtraAppenderArgs; +typedef Appender*(*AppenderCreatorFn)(uint8 id, std::string const& name, LogLevel level, AppenderFlags flags, ExtraAppenderArgs extraArgs); +typedef std::unordered_map AppenderCreatorMap; + +template +Appender* CreateAppender(uint8 id, std::string const& name, LogLevel level, AppenderFlags flags, ExtraAppenderArgs extraArgs) +{ + return new AppenderImpl(id, name, level, flags, std::forward(extraArgs)); +} + +class InvalidAppenderArgsException : public std::length_error +{ +public: + explicit InvalidAppenderArgsException(std::string const& message) : std::length_error(message) { } +}; + #endif diff --git a/src/server/shared/Logging/AppenderConsole.cpp b/src/common/Logging/AppenderConsole.cpp similarity index 97% rename from src/server/shared/Logging/AppenderConsole.cpp rename to src/common/Logging/AppenderConsole.cpp index 2efa4db4d2e..531df266aa1 100644 --- a/src/server/shared/Logging/AppenderConsole.cpp +++ b/src/common/Logging/AppenderConsole.cpp @@ -25,11 +25,14 @@ #include #endif -AppenderConsole::AppenderConsole(uint8 id, std::string const& name, LogLevel level, AppenderFlags flags): -Appender(id, name, APPENDER_CONSOLE, level, flags), _colored(false) +AppenderConsole::AppenderConsole(uint8 id, std::string const& name, LogLevel level, AppenderFlags flags, ExtraAppenderArgs extraArgs) + : Appender(id, name, level, flags), _colored(false) { for (uint8 i = 0; i < MaxLogLevels; ++i) _colors[i] = ColorTypes(MaxColors); + + if (!extraArgs.empty()) + InitColors(extraArgs[0]); } void AppenderConsole::InitColors(std::string const& str) diff --git a/src/server/shared/Logging/AppenderConsole.h b/src/common/Logging/AppenderConsole.h similarity index 84% rename from src/server/shared/Logging/AppenderConsole.h rename to src/common/Logging/AppenderConsole.h index 0acf7636e35..6b30505c6bd 100644 --- a/src/server/shared/Logging/AppenderConsole.h +++ b/src/common/Logging/AppenderConsole.h @@ -42,11 +42,14 @@ enum ColorTypes const uint8 MaxColors = uint8(WHITE) + 1; -class AppenderConsole: public Appender +class AppenderConsole : public Appender { public: - AppenderConsole(uint8 _id, std::string const& name, LogLevel level, AppenderFlags flags); + typedef std::integral_constant::type TypeIndex; + + AppenderConsole(uint8 _id, std::string const& name, LogLevel level, AppenderFlags flags, ExtraAppenderArgs extraArgs); void InitColors(const std::string& init_str); + AppenderType getType() const override { return TypeIndex::value; } private: void SetColor(bool stdout_stream, ColorTypes color); diff --git a/src/server/shared/Logging/AppenderFile.cpp b/src/common/Logging/AppenderFile.cpp similarity index 75% rename from src/server/shared/Logging/AppenderFile.cpp rename to src/common/Logging/AppenderFile.cpp index c9cc1935c7a..c90c8f6ccea 100644 --- a/src/server/shared/Logging/AppenderFile.cpp +++ b/src/common/Logging/AppenderFile.cpp @@ -17,24 +17,47 @@ #include "AppenderFile.h" #include "Common.h" +#include "StringFormat.h" +#include "Log.h" #if PLATFORM == PLATFORM_WINDOWS # include #endif -AppenderFile::AppenderFile(uint8 id, std::string const& name, LogLevel level, const char* filename, const char* logDir, const char* mode, AppenderFlags flags, uint64 fileSize): - Appender(id, name, APPENDER_FILE, level, flags), +AppenderFile::AppenderFile(uint8 id, std::string const& name, LogLevel level, AppenderFlags flags, ExtraAppenderArgs extraArgs) : + Appender(id, name, level, flags), logfile(NULL), - _fileName(filename), - _logDir(logDir), - _maxFileSize(fileSize), + _logDir(sLog->GetLogsDir()), _fileSize(0) { + if (extraArgs.empty()) + throw InvalidAppenderArgsException(Trinity::StringFormat("Log::CreateAppenderFromConfig: Missing file name for appender %s\n", name.c_str())); + + _fileName = extraArgs[0]; + + char const* mode = "a"; + if (extraArgs.size() > 1) + mode = extraArgs[1]; + + if (flags & APPENDER_FLAGS_USE_TIMESTAMP) + { + size_t dot_pos = _fileName.find_last_of("."); + if (dot_pos != std::string::npos) + _fileName.insert(dot_pos, sLog->GetLogsTimestamp()); + else + _fileName += sLog->GetLogsTimestamp(); + } + + if (extraArgs.size() > 2) + _maxFileSize = atoi(extraArgs[2]); + else + _maxFileSize = 0; + _dynamicName = std::string::npos != _fileName.find("%s"); _backup = (flags & APPENDER_FLAGS_MAKE_FILE_BACKUP) != 0; if (!_dynamicName) - logfile = OpenFile(filename, mode, !strcmp(mode, "w") && _backup); + logfile = OpenFile(_fileName, mode, !strcmp(mode, "w") && _backup); } AppenderFile::~AppenderFile() diff --git a/src/server/shared/Logging/AppenderFile.h b/src/common/Logging/AppenderFile.h similarity index 83% rename from src/server/shared/Logging/AppenderFile.h rename to src/common/Logging/AppenderFile.h index 4082b34a2b4..c2781eb1ee9 100644 --- a/src/server/shared/Logging/AppenderFile.h +++ b/src/common/Logging/AppenderFile.h @@ -21,12 +21,15 @@ #include #include "Appender.h" -class AppenderFile: public Appender +class AppenderFile : public Appender { public: - AppenderFile(uint8 id, std::string const& name, LogLevel level, const char* filename, const char* logDir, const char* mode, AppenderFlags flags, uint64 maxSize); + typedef std::integral_constant::type TypeIndex; + + AppenderFile(uint8 id, std::string const& name, LogLevel level, AppenderFlags flags, ExtraAppenderArgs extraArgs); ~AppenderFile(); FILE* OpenFile(std::string const& name, std::string const& mode, bool backup); + AppenderType getType() const override { return TypeIndex::value; } private: void CloseFile(); diff --git a/src/server/shared/Logging/Log.cpp b/src/common/Logging/Log.cpp similarity index 79% rename from src/server/shared/Logging/Log.cpp rename to src/common/Logging/Log.cpp index 6c2580b3168..57d399a9d96 100644 --- a/src/server/shared/Logging/Log.cpp +++ b/src/common/Logging/Log.cpp @@ -22,16 +22,16 @@ #include "Util.h" #include "AppenderConsole.h" #include "AppenderFile.h" -#include "AppenderDB.h" #include "LogOperation.h" #include #include -Log::Log() : _ioService(nullptr), _strand(nullptr) +Log::Log() : AppenderId(0), lowestLogLevel(LOG_LEVEL_FATAL), _ioService(nullptr), _strand(nullptr) { m_logsTimestamp = "_" + GetTimestampStr(); - LoadFromConfig(); + RegisterAppender(); + RegisterAppender(); } Log::~Log() @@ -101,60 +101,21 @@ void Log::CreateAppenderFromConfig(std::string const& appenderName) if (size > 2) flags = AppenderFlags(atoi(*iter++)); - switch (type) + auto factoryFunction = appenderFactory.find(type); + if (factoryFunction == appenderFactory.end()) { - case APPENDER_CONSOLE: - { - AppenderConsole* appender = new AppenderConsole(NextAppenderId(), name, level, flags); - appenders[appender->getId()] = appender; - if (size > 3) - appender->InitColors(*iter++); - //fprintf(stdout, "Log::CreateAppenderFromConfig: Created Appender %s (%u), Type CONSOLE, Mask %u\n", appender->getName().c_str(), appender->getId(), appender->getLogLevel()); - break; - } - case APPENDER_FILE: - { - std::string filename; - std::string mode = "a"; + fprintf(stderr, "Log::CreateAppenderFromConfig: Unknown type %d for appender %s\n", type, name.c_str()); + return; + } - if (size < 4) - { - fprintf(stderr, "Log::CreateAppenderFromConfig: Missing file name for appender %s\n", name.c_str()); - return; - } - - filename = *iter++; - - if (size > 4) - mode = *iter++; - - if (flags & APPENDER_FLAGS_USE_TIMESTAMP) - { - size_t dot_pos = filename.find_last_of("."); - if (dot_pos != filename.npos) - filename.insert(dot_pos, m_logsTimestamp); - else - filename += m_logsTimestamp; - } - - uint64 maxFileSize = 0; - if (size > 5) - maxFileSize = atoi(*iter++); - - uint8 id = NextAppenderId(); - appenders[id] = new AppenderFile(id, name, level, filename.c_str(), m_logsDir.c_str(), mode.c_str(), flags, maxFileSize); - //fprintf(stdout, "Log::CreateAppenderFromConfig: Created Appender %s (%u), Type FILE, Mask %u, File %s, Mode %s\n", name.c_str(), id, level, filename.c_str(), mode.c_str()); - break; - } - case APPENDER_DB: - { - uint8 id = NextAppenderId(); - appenders[id] = new AppenderDB(id, name, level); - break; - } - default: - fprintf(stderr, "Log::CreateAppenderFromConfig: Unknown type %d for appender %s\n", type, name.c_str()); - break; + try + { + Appender* appender = factoryFunction->second(NextAppenderId(), name, level, flags, ExtraAppenderArgs(iter, tokens.end())); + appenders[appender->getId()] = appender; + } + catch (InvalidAppenderArgsException const& iaae) + { + fprintf(stderr, "%s", iaae.what()); } } @@ -250,7 +211,7 @@ void Log::ReadLoggersFromConfig() Close(); // Clean any Logger or Appender created - AppenderConsole* appender = new AppenderConsole(NextAppenderId(), "Console", LOG_LEVEL_DEBUG, APPENDER_FLAGS_NONE); + AppenderConsole* appender = new AppenderConsole(NextAppenderId(), "Console", LOG_LEVEL_DEBUG, APPENDER_FLAGS_NONE, ExtraAppenderArgs()); appenders[appender->getId()] = appender; Logger& logger = loggers[LOGGER_ROOT]; @@ -347,21 +308,29 @@ void Log::outCharDump(char const* str, uint32 accountId, uint64 guid, char const void Log::SetRealmId(uint32 id) { for (AppenderMap::iterator it = appenders.begin(); it != appenders.end(); ++it) - if (it->second && it->second->getType() == APPENDER_DB) - static_cast(it->second)->setRealmId(id); + it->second->setRealmId(id); } void Log::Close() { loggers.clear(); for (AppenderMap::iterator it = appenders.begin(); it != appenders.end(); ++it) - { delete it->second; - it->second = NULL; - } + appenders.clear(); } +void Log::Initialize(boost::asio::io_service* ioService) +{ + if (ioService) + { + _ioService = ioService; + _strand = new boost::asio::strand(*ioService); + } + + LoadFromConfig(); +} + void Log::LoadFromConfig() { Close(); diff --git a/src/server/shared/Logging/Log.h b/src/common/Logging/Log.h similarity index 91% rename from src/server/shared/Logging/Log.h rename to src/common/Logging/Log.h index ab7b2169ed2..a15bb4ad485 100644 --- a/src/server/shared/Logging/Log.h +++ b/src/common/Logging/Log.h @@ -44,19 +44,13 @@ class Log public: - static Log* instance(boost::asio::io_service* ioService = nullptr) + static Log* instance() { static Log instance; - - if (ioService != nullptr) - { - instance._ioService = ioService; - instance._strand = new boost::asio::strand(*ioService); - } - return &instance; } + void Initialize(boost::asio::io_service* ioService); void LoadFromConfig(); void Close(); bool ShouldLog(std::string const& type, LogLevel level) const; @@ -88,6 +82,18 @@ class Log void SetRealmId(uint32 id); + template + void RegisterAppender() + { + using Index = typename AppenderImpl::TypeIndex; + auto itr = appenderFactory.find(Index::value); + ASSERT(itr == appenderFactory.end()); + appenderFactory[Index::value] = &CreateAppender; + } + + std::string const& GetLogsDir() const { return m_logsDir; } + std::string const& GetLogsTimestamp() const { return m_logsTimestamp; } + private: static std::string GetTimestampStr(); void write(std::unique_ptr&& msg) const; @@ -100,6 +106,7 @@ class Log void ReadAppendersFromConfig(); void ReadLoggersFromConfig(); + AppenderCreatorMap appenderFactory; AppenderMap appenders; LoggerMap loggers; uint8 AppenderId; diff --git a/src/server/shared/Logging/LogOperation.cpp b/src/common/Logging/LogOperation.cpp similarity index 100% rename from src/server/shared/Logging/LogOperation.cpp rename to src/common/Logging/LogOperation.cpp diff --git a/src/server/shared/Logging/LogOperation.h b/src/common/Logging/LogOperation.h similarity index 100% rename from src/server/shared/Logging/LogOperation.h rename to src/common/Logging/LogOperation.h diff --git a/src/server/shared/Logging/Logger.cpp b/src/common/Logging/Logger.cpp similarity index 100% rename from src/server/shared/Logging/Logger.cpp rename to src/common/Logging/Logger.cpp diff --git a/src/server/shared/Logging/Logger.h b/src/common/Logging/Logger.h similarity index 100% rename from src/server/shared/Logging/Logger.h rename to src/common/Logging/Logger.h diff --git a/src/common/PrecompiledHeaders/commonPCH.cpp b/src/common/PrecompiledHeaders/commonPCH.cpp new file mode 100644 index 00000000000..52c623ca64a --- /dev/null +++ b/src/common/PrecompiledHeaders/commonPCH.cpp @@ -0,0 +1 @@ +#include "PrecompiledHeaders/commonPCH.h" diff --git a/src/common/PrecompiledHeaders/commonPCH.h b/src/common/PrecompiledHeaders/commonPCH.h new file mode 100644 index 00000000000..2d4f1ff4694 --- /dev/null +++ b/src/common/PrecompiledHeaders/commonPCH.h @@ -0,0 +1,13 @@ +#include "Define.h" +#include "Common.h" +#include "BoundingIntervalHierarchy.h" +#include "BoundingIntervalHierarchyWrapper.h" +#include "RegularGrid.h" +#include "Collision/VMapDefinitions.h" +#include "Collision/Maps/MapTree.h" +#include "Collision/Models/WorldModel.h" +#include "Collision/Models/ModelInstance.h" +#include "Collision/Models/GameObjectModel.h" +#include "Threading/ProducerConsumerQueue.h" +#include "Utilities/TaskScheduler.h" +#include "Utilities/EventMap.h" diff --git a/src/server/shared/Threading/Callback.h b/src/common/Threading/Callback.h similarity index 100% rename from src/server/shared/Threading/Callback.h rename to src/common/Threading/Callback.h diff --git a/src/server/shared/Threading/LockedQueue.h b/src/common/Threading/LockedQueue.h similarity index 100% rename from src/server/shared/Threading/LockedQueue.h rename to src/common/Threading/LockedQueue.h diff --git a/src/server/shared/Threading/ProcessPriority.h b/src/common/Threading/ProcessPriority.h similarity index 100% rename from src/server/shared/Threading/ProcessPriority.h rename to src/common/Threading/ProcessPriority.h diff --git a/src/server/shared/Threading/ProducerConsumerQueue.h b/src/common/Threading/ProducerConsumerQueue.h similarity index 100% rename from src/server/shared/Threading/ProducerConsumerQueue.h rename to src/common/Threading/ProducerConsumerQueue.h diff --git a/src/server/shared/Utilities/ByteConverter.h b/src/common/Utilities/ByteConverter.h similarity index 100% rename from src/server/shared/Utilities/ByteConverter.h rename to src/common/Utilities/ByteConverter.h diff --git a/src/server/shared/Utilities/Duration.h b/src/common/Utilities/Duration.h similarity index 100% rename from src/server/shared/Utilities/Duration.h rename to src/common/Utilities/Duration.h diff --git a/src/server/shared/Utilities/EventMap.cpp b/src/common/Utilities/EventMap.cpp similarity index 100% rename from src/server/shared/Utilities/EventMap.cpp rename to src/common/Utilities/EventMap.cpp diff --git a/src/server/shared/Utilities/EventMap.h b/src/common/Utilities/EventMap.h similarity index 100% rename from src/server/shared/Utilities/EventMap.h rename to src/common/Utilities/EventMap.h diff --git a/src/server/shared/Utilities/EventProcessor.cpp b/src/common/Utilities/EventProcessor.cpp similarity index 100% rename from src/server/shared/Utilities/EventProcessor.cpp rename to src/common/Utilities/EventProcessor.cpp diff --git a/src/server/shared/Utilities/EventProcessor.h b/src/common/Utilities/EventProcessor.h similarity index 100% rename from src/server/shared/Utilities/EventProcessor.h rename to src/common/Utilities/EventProcessor.h diff --git a/src/server/shared/Utilities/StringFormat.h b/src/common/Utilities/StringFormat.h similarity index 100% rename from src/server/shared/Utilities/StringFormat.h rename to src/common/Utilities/StringFormat.h diff --git a/src/server/shared/Utilities/TaskScheduler.cpp b/src/common/Utilities/TaskScheduler.cpp similarity index 100% rename from src/server/shared/Utilities/TaskScheduler.cpp rename to src/common/Utilities/TaskScheduler.cpp diff --git a/src/server/shared/Utilities/TaskScheduler.h b/src/common/Utilities/TaskScheduler.h similarity index 100% rename from src/server/shared/Utilities/TaskScheduler.h rename to src/common/Utilities/TaskScheduler.h diff --git a/src/server/shared/Utilities/Timer.h b/src/common/Utilities/Timer.h similarity index 100% rename from src/server/shared/Utilities/Timer.h rename to src/common/Utilities/Timer.h diff --git a/src/server/shared/Utilities/Util.cpp b/src/common/Utilities/Util.cpp similarity index 100% rename from src/server/shared/Utilities/Util.cpp rename to src/common/Utilities/Util.cpp diff --git a/src/server/shared/Utilities/Util.h b/src/common/Utilities/Util.h similarity index 100% rename from src/server/shared/Utilities/Util.h rename to src/common/Utilities/Util.h diff --git a/src/genrev/CMakeLists.txt b/src/genrev/CMakeLists.txt index e72643c6a6b..05db165fe00 100644 --- a/src/genrev/CMakeLists.txt +++ b/src/genrev/CMakeLists.txt @@ -9,7 +9,7 @@ # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # Need to pass old ${CMAKE_BINARY_DIR} as param because its different at build stage -add_custom_target(revision.h ALL +add_custom_target(revision_data.h ALL COMMAND "${CMAKE_COMMAND}" -DBUILDDIR="${CMAKE_BINARY_DIR}" -P "${CMAKE_SOURCE_DIR}/cmake/genrev.cmake" "${CMAKE_BINARY_DIR}" WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" ) diff --git a/src/server/CMakeLists.txt b/src/server/CMakeLists.txt index ae710d0bfab..32118db6a62 100644 --- a/src/server/CMakeLists.txt +++ b/src/server/CMakeLists.txt @@ -12,26 +12,21 @@ # This to stop a few silly crashes that could have been avoided IF people # weren't doing some -O3 psychooptimizations etc. +find_package(MySQL REQUIRED) + if(CMAKE_COMPILER_IS_GNUCXX AND NOT MINGW) add_definitions(-fno-delete-null-pointer-checks) endif() -if( SERVERS ) - set(sources_windows_Debugging - ${CMAKE_SOURCE_DIR}/src/server/shared/Debugging/WheatyExceptionReport.cpp - ${CMAKE_SOURCE_DIR}/src/server/shared/Debugging/WheatyExceptionReport.h - ) - add_subdirectory(shared) - add_subdirectory(game) - add_subdirectory(collision) - add_subdirectory(authserver) +set(sources_windows_Debugging + ${CMAKE_SOURCE_DIR}/src/common/Debugging/WheatyExceptionReport.cpp + ${CMAKE_SOURCE_DIR}/src/common/Debugging/WheatyExceptionReport.h +) +add_subdirectory(database) +add_subdirectory(shared) +add_subdirectory(game) +add_subdirectory(authserver) add_subdirectory(ipc) add_subdirectory(bnetserver) - add_subdirectory(scripts) - add_subdirectory(worldserver) -else() - if( TOOLS ) - add_subdirectory(collision) - add_subdirectory(shared) - endif() -endif() +add_subdirectory(scripts) +add_subdirectory(worldserver) diff --git a/src/server/authserver/CMakeLists.txt b/src/server/authserver/CMakeLists.txt index 7c76df5d06c..a8e35a8d9ef 100644 --- a/src/server/authserver/CMakeLists.txt +++ b/src/server/authserver/CMakeLists.txt @@ -43,24 +43,23 @@ endif() include_directories( ${CMAKE_BINARY_DIR} - ${CMAKE_SOURCE_DIR}/dep/cppformat - ${CMAKE_SOURCE_DIR}/dep/process - ${CMAKE_SOURCE_DIR}/src/server/shared - ${CMAKE_SOURCE_DIR}/src/server/shared/Configuration - ${CMAKE_SOURCE_DIR}/src/server/shared/Database - ${CMAKE_SOURCE_DIR}/src/server/shared/Debugging - ${CMAKE_SOURCE_DIR}/src/server/shared/Packets - ${CMAKE_SOURCE_DIR}/src/server/shared/Cryptography - ${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/Threading - ${CMAKE_SOURCE_DIR}/src/server/shared/Updater - ${CMAKE_SOURCE_DIR}/src/server/shared/Utilities - ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/Authentication ${CMAKE_CURRENT_SOURCE_DIR}/Realms ${CMAKE_CURRENT_SOURCE_DIR}/Server + ${CMAKE_SOURCE_DIR}/dep/cppformat + ${CMAKE_SOURCE_DIR}/src/common/ + ${CMAKE_SOURCE_DIR}/src/common/Configuration + ${CMAKE_SOURCE_DIR}/src/common/Cryptography + ${CMAKE_SOURCE_DIR}/src/common/Debugging + ${CMAKE_SOURCE_DIR}/src/common/Logging + ${CMAKE_SOURCE_DIR}/src/common/Threading + ${CMAKE_SOURCE_DIR}/src/common/Utilities + ${CMAKE_SOURCE_DIR}/src/server/database + ${CMAKE_SOURCE_DIR}/src/server/database/Database + ${CMAKE_SOURCE_DIR}/src/server/database/Logging + ${CMAKE_SOURCE_DIR}/src/server/shared/Networking + ${CMAKE_SOURCE_DIR}/src/server/shared/Packets + ${CMAKE_SOURCE_DIR}/src/server/shared/Service ${MYSQL_INCLUDE_DIR} ${OPENSSL_INCLUDE_DIR} ${VALGRIND_INCLUDE_DIR} @@ -73,8 +72,6 @@ add_executable(authserver ${authserver_PCH_SRC} ) -add_dependencies(authserver revision.h) - if( NOT WIN32 ) set_target_properties(authserver PROPERTIES COMPILE_DEFINITIONS _TRINITY_REALM_CONFIG="${CONF_DIR}/authserver.conf" @@ -82,8 +79,10 @@ if( NOT WIN32 ) endif() target_link_libraries(authserver + common shared format + database ${MYSQL_LIBRARY} ${OPENSSL_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} diff --git a/src/server/authserver/Main.cpp b/src/server/authserver/Main.cpp index 9a3bd6a58dd..205053c47ee 100644 --- a/src/server/authserver/Main.cpp +++ b/src/server/authserver/Main.cpp @@ -30,9 +30,10 @@ #include "DatabaseEnv.h" #include "DatabaseLoader.h" #include "Log.h" +#include "AppenderDB.h" #include "ProcessPriority.h" #include "RealmList.h" -#include "SystemConfig.h" +#include "GitRevision.h" #include "Util.h" #include #include @@ -99,7 +100,10 @@ int main(int argc, char** argv) return 1; } - TC_LOG_INFO("server.authserver", "%s (authserver)", _FULLVERSION); + sLog->RegisterAppender(); + sLog->Initialize(nullptr); + + TC_LOG_INFO("server.authserver", "%s (authserver)", GitRevision::GetFullVersion()); TC_LOG_INFO("server.authserver", " to stop.\n"); TC_LOG_INFO("server.authserver", "Using configuration file %s.", configFile.c_str()); TC_LOG_INFO("server.authserver", "Using SSL version: %s (library: %s)", OPENSSL_VERSION_TEXT, SSLeay_version(SSLEAY_VERSION)); @@ -289,7 +293,7 @@ variables_map GetConsoleArguments(int argc, char** argv, std::string& configFile if (variablesMap.count("help")) std::cout << all << "\n"; else if (variablesMap.count("version")) - std::cout << _FULLVERSION << "\n"; + std::cout << GitRevision::GetFullVersion() << "\n"; return variablesMap; } diff --git a/src/server/authserver/authserver.conf.dist b/src/server/authserver/authserver.conf.dist index ba9cb5b23b4..437ec221e94 100644 --- a/src/server/authserver/authserver.conf.dist +++ b/src/server/authserver/authserver.conf.dist @@ -182,7 +182,7 @@ Updates.EnableDatabases = 0 Updates.SourcePath = "" # -# Updates.SourcePath +# Updates.MySqlCLIPath # Description: The path to your mysql cli binary. # If the path is left empty, built-in path from cmake is used. # Example: "C:/Program Files/MySQL/MySQL Server 5.6/bin/mysql.exe" diff --git a/src/server/authserver/authserver.rc b/src/server/authserver/authserver.rc index e0d972d9351..ca8fc9f031f 100644 --- a/src/server/authserver/authserver.rc +++ b/src/server/authserver/authserver.rc @@ -17,7 +17,7 @@ */ #include "resource.h" -#include "revision.h" +#include "revision_data.h" #define APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// diff --git a/src/server/bnetserver/CMakeLists.txt b/src/server/bnetserver/CMakeLists.txt index 15d55f2e8cd..40b52afd0b1 100644 --- a/src/server/bnetserver/CMakeLists.txt +++ b/src/server/bnetserver/CMakeLists.txt @@ -45,25 +45,29 @@ endif() include_directories( ${CMAKE_BINARY_DIR} - ${CMAKE_SOURCE_DIR}/dep/zmqpp - ${CMAKE_SOURCE_DIR}/dep/cppformat - ${CMAKE_SOURCE_DIR}/src/server/shared - ${CMAKE_SOURCE_DIR}/src/server/shared/Configuration - ${CMAKE_SOURCE_DIR}/src/server/shared/Database - ${CMAKE_SOURCE_DIR}/src/server/shared/Debugging - ${CMAKE_SOURCE_DIR}/src/server/shared/Packets - ${CMAKE_SOURCE_DIR}/src/server/shared/Cryptography - ${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/Threading - ${CMAKE_SOURCE_DIR}/src/server/shared/Utilities - ${CMAKE_SOURCE_DIR}/src/server/ipc ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/Authentication ${CMAKE_CURRENT_SOURCE_DIR}/Realms ${CMAKE_CURRENT_SOURCE_DIR}/Server ${CMAKE_CURRENT_SOURCE_DIR}/Packets + ${CMAKE_SOURCE_DIR}/dep/cppformat + ${CMAKE_SOURCE_DIR}/dep/zmqpp + ${CMAKE_SOURCE_DIR}/src/common + ${CMAKE_SOURCE_DIR}/src/common/Configuration + ${CMAKE_SOURCE_DIR}/src/common/Cryptography + ${CMAKE_SOURCE_DIR}/src/common/Cryptography/Authentication + ${CMAKE_SOURCE_DIR}/src/common/Debugging + ${CMAKE_SOURCE_DIR}/src/common/Logging + ${CMAKE_SOURCE_DIR}/src/common/Threading + ${CMAKE_SOURCE_DIR}/src/common/Utilities + ${CMAKE_SOURCE_DIR}/src/server/database + ${CMAKE_SOURCE_DIR}/src/server/database/Database + ${CMAKE_SOURCE_DIR}/src/server/database/Logging + ${CMAKE_SOURCE_DIR}/src/server/ipc + ${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/Service ${MYSQL_INCLUDE_DIR} ${OPENSSL_INCLUDE_DIR} ${VALGRIND_INCLUDE_DIR} @@ -75,8 +79,6 @@ add_executable(bnetserver ${bnetserver_PCH_SRC} ) -add_dependencies(bnetserver revision.h) - if( NOT WIN32 ) set_target_properties(bnetserver PROPERTIES COMPILE_DEFINITIONS _TRINITY_BNET_CONFIG="${CONF_DIR}/bnetserver.conf" @@ -84,6 +86,8 @@ if( NOT WIN32 ) endif() target_link_libraries(bnetserver + common + database ipc shared format diff --git a/src/server/bnetserver/Main.cpp b/src/server/bnetserver/Main.cpp index 678e24c4682..858d0bcd640 100644 --- a/src/server/bnetserver/Main.cpp +++ b/src/server/bnetserver/Main.cpp @@ -33,7 +33,7 @@ #include "Log.h" #include "ProcessPriority.h" #include "RealmList.h" -#include "SystemConfig.h" +#include "GitRevision.h" #include "Util.h" #include "ZmqContext.h" #include "DatabaseLoader.h" @@ -77,7 +77,7 @@ int main(int argc, char** argv) return 1; } - TC_LOG_INFO("server.bnetserver", "%s (bnetserver)", _FULLVERSION); + TC_LOG_INFO("server.bnetserver", "%s (bnetserver)", GitRevision::GetFullVersion()); TC_LOG_INFO("server.bnetserver", " to stop.\n"); TC_LOG_INFO("server.bnetserver", "Using configuration file %s.", configFile.c_str()); TC_LOG_INFO("server.bnetserver", "Using SSL version: %s (library: %s)", OPENSSL_VERSION_TEXT, SSLeay_version(SSLEAY_VERSION)); diff --git a/src/server/collision/CMakeLists.txt b/src/server/collision/CMakeLists.txt deleted file mode 100644 index f0f5cef5985..00000000000 --- a/src/server/collision/CMakeLists.txt +++ /dev/null @@ -1,98 +0,0 @@ -# Copyright (C) 2008-2015 TrinityCore -# -# This file is free software; as a special exception the author gives -# unlimited permission to copy and/or distribute it, with or without -# modifications, as long as this notice is preserved. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the -# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -if( USE_COREPCH ) - include_directories(${CMAKE_CURRENT_BINARY_DIR}) -endif() - -file(GLOB_RECURSE sources_Management Management/*.cpp Management/*.h) -file(GLOB_RECURSE sources_Maps Maps/*.cpp Maps/*.h) -file(GLOB_RECURSE sources_Models Models/*.cpp Models/*.h) -file(GLOB sources_localdir *.cpp *.h) - -if (USE_COREPCH) - set(collision_STAT_PCH_HDR PrecompiledHeaders/collisionPCH.h) - set(collision_STAT_PCH_SRC PrecompiledHeaders/collisionPCH.cpp) -endif () - -set(collision_STAT_SRCS - ${collision_STAT_SRCS} - ${sources_Management} - ${sources_Maps} - ${sources_Models} - ${sources_localdir} -) - -include_directories( - ${CMAKE_BINARY_DIR} - ${CMAKE_SOURCE_DIR}/dep/g3dlite/include - ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour - ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour/Include - ${CMAKE_SOURCE_DIR}/dep/cppformat - ${CMAKE_SOURCE_DIR}/src/server/shared - ${CMAKE_SOURCE_DIR}/src/server/shared/Configuration - ${CMAKE_SOURCE_DIR}/src/server/shared/Debugging - ${CMAKE_SOURCE_DIR}/src/server/shared/Database - ${CMAKE_SOURCE_DIR}/src/server/shared/Debugging - ${CMAKE_SOURCE_DIR}/src/server/shared/Dynamic - ${CMAKE_SOURCE_DIR}/src/server/shared/Dynamic/LinkedReference - ${CMAKE_SOURCE_DIR}/src/server/shared/Logging - ${CMAKE_SOURCE_DIR}/src/server/shared/Threading - ${CMAKE_SOURCE_DIR}/src/server/shared/Packets - ${CMAKE_SOURCE_DIR}/src/server/shared/Utilities - ${CMAKE_SOURCE_DIR}/src/server/shared/DataStores - ${CMAKE_SOURCE_DIR}/src/server/ipc - ${CMAKE_SOURCE_DIR}/src/server/game/Addons - ${CMAKE_SOURCE_DIR}/src/server/game/Conditions - ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Item - ${CMAKE_SOURCE_DIR}/src/server/game/Entities/GameObject - ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Creature - ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Object - ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Object/Updates - ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Unit - ${CMAKE_SOURCE_DIR}/src/server/game/Combat - ${CMAKE_SOURCE_DIR}/src/server/game/Loot - ${CMAKE_SOURCE_DIR}/src/server/game/Miscellaneous - ${CMAKE_SOURCE_DIR}/src/server/game/Grids - ${CMAKE_SOURCE_DIR}/src/server/game/Grids/Cells - ${CMAKE_SOURCE_DIR}/src/server/game/Grids/Notifiers - ${CMAKE_SOURCE_DIR}/src/server/game/Maps - ${CMAKE_SOURCE_DIR}/src/server/game/DataStores - ${CMAKE_SOURCE_DIR}/src/server/game/Movement/Waypoints - ${CMAKE_SOURCE_DIR}/src/server/game/Movement/Spline - ${CMAKE_SOURCE_DIR}/src/server/game/Movement - ${CMAKE_SOURCE_DIR}/src/server/game/Server - ${CMAKE_SOURCE_DIR}/src/server/game/Server/Protocol - ${CMAKE_SOURCE_DIR}/src/server/game/World - ${CMAKE_SOURCE_DIR}/src/server/game/Spells - ${CMAKE_SOURCE_DIR}/src/server/game/Spells/Auras - ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/Management - ${CMAKE_CURRENT_SOURCE_DIR}/Maps - ${CMAKE_CURRENT_SOURCE_DIR}/Models - ${MYSQL_INCLUDE_DIR} - ${VALGRIND_INCLUDE_DIR} -) - -GroupSources(${CMAKE_CURRENT_SOURCE_DIR}) - -add_library(collision STATIC - ${collision_STAT_SRCS} - ${collision_STAT_PCH_SRC} -) - -target_link_libraries(collision - shared -) - -# Generate precompiled header -if (USE_COREPCH) - add_cxx_pch(collision ${collision_STAT_PCH_HDR} ${collision_STAT_PCH_SRC}) -endif () diff --git a/src/server/collision/PrecompiledHeaders/collisionPCH.cpp b/src/server/collision/PrecompiledHeaders/collisionPCH.cpp deleted file mode 100644 index 36eae8e2b0d..00000000000 --- a/src/server/collision/PrecompiledHeaders/collisionPCH.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "collisionPCH.h" diff --git a/src/server/collision/PrecompiledHeaders/collisionPCH.h b/src/server/collision/PrecompiledHeaders/collisionPCH.h deleted file mode 100644 index ece2ef1b8ef..00000000000 --- a/src/server/collision/PrecompiledHeaders/collisionPCH.h +++ /dev/null @@ -1,9 +0,0 @@ -#include "Define.h" -#include "VMapDefinitions.h" -#include "MapTree.h" -#include "WorldModel.h" -#include "ModelInstance.h" -#include "BoundingIntervalHierarchy.h" -#include "RegularGrid.h" -#include "BoundingIntervalHierarchyWrapper.h" -#include "GameObjectModel.h" diff --git a/src/server/database/CMakeLists.txt b/src/server/database/CMakeLists.txt new file mode 100644 index 00000000000..2375f18d7b5 --- /dev/null +++ b/src/server/database/CMakeLists.txt @@ -0,0 +1,75 @@ +# Copyright (C) 2008-2015 TrinityCore +# +# This file is free software; as a special exception the author gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +find_package(MySQL REQUIRED) + +if( USE_COREPCH ) + include_directories(${CMAKE_CURRENT_BINARY_DIR}) +endif() + +file(GLOB_RECURSE sources_Database Database/*.cpp Database/*.h) +file(GLOB_RECURSE sources_Logging Logging/*.cpp Logging/*.h) +file(GLOB_RECURSE sources_Updater Updater/*.cpp Updater/*.h) + +file(GLOB sources_localdir *.cpp *.h) + +# +# Build shared sourcelist +# + +if (USE_COREPCH) + set(database_STAT_PCH_HDR PrecompiledHeaders/databasePCH.h) + set(database_STAT_PCH_SRC PrecompiledHeaders/databasePCH.cpp) +endif() + +set(database_STAT_SRCS + ${database_STAT_SRCS} + ${sources_Database} + ${sources_Logging} + ${sources_Updater} +) + +# Do NOT add any extra include directory unless it does not create unneeded extra dependencies, +# and specially, not add any dependency to neither of these: shared, game, scripts +# This way we ensure that if either a PR does that without modifying this file, +# a compile error will be generated, either this file will be modified so it +# is detected more easily. +# While it is OK to include files from other libs as long as they don't require +# linkage (enums, defines...) it is discouraged to do so unless necessary, as it will pullute +# include_directories leading to further unnoticed dependency aditions +# Linker Depencency requirements: common +include_directories( + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/Database + ${CMAKE_CURRENT_SOURCE_DIR}/Updater + ${CMAKE_SOURCE_DIR}/dep/cppformat + ${CMAKE_SOURCE_DIR}/dep/process + ${CMAKE_SOURCE_DIR}/src/common/ + ${CMAKE_SOURCE_DIR}/src/common/Configuration + ${CMAKE_SOURCE_DIR}/src/common/Debugging + ${CMAKE_SOURCE_DIR}/src/common/Logging + ${CMAKE_SOURCE_DIR}/src/common/Threading + ${CMAKE_SOURCE_DIR}/src/common/Utilities + ${MYSQL_INCLUDE_DIR} + ${OPENSSL_INCLUDE_DIR} + ${VALGRIND_INCLUDE_DIR} +) + +GroupSources(${CMAKE_CURRENT_SOURCE_DIR}) + +add_library(database STATIC + ${database_STAT_SRCS} + ${database_STAT_PCH_SRC} +) + +# Generate precompiled header +if (USE_COREPCH) + add_cxx_pch(database ${database_STAT_PCH_HDR} ${database_STAT_PCH_SRC}) +endif () diff --git a/src/server/shared/Database/AdhocStatement.cpp b/src/server/database/Database/AdhocStatement.cpp similarity index 100% rename from src/server/shared/Database/AdhocStatement.cpp rename to src/server/database/Database/AdhocStatement.cpp diff --git a/src/server/shared/Database/AdhocStatement.h b/src/server/database/Database/AdhocStatement.h similarity index 100% rename from src/server/shared/Database/AdhocStatement.h rename to src/server/database/Database/AdhocStatement.h diff --git a/src/server/shared/Database/DatabaseEnv.h b/src/server/database/Database/DatabaseEnv.h similarity index 100% rename from src/server/shared/Database/DatabaseEnv.h rename to src/server/database/Database/DatabaseEnv.h diff --git a/src/server/shared/Database/DatabaseLoader.cpp b/src/server/database/Database/DatabaseLoader.cpp similarity index 100% rename from src/server/shared/Database/DatabaseLoader.cpp rename to src/server/database/Database/DatabaseLoader.cpp diff --git a/src/server/shared/Database/DatabaseLoader.h b/src/server/database/Database/DatabaseLoader.h similarity index 100% rename from src/server/shared/Database/DatabaseLoader.h rename to src/server/database/Database/DatabaseLoader.h diff --git a/src/server/shared/Database/DatabaseWorker.cpp b/src/server/database/Database/DatabaseWorker.cpp similarity index 100% rename from src/server/shared/Database/DatabaseWorker.cpp rename to src/server/database/Database/DatabaseWorker.cpp diff --git a/src/server/shared/Database/DatabaseWorker.h b/src/server/database/Database/DatabaseWorker.h similarity index 100% rename from src/server/shared/Database/DatabaseWorker.h rename to src/server/database/Database/DatabaseWorker.h diff --git a/src/server/shared/Database/DatabaseWorkerPool.h b/src/server/database/Database/DatabaseWorkerPool.h similarity index 100% rename from src/server/shared/Database/DatabaseWorkerPool.h rename to src/server/database/Database/DatabaseWorkerPool.h diff --git a/src/server/shared/Database/Field.cpp b/src/server/database/Database/Field.cpp similarity index 100% rename from src/server/shared/Database/Field.cpp rename to src/server/database/Database/Field.cpp diff --git a/src/server/shared/Database/Field.h b/src/server/database/Database/Field.h similarity index 100% rename from src/server/shared/Database/Field.h rename to src/server/database/Database/Field.h diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.cpp b/src/server/database/Database/Implementation/CharacterDatabase.cpp similarity index 100% rename from src/server/shared/Database/Implementation/CharacterDatabase.cpp rename to src/server/database/Database/Implementation/CharacterDatabase.cpp diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.h b/src/server/database/Database/Implementation/CharacterDatabase.h similarity index 100% rename from src/server/shared/Database/Implementation/CharacterDatabase.h rename to src/server/database/Database/Implementation/CharacterDatabase.h diff --git a/src/server/shared/Database/Implementation/LoginDatabase.cpp b/src/server/database/Database/Implementation/LoginDatabase.cpp similarity index 100% rename from src/server/shared/Database/Implementation/LoginDatabase.cpp rename to src/server/database/Database/Implementation/LoginDatabase.cpp diff --git a/src/server/shared/Database/Implementation/LoginDatabase.h b/src/server/database/Database/Implementation/LoginDatabase.h similarity index 100% rename from src/server/shared/Database/Implementation/LoginDatabase.h rename to src/server/database/Database/Implementation/LoginDatabase.h diff --git a/src/server/shared/Database/Implementation/WorldDatabase.cpp b/src/server/database/Database/Implementation/WorldDatabase.cpp similarity index 100% rename from src/server/shared/Database/Implementation/WorldDatabase.cpp rename to src/server/database/Database/Implementation/WorldDatabase.cpp diff --git a/src/server/shared/Database/Implementation/WorldDatabase.h b/src/server/database/Database/Implementation/WorldDatabase.h similarity index 100% rename from src/server/shared/Database/Implementation/WorldDatabase.h rename to src/server/database/Database/Implementation/WorldDatabase.h diff --git a/src/server/shared/Database/MySQLConnection.cpp b/src/server/database/Database/MySQLConnection.cpp similarity index 100% rename from src/server/shared/Database/MySQLConnection.cpp rename to src/server/database/Database/MySQLConnection.cpp diff --git a/src/server/shared/Database/MySQLConnection.h b/src/server/database/Database/MySQLConnection.h similarity index 100% rename from src/server/shared/Database/MySQLConnection.h rename to src/server/database/Database/MySQLConnection.h diff --git a/src/server/shared/Database/MySQLThreading.h b/src/server/database/Database/MySQLThreading.h similarity index 100% rename from src/server/shared/Database/MySQLThreading.h rename to src/server/database/Database/MySQLThreading.h diff --git a/src/server/shared/Database/PreparedStatement.cpp b/src/server/database/Database/PreparedStatement.cpp similarity index 100% rename from src/server/shared/Database/PreparedStatement.cpp rename to src/server/database/Database/PreparedStatement.cpp diff --git a/src/server/shared/Database/PreparedStatement.h b/src/server/database/Database/PreparedStatement.h similarity index 100% rename from src/server/shared/Database/PreparedStatement.h rename to src/server/database/Database/PreparedStatement.h diff --git a/src/server/shared/Database/QueryHolder.cpp b/src/server/database/Database/QueryHolder.cpp similarity index 100% rename from src/server/shared/Database/QueryHolder.cpp rename to src/server/database/Database/QueryHolder.cpp diff --git a/src/server/shared/Database/QueryHolder.h b/src/server/database/Database/QueryHolder.h similarity index 100% rename from src/server/shared/Database/QueryHolder.h rename to src/server/database/Database/QueryHolder.h diff --git a/src/server/shared/Database/QueryResult.cpp b/src/server/database/Database/QueryResult.cpp similarity index 100% rename from src/server/shared/Database/QueryResult.cpp rename to src/server/database/Database/QueryResult.cpp diff --git a/src/server/shared/Database/QueryResult.h b/src/server/database/Database/QueryResult.h similarity index 100% rename from src/server/shared/Database/QueryResult.h rename to src/server/database/Database/QueryResult.h diff --git a/src/server/shared/Database/SQLOperation.h b/src/server/database/Database/SQLOperation.h similarity index 100% rename from src/server/shared/Database/SQLOperation.h rename to src/server/database/Database/SQLOperation.h diff --git a/src/server/shared/Database/Transaction.cpp b/src/server/database/Database/Transaction.cpp similarity index 100% rename from src/server/shared/Database/Transaction.cpp rename to src/server/database/Database/Transaction.cpp diff --git a/src/server/shared/Database/Transaction.h b/src/server/database/Database/Transaction.h similarity index 100% rename from src/server/shared/Database/Transaction.h rename to src/server/database/Database/Transaction.h diff --git a/src/server/shared/Logging/AppenderDB.cpp b/src/server/database/Logging/AppenderDB.cpp similarity index 91% rename from src/server/shared/Logging/AppenderDB.cpp rename to src/server/database/Logging/AppenderDB.cpp index 8a329ea3a0f..9e6ab1a057c 100644 --- a/src/server/shared/Logging/AppenderDB.cpp +++ b/src/server/database/Logging/AppenderDB.cpp @@ -18,8 +18,8 @@ #include "AppenderDB.h" #include "Database/DatabaseEnv.h" -AppenderDB::AppenderDB(uint8 id, std::string const& name, LogLevel level) - : Appender(id, name, APPENDER_DB, level), realmId(0), enabled(false) { } +AppenderDB::AppenderDB(uint8 id, std::string const& name, LogLevel level, AppenderFlags /*flags*/, ExtraAppenderArgs /*extraArgs*/) + : Appender(id, name, level), realmId(0), enabled(false) { } AppenderDB::~AppenderDB() { } diff --git a/src/server/shared/Logging/AppenderDB.h b/src/server/database/Logging/AppenderDB.h similarity index 75% rename from src/server/shared/Logging/AppenderDB.h rename to src/server/database/Logging/AppenderDB.h index 09affdb46f1..50607fd8136 100644 --- a/src/server/shared/Logging/AppenderDB.h +++ b/src/server/database/Logging/AppenderDB.h @@ -23,10 +23,13 @@ class AppenderDB: public Appender { public: - AppenderDB(uint8 _id, std::string const& _name, LogLevel level); + typedef std::integral_constant::type TypeIndex; + + AppenderDB(uint8 id, std::string const& name, LogLevel level, AppenderFlags flags, ExtraAppenderArgs extraArgs); ~AppenderDB(); - void setRealmId(uint32 realmId); + void setRealmId(uint32 realmId) override; + AppenderType getType() const override { return TypeIndex::value; } private: uint32 realmId; diff --git a/src/server/database/PrecompiledHeaders/databasePCH.cpp b/src/server/database/PrecompiledHeaders/databasePCH.cpp new file mode 100644 index 00000000000..f84a52be82a --- /dev/null +++ b/src/server/database/PrecompiledHeaders/databasePCH.cpp @@ -0,0 +1 @@ +#include "PrecompiledHeaders/databasePCH.h" diff --git a/src/server/database/PrecompiledHeaders/databasePCH.h b/src/server/database/PrecompiledHeaders/databasePCH.h new file mode 100644 index 00000000000..d524d52ade0 --- /dev/null +++ b/src/server/database/PrecompiledHeaders/databasePCH.h @@ -0,0 +1,23 @@ +#include "Config.h" +#include "Database/AdhocStatement.h" +#include "Database/DatabaseEnv.h" +#include "Database/DatabaseLoader.h" +#include "Database/DatabaseWorker.h" +#include "Database/DatabaseWorkerPool.h" +#include "Database/Field.h" +#include "Database/MySQLConnection.h" +#include "Database/MySQLThreading.h" +#include "Database/PreparedStatement.h" +#include "Database/QueryHolder.h" +#include "Database/QueryResult.h" +#include "Database/SQLOperation.h" +#include "Database/Transaction.h" +#include "Logging/Appender.h" +#include "Logging/AppenderConsole.h" +#include "Logging/AppenderDB.h" +#include "Logging/AppenderFile.h" +#include "Logging/Log.h" +#include "Logging/LogOperation.h" +#include "Logging/Logger.h" +#include "Updater/DBUpdater.h" +#include "Updater/UpdateFetcher.h" diff --git a/src/server/shared/Updater/DBUpdater.cpp b/src/server/database/Updater/DBUpdater.cpp similarity index 98% rename from src/server/shared/Updater/DBUpdater.cpp rename to src/server/database/Updater/DBUpdater.cpp index 7b39062222e..ebdd6604fef 100644 --- a/src/server/shared/Updater/DBUpdater.cpp +++ b/src/server/database/Updater/DBUpdater.cpp @@ -17,7 +17,7 @@ #include "DBUpdater.h" #include "Log.h" -#include "revision.h" +#include "GitRevision.h" #include "UpdateFetcher.h" #include "DatabaseLoader.h" #include "Config.h" @@ -40,7 +40,7 @@ std::string DBUpdater::GetSourceDirectory() if (!entry.empty()) return entry; else - return _SOURCE_DIRECTORY; + return GitRevision::GetSourceDirectory(); } template @@ -50,7 +50,7 @@ std::string DBUpdater::GetMySqlCli() if (!entry.empty()) return entry; else - return _MYSQL_EXECUTABLE; + return GitRevision::GetMySQLExecutable(); } // Auth Database @@ -95,7 +95,7 @@ std::string DBUpdater::GetTableName() template<> std::string DBUpdater::GetBaseFile() { - return _FULL_DATABASE; + return GitRevision::GetFullDatabase(); } template<> diff --git a/src/server/shared/Updater/DBUpdater.h b/src/server/database/Updater/DBUpdater.h similarity index 100% rename from src/server/shared/Updater/DBUpdater.h rename to src/server/database/Updater/DBUpdater.h diff --git a/src/server/shared/Updater/UpdateFetcher.cpp b/src/server/database/Updater/UpdateFetcher.cpp similarity index 100% rename from src/server/shared/Updater/UpdateFetcher.cpp rename to src/server/database/Updater/UpdateFetcher.cpp diff --git a/src/server/shared/Updater/UpdateFetcher.h b/src/server/database/Updater/UpdateFetcher.h similarity index 100% rename from src/server/shared/Updater/UpdateFetcher.h rename to src/server/database/Updater/UpdateFetcher.h diff --git a/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp b/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp index 3da37811e93..88357571a33 100644 --- a/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp +++ b/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp @@ -457,7 +457,13 @@ BossAI::BossAI(Creature* creature, uint32 bossId) : ScriptedAI(creature), instance(creature->GetInstanceScript()), summons(creature), _boundary(instance ? instance->GetBossBoundary(bossId) : NULL), - _bossId(bossId) { } + _bossId(bossId) +{ + scheduler.SetValidator([this] + { + return !me->HasUnitState(UNIT_STATE_CASTING); + }); +} void BossAI::_Reset() { @@ -467,6 +473,7 @@ void BossAI::_Reset() me->ResetLootMode(); events.Reset(); summons.DespawnAll(); + scheduler.CancelAll(); if (instance) instance->SetBossState(_bossId, NOT_STARTED); } @@ -475,14 +482,13 @@ void BossAI::_JustDied() { events.Reset(); summons.DespawnAll(); + scheduler.CancelAll(); if (instance) instance->SetBossState(_bossId, DONE); } void BossAI::_EnterCombat() { - me->setActive(true); - DoZoneInCombat(); if (instance) { // bosses do not respawn, check only on enter combat @@ -493,6 +499,10 @@ void BossAI::_EnterCombat() } instance->SetBossState(_bossId, IN_PROGRESS); } + + me->setActive(true); + DoZoneInCombat(); + ScheduleTasks(); } void BossAI::TeleportCheaters() diff --git a/src/server/game/AI/ScriptedAI/ScriptedCreature.h b/src/server/game/AI/ScriptedAI/ScriptedCreature.h index d88b21f6318..40dd4b67ae9 100644 --- a/src/server/game/AI/ScriptedAI/ScriptedCreature.h +++ b/src/server/game/AI/ScriptedAI/ScriptedCreature.h @@ -23,6 +23,7 @@ #include "CreatureAI.h" #include "CreatureAIImpl.h" #include "InstanceScript.h" +#include "TaskScheduler.h" #define CAST_AI(a, b) (dynamic_cast(b)) #define ENSURE_AI(a,b) (EnsureAI(b)) @@ -359,6 +360,8 @@ class BossAI : public ScriptedAI // is supposed to run more than once virtual void ExecuteEvent(uint32 /*eventId*/) { } + virtual void ScheduleTasks() { } + void Reset() override { _Reset(); } void EnterCombat(Unit* /*who*/) override { _EnterCombat(); } void JustDied(Unit* /*killer*/) override { _JustDied(); } @@ -385,6 +388,7 @@ class BossAI : public ScriptedAI EventMap events; SummonList summons; + TaskScheduler scheduler; private: BossBoundaryMap const* const _boundary; diff --git a/src/server/game/AI/ScriptedAI/ScriptedEscortAI.h b/src/server/game/AI/ScriptedAI/ScriptedEscortAI.h index 1d71652c948..deabd1dc484 100644 --- a/src/server/game/AI/ScriptedAI/ScriptedEscortAI.h +++ b/src/server/game/AI/ScriptedAI/ScriptedEscortAI.h @@ -68,8 +68,8 @@ struct npc_escortAI : public ScriptedAI void EnterEvadeMode() override; - void UpdateAI(uint32 diff) override; //the "internal" update, calls UpdateEscortAI() - virtual void UpdateEscortAI(uint32 const diff); //used when it's needed to add code in update (abilities, scripted events, etc) + void UpdateAI(uint32 diff) override; // the "internal" update, calls UpdateEscortAI() + virtual void UpdateEscortAI(uint32 diff); // used when it's needed to add code in update (abilities, scripted events, etc) void MovementInform(uint32, uint32) override; diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp index 32d81fbe785..4644026c0c3 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.cpp +++ b/src/server/game/AI/SmartScripts/SmartScript.cpp @@ -123,13 +123,18 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u ObjectList* targets = GetTargets(e, unit); Creature* talker = me; Player* targetPlayer = NULL; + Unit* talkTarget = NULL; + if (targets) { for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) { if (IsCreature(*itr) && !(*itr)->ToCreature()->IsPet()) // Prevented sending text to pets. { - talker = (*itr)->ToCreature(); + if (e.action.talk.useTalkTarget) + talkTarget = (*itr)->ToCreature(); + else + talker = (*itr)->ToCreature(); break; } else if (IsPlayer(*itr)) @@ -148,7 +153,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u mTalkerEntry = talker->GetEntry(); mLastTextID = e.action.talk.textGroupID; mTextTimer = e.action.talk.duration; - Unit* talkTarget = NULL; + if (IsPlayer(GetLastInvoker())) // used for $vars in texts and whisper target talkTarget = GetLastInvoker(); else if (targetPlayer) diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.h b/src/server/game/AI/SmartScripts/SmartScriptMgr.h index f957d79e008..87bab275013 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.h +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.h @@ -427,7 +427,7 @@ enum SMART_SCRIPT_RESPAWN_CONDITION enum SMART_ACTION { SMART_ACTION_NONE = 0, // No action - SMART_ACTION_TALK = 1, // groupID from creature_text, duration to wait before TEXT_OVER event is triggered + SMART_ACTION_TALK = 1, // groupID from creature_text, duration to wait before TEXT_OVER event is triggered, useTalkTarget (0/1) - use target as talk target SMART_ACTION_SET_FACTION = 2, // FactionId (or 0 for default) SMART_ACTION_MORPH_TO_ENTRY_OR_MODEL = 3, // Creature_template entry(param1) OR ModelId (param2) (or 0 for both to demorph) SMART_ACTION_SOUND = 4, // SoundId, onlySelf @@ -554,6 +554,7 @@ struct SmartAction { uint32 textGroupID; uint32 duration; + uint32 useTalkTarget; } talk; struct diff --git a/src/server/game/Accounts/RBAC.h b/src/server/game/Accounts/RBAC.h index 1ae38e718ff..3b44e7a5205 100644 --- a/src/server/game/Accounts/RBAC.h +++ b/src/server/game/Accounts/RBAC.h @@ -703,6 +703,8 @@ enum RBACPermissions RBAC_PERM_COMMAND_INSTANCE_GET_BOSS_STATE = 796, RBAC_PERM_COMMAND_PVPSTATS = 797, RBAC_PERM_COMMAND_MODIFY_XP = 798, + // 799 - 834 6.x only + RBAC_PERM_COMMAND_DEBUG_LOADCELLS = 835, // custom permissions 1000+ RBAC_PERM_MAX diff --git a/src/server/game/Battlegrounds/BattlegroundMgr.cpp b/src/server/game/Battlegrounds/BattlegroundMgr.cpp index e50ee597307..1b290799e76 100644 --- a/src/server/game/Battlegrounds/BattlegroundMgr.cpp +++ b/src/server/game/Battlegrounds/BattlegroundMgr.cpp @@ -1069,7 +1069,8 @@ void BattlegroundMgr::ToggleArenaTesting() void BattlegroundMgr::SetHolidayWeekends(uint32 mask) { - for (uint32 bgtype = 1; bgtype < MAX_BATTLEGROUND_TYPE_ID; ++bgtype) + // The current code supports battlegrounds up to BattlegroundTypeId(31) + for (uint32 bgtype = 1; bgtype < MAX_BATTLEGROUND_TYPE_ID && bgtype < 32; ++bgtype) if (Battleground* bg = GetBattlegroundTemplate(BattlegroundTypeId(bgtype))) bg->SetHoliday((mask & (1 << bgtype)) != 0); } diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp index 12c80237423..3f11ad01fcb 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp @@ -882,7 +882,10 @@ bool BattlegroundWS::CheckAchievementCriteriaMeet(uint32 criteriaId, Player cons switch (criteriaId) { case BG_CRITERIA_CHECK_SAVE_THE_DAY: - return GetFlagState(player->GetTeam()) == BG_WS_FLAG_STATE_ON_BASE; + if (target) + if (Player const* playerTarget = target->ToPlayer()) + return GetFlagState(playerTarget->GetTeam()) == BG_WS_FLAG_STATE_ON_BASE; + return false; } return Battleground::CheckAchievementCriteriaMeet(criteriaId, player, target, miscValue); diff --git a/src/server/game/CMakeLists.txt b/src/server/game/CMakeLists.txt index 4a909869955..0d650b413eb 100644 --- a/src/server/game/CMakeLists.txt +++ b/src/server/game/CMakeLists.txt @@ -103,37 +103,6 @@ set(game_STAT_SRCS ) include_directories( - ${CMAKE_BINARY_DIR} - ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour - ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour/Include - ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Recast - ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Recast/Include - ${CMAKE_SOURCE_DIR}/dep/g3dlite/include - ${CMAKE_SOURCE_DIR}/dep/SFMT - ${CMAKE_SOURCE_DIR}/dep/cppformat - ${CMAKE_SOURCE_DIR}/dep/zlib - ${CMAKE_SOURCE_DIR}/dep/zmqpp - ${CMAKE_SOURCE_DIR}/src/server/collision - ${CMAKE_SOURCE_DIR}/src/server/collision/Management - ${CMAKE_SOURCE_DIR}/src/server/collision/Models - ${CMAKE_SOURCE_DIR}/src/server/collision/Maps - ${CMAKE_SOURCE_DIR}/src/server/shared - ${CMAKE_SOURCE_DIR}/src/server/shared/Configuration - ${CMAKE_SOURCE_DIR}/src/server/shared/Cryptography - ${CMAKE_SOURCE_DIR}/src/server/shared/Cryptography/Authentication - ${CMAKE_SOURCE_DIR}/src/server/shared/Database - ${CMAKE_SOURCE_DIR}/src/server/shared/DataStores - ${CMAKE_SOURCE_DIR}/src/server/shared/Debugging - ${CMAKE_SOURCE_DIR}/src/server/shared/Dynamic/LinkedReference - ${CMAKE_SOURCE_DIR}/src/server/shared/Dynamic - ${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/Threading - ${CMAKE_SOURCE_DIR}/src/server/shared/Updater - ${CMAKE_SOURCE_DIR}/src/server/shared/Utilities - ${CMAKE_SOURCE_DIR}/src/server/ipc - ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/Accounts ${CMAKE_CURRENT_SOURCE_DIR}/Achievements ${CMAKE_CURRENT_SOURCE_DIR}/Addons @@ -154,10 +123,9 @@ include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/Conditions ${CMAKE_CURRENT_SOURCE_DIR}/DataStores ${CMAKE_CURRENT_SOURCE_DIR}/DungeonFinding - ${CMAKE_CURRENT_SOURCE_DIR}/Entities ${CMAKE_CURRENT_SOURCE_DIR}/Entities/AreaTrigger - ${CMAKE_CURRENT_SOURCE_DIR}/Entities/Creature ${CMAKE_CURRENT_SOURCE_DIR}/Entities/Corpse + ${CMAKE_CURRENT_SOURCE_DIR}/Entities/Creature ${CMAKE_CURRENT_SOURCE_DIR}/Entities/DynamicObject ${CMAKE_CURRENT_SOURCE_DIR}/Entities/GameObject ${CMAKE_CURRENT_SOURCE_DIR}/Entities/Item @@ -167,14 +135,14 @@ include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/Entities/Pet ${CMAKE_CURRENT_SOURCE_DIR}/Entities/Player ${CMAKE_CURRENT_SOURCE_DIR}/Entities/Totem + ${CMAKE_CURRENT_SOURCE_DIR}/Entities/Transport ${CMAKE_CURRENT_SOURCE_DIR}/Entities/Unit ${CMAKE_CURRENT_SOURCE_DIR}/Entities/Vehicle - ${CMAKE_CURRENT_SOURCE_DIR}/Entities/Transport ${CMAKE_CURRENT_SOURCE_DIR}/Events ${CMAKE_CURRENT_SOURCE_DIR}/Globals + ${CMAKE_CURRENT_SOURCE_DIR}/Grids ${CMAKE_CURRENT_SOURCE_DIR}/Grids/Cells ${CMAKE_CURRENT_SOURCE_DIR}/Grids/Notifiers - ${CMAKE_CURRENT_SOURCE_DIR}/Grids ${CMAKE_CURRENT_SOURCE_DIR}/Groups ${CMAKE_CURRENT_SOURCE_DIR}/Guilds ${CMAKE_CURRENT_SOURCE_DIR}/Handlers @@ -184,28 +152,52 @@ include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/Maps ${CMAKE_CURRENT_SOURCE_DIR}/Miscellaneous ${CMAKE_CURRENT_SOURCE_DIR}/Movement - ${CMAKE_CURRENT_SOURCE_DIR}/Movement/Spline ${CMAKE_CURRENT_SOURCE_DIR}/Movement/MovementGenerators + ${CMAKE_CURRENT_SOURCE_DIR}/Movement/Spline ${CMAKE_CURRENT_SOURCE_DIR}/Movement/Waypoints ${CMAKE_CURRENT_SOURCE_DIR}/OutdoorPvP ${CMAKE_CURRENT_SOURCE_DIR}/Pools - ${CMAKE_CURRENT_SOURCE_DIR}/PrecompiledHeaders ${CMAKE_CURRENT_SOURCE_DIR}/Quests ${CMAKE_CURRENT_SOURCE_DIR}/Reputation ${CMAKE_CURRENT_SOURCE_DIR}/Scripting - ${CMAKE_CURRENT_SOURCE_DIR}/Server/Protocol ${CMAKE_CURRENT_SOURCE_DIR}/Server + ${CMAKE_CURRENT_SOURCE_DIR}/Server/Protocol ${CMAKE_CURRENT_SOURCE_DIR}/Skills ${CMAKE_CURRENT_SOURCE_DIR}/Spells ${CMAKE_CURRENT_SOURCE_DIR}/Spells/Auras ${CMAKE_CURRENT_SOURCE_DIR}/Texts - ${CMAKE_CURRENT_SOURCE_DIR}/Tools ${CMAKE_CURRENT_SOURCE_DIR}/Tickets + ${CMAKE_CURRENT_SOURCE_DIR}/Tools ${CMAKE_CURRENT_SOURCE_DIR}/Warden ${CMAKE_CURRENT_SOURCE_DIR}/Warden/Modules ${CMAKE_CURRENT_SOURCE_DIR}/Weather ${CMAKE_CURRENT_SOURCE_DIR}/World - ${CMAKE_SOURCE_DIR}/src/server/scripts/PrecompiledHeaders + ${CMAKE_SOURCE_DIR}/dep/cppformat + ${CMAKE_SOURCE_DIR}/dep/g3dlite/include + ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour/Include + ${CMAKE_SOURCE_DIR}/dep/zlib + ${CMAKE_SOURCE_DIR}/dep/zmqpp + ${CMAKE_SOURCE_DIR}/src/common + ${CMAKE_SOURCE_DIR}/src/common/Collision + ${CMAKE_SOURCE_DIR}/src/common/Collision/Management + ${CMAKE_SOURCE_DIR}/src/common/Collision/Maps + ${CMAKE_SOURCE_DIR}/src/common/Collision/Models + ${CMAKE_SOURCE_DIR}/src/common/Configuration + ${CMAKE_SOURCE_DIR}/src/common/Cryptography + ${CMAKE_SOURCE_DIR}/src/common/Cryptography/Authentication + ${CMAKE_SOURCE_DIR}/src/common/Debugging + ${CMAKE_SOURCE_DIR}/src/common/Logging + ${CMAKE_SOURCE_DIR}/src/common/Threading + ${CMAKE_SOURCE_DIR}/src/common/Utilities + ${CMAKE_SOURCE_DIR}/src/server/database + ${CMAKE_SOURCE_DIR}/src/server/database/Database + ${CMAKE_SOURCE_DIR}/src/server/ipc + ${CMAKE_SOURCE_DIR}/src/server/shared + ${CMAKE_SOURCE_DIR}/src/server/shared/DataStores + ${CMAKE_SOURCE_DIR}/src/server/shared/Dynamic + ${CMAKE_SOURCE_DIR}/src/server/shared/Dynamic/LinkedReference + ${CMAKE_SOURCE_DIR}/src/server/shared/Networking + ${CMAKE_SOURCE_DIR}/src/server/shared/Packets ${MYSQL_INCLUDE_DIR} ${OPENSSL_INCLUDE_DIR} ${VALGRIND_INCLUDE_DIR} @@ -219,8 +211,6 @@ add_library(game STATIC ${game_STAT_PCH_SRC} ) -add_dependencies(game revision.h) - # Generate precompiled header if (USE_COREPCH) add_cxx_pch(game ${game_STAT_PCH_HDR} ${game_STAT_PCH_SRC}) diff --git a/src/server/game/Chat/Chat.cpp b/src/server/game/Chat/Chat.cpp index 00fe8874398..00970742e13 100644 --- a/src/server/game/Chat/Chat.cpp +++ b/src/server/game/Chat/Chat.cpp @@ -186,13 +186,33 @@ bool ChatHandler::hasStringAbbr(const char* name, const char* part) return true; } -void ChatHandler::SendSysMessage(const char *str) +void ChatHandler::SendSysMessage(const char *str, bool escapeCharacters) { WorldPacket data; // need copy to prevent corruption by strtok call in LineFromMessage original string - char* buf = strdup(str); - char* pos = buf; + char* buf; + char* pos; + + if (escapeCharacters && strchr(str, '|')) + { + size_t startPos = 0; + std::ostringstream o; + while (const char* charPos = strchr(str + startPos, '|')) + { + o.write(str + startPos, charPos - str - startPos); + o << "||"; + startPos = charPos - str + 1; + } + o.write(str + startPos, strlen(str) - startPos); + buf = strdup(o.str().c_str()); + } + else + { + buf = strdup(str); + } + + pos = buf; while (char* line = LineFromMessage(pos)) { @@ -1241,7 +1261,7 @@ bool CliHandler::isAvailable(ChatCommand const& cmd) const return cmd.AllowConsole; } -void CliHandler::SendSysMessage(const char *str) +void CliHandler::SendSysMessage(const char *str, bool /*escapeCharacters*/) { m_print(m_callbackArg, str); m_print(m_callbackArg, "\r\n"); diff --git a/src/server/game/Chat/Chat.h b/src/server/game/Chat/Chat.h index dde65163a83..00d2ae39b6f 100644 --- a/src/server/game/Chat/Chat.h +++ b/src/server/game/Chat/Chat.h @@ -67,7 +67,7 @@ class ChatHandler // function with different implementation for chat/console virtual char const* GetTrinityString(uint32 entry) const; - virtual void SendSysMessage(char const* str); + virtual void SendSysMessage(char const* str, bool escapeCharacters = false); void SendSysMessage(uint32 entry); @@ -167,7 +167,7 @@ class CliHandler : public ChatHandler char const* GetTrinityString(uint32 entry) const override; bool isAvailable(ChatCommand const& cmd) const override; bool HasPermission(uint32 /*permission*/) const override { return true; } - void SendSysMessage(const char *str) override; + void SendSysMessage(const char *str, bool escapeCharacters) override; std::string GetNameLink() const override; bool needReportToTarget(Player* chr) const override; LocaleConstant GetSessionDbcLocale() const override; diff --git a/src/server/game/DataStores/DBCStructure.h b/src/server/game/DataStores/DBCStructure.h index aad1156af11..6f5292866a1 100644 --- a/src/server/game/DataStores/DBCStructure.h +++ b/src/server/game/DataStores/DBCStructure.h @@ -2377,7 +2377,12 @@ struct VehicleSeatEntry uint32 m_flagsB; // 45 // 46-57 added in 3.1, floats mostly - bool CanEnterOrExit() const { return (m_flags & VEHICLE_SEAT_FLAG_CAN_ENTER_OR_EXIT) != 0; } + bool CanEnterOrExit() const + { + return ((m_flags & VEHICLE_SEAT_FLAG_CAN_ENTER_OR_EXIT) != 0 || + //If it has anmation for enter/ride, means it can be entered/exited by logic + (m_flags & (VEHICLE_SEAT_FLAG_HAS_LOWER_ANIM_FOR_ENTER | VEHICLE_SEAT_FLAG_HAS_LOWER_ANIM_FOR_RIDE)) != 0); + } bool CanSwitchFromSeat() const { return (m_flags & VEHICLE_SEAT_FLAG_CAN_SWITCH) != 0; } bool IsUsableByOverride() const { return (m_flags & (VEHICLE_SEAT_FLAG_UNCONTROLLED | VEHICLE_SEAT_FLAG_UNK18) || (m_flagsB & (VEHICLE_SEAT_FLAG_B_USABLE_FORCED | VEHICLE_SEAT_FLAG_B_USABLE_FORCED_2 | diff --git a/src/server/game/DungeonFinding/LFGMgr.cpp b/src/server/game/DungeonFinding/LFGMgr.cpp index 9a83d79d496..5f406b2cc1e 100644 --- a/src/server/game/DungeonFinding/LFGMgr.cpp +++ b/src/server/game/DungeonFinding/LFGMgr.cpp @@ -580,7 +580,7 @@ void LFGMgr::JoinLfg(Player* player, uint8 roles, LfgDungeonSet& dungeons, const @param[in] guid Player or group guid */ -void LFGMgr::LeaveLfg(ObjectGuid guid) +void LFGMgr::LeaveLfg(ObjectGuid guid, bool disconnected) { ObjectGuid gguid = guid.IsGroup() ? guid : GetGroup(guid); @@ -641,7 +641,7 @@ void LFGMgr::LeaveLfg(ObjectGuid guid) break; case LFG_STATE_DUNGEON: case LFG_STATE_FINISHED_DUNGEON: - if (guid != gguid) // Player + if (guid != gguid && !disconnected) // Player SetState(guid, LFG_STATE_NONE); break; } diff --git a/src/server/game/DungeonFinding/LFGMgr.h b/src/server/game/DungeonFinding/LFGMgr.h index 1f84c3a651a..50a7c8ab196 100644 --- a/src/server/game/DungeonFinding/LFGMgr.h +++ b/src/server/game/DungeonFinding/LFGMgr.h @@ -405,7 +405,7 @@ class LFGMgr /// Join Lfg with selected roles, dungeons and comment void JoinLfg(Player* player, uint8 roles, LfgDungeonSet& dungeons, std::string const& comment); /// Leaves lfg - void LeaveLfg(ObjectGuid guid); + void LeaveLfg(ObjectGuid guid, bool disconnected = false); // LfgQueue /// Get last lfg state (NONE, DUNGEON or FINISHED_DUNGEON) diff --git a/src/server/game/DungeonFinding/LFGQueue.cpp b/src/server/game/DungeonFinding/LFGQueue.cpp index e396271d999..9c4ee583e7b 100644 --- a/src/server/game/DungeonFinding/LFGQueue.cpp +++ b/src/server/game/DungeonFinding/LFGQueue.cpp @@ -72,7 +72,7 @@ char const* GetCompatibleString(LfgCompatibility compatibles) case LFG_INCOMPATIBLES_NO_ROLES: return "Incompatible roles"; case LFG_INCOMPATIBLES_TOO_MUCH_PLAYERS: - return "Too much players"; + return "Too many players"; case LFG_INCOMPATIBLES_WRONG_GROUP_SIZE: return "Wrong group size"; default: @@ -80,6 +80,43 @@ char const* GetCompatibleString(LfgCompatibility compatibles) } } +std::string LFGQueue::GetDetailedMatchRoles(GuidList const& check) const +{ + if (check.empty()) + return ""; + + // need the guids in order to avoid duplicates + GuidSet guids(check.begin(), check.end()); + + std::ostringstream o; + + GuidSet::const_iterator it = guids.begin(); + o << it->GetRawValue(); + LfgQueueDataContainer::const_iterator itQueue = QueueDataStore.find(*it); + if (itQueue != QueueDataStore.end()) + { + // skip leader flag, log only dps/tank/healer + auto role = itQueue->second.roles.find(*it); + if (role != itQueue->second.roles.end()) + o << ' ' << GetRolesString(itQueue->second.roles.at(*it) & uint8(~PLAYER_ROLE_LEADER)); + } + + for (++it; it != guids.end(); ++it) + { + o << '|' << it->GetRawValue(); + itQueue = QueueDataStore.find(*it); + if (itQueue != QueueDataStore.end()) + { + // skip leader flag, log only dps/tank/healer + auto role = itQueue->second.roles.find(*it); + if (role != itQueue->second.roles.end()) + o << ' ' << GetRolesString(itQueue->second.roles.at(*it) & uint8(~PLAYER_ROLE_LEADER)); + } + } + + return o.str(); +} + void LFGQueue::AddToQueue(ObjectGuid guid) { LfgQueueDataContainer::iterator itQueue = QueueDataStore.find(guid); @@ -278,13 +315,13 @@ LfgCompatibility LFGQueue::FindNewGroups(GuidList& check, GuidList& all) std::string strGuids = ConcatenateGuids(check); LfgCompatibility compatibles = GetCompatibles(strGuids); - TC_LOG_DEBUG("lfg.queue.match.check", "Guids: (%s): %s - all(%s)", strGuids.c_str(), GetCompatibleString(compatibles), ConcatenateGuids(all).c_str()); + TC_LOG_DEBUG("lfg.queue.match.check", "Guids: (%s): %s - all(%s)", GetDetailedMatchRoles(check).c_str(), GetCompatibleString(compatibles), GetDetailedMatchRoles(all).c_str()); if (compatibles == LFG_COMPATIBILITY_PENDING) // Not previously cached, calculate compatibles = CheckCompatibility(check); if (compatibles == LFG_COMPATIBLES_BAD_STATES && sLFGMgr->AllQueued(check)) { - TC_LOG_DEBUG("lfg.queue.match.check", "Guids: (%s) compatibles (cached) changed from bad states to match", strGuids.c_str()); + TC_LOG_DEBUG("lfg.queue.match.check", "Guids: (%s) compatibles (cached) changed from bad states to match", GetDetailedMatchRoles(check).c_str()); SetCompatibles(strGuids, LFG_COMPATIBLES_MATCH); return LFG_COMPATIBLES_MATCH; } @@ -322,7 +359,7 @@ LfgCompatibility LFGQueue::CheckCompatibility(GuidList check) // Check for correct size if (check.size() > MAXGROUPSIZE || check.empty()) { - TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: (%s): Size wrong - Not compatibles", strGuids.c_str()); + TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: (%s): Size wrong - Not compatibles", GetDetailedMatchRoles(check).c_str()); return LFG_INCOMPATIBLES_WRONG_GROUP_SIZE; } @@ -336,7 +373,7 @@ LfgCompatibility LFGQueue::CheckCompatibility(GuidList check) LfgCompatibility child_compatibles = CheckCompatibility(check); if (child_compatibles < LFG_COMPATIBLES_WITH_LESS_PLAYERS) // Group not compatible { - TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: (%s) child %s not compatibles", strGuids.c_str(), ConcatenateGuids(check).c_str()); + TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: (%s) child %s not compatibles", strGuids.c_str(), GetDetailedMatchRoles(check).c_str()); SetCompatibles(strGuids, child_compatibles); return child_compatibles; } @@ -374,7 +411,7 @@ LfgCompatibility LFGQueue::CheckCompatibility(GuidList check) // Group with less that MAXGROUPSIZE members always compatible if (check.size() == 1 && numPlayers != MAXGROUPSIZE) { - TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: (%s) single group. Compatibles", strGuids.c_str()); + TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: (%s) single group. Compatibles", GetDetailedMatchRoles(check).c_str()); LfgQueueDataContainer::iterator itQueue = QueueDataStore.find(check.front()); LfgCompatibilityData data(LFG_COMPATIBLES_WITH_LESS_PLAYERS); @@ -388,14 +425,14 @@ LfgCompatibility LFGQueue::CheckCompatibility(GuidList check) if (numLfgGroups > 1) { - TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: (%s) More than one Lfggroup (%u)", strGuids.c_str(), numLfgGroups); + TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: (%s) More than one Lfggroup (%u)", GetDetailedMatchRoles(check).c_str(), numLfgGroups); SetCompatibles(strGuids, LFG_INCOMPATIBLES_MULTIPLE_LFG_GROUPS); return LFG_INCOMPATIBLES_MULTIPLE_LFG_GROUPS; } if (numPlayers > MAXGROUPSIZE) { - TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: (%s) Too much players (%u)", strGuids.c_str(), numPlayers); + TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: (%s) Too many players (%u)", GetDetailedMatchRoles(check).c_str(), numPlayers); SetCompatibles(strGuids, LFG_INCOMPATIBLES_TOO_MUCH_PLAYERS); return LFG_INCOMPATIBLES_TOO_MUCH_PLAYERS; } @@ -423,7 +460,7 @@ LfgCompatibility LFGQueue::CheckCompatibility(GuidList check) if (uint8 playersize = numPlayers - proposalRoles.size()) { - TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: (%s) not compatible, %u players are ignoring each other", strGuids.c_str(), playersize); + TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: (%s) not compatible, %u players are ignoring each other", GetDetailedMatchRoles(check).c_str(), playersize); SetCompatibles(strGuids, LFG_INCOMPATIBLES_HAS_IGNORES); return LFG_INCOMPATIBLES_HAS_IGNORES; } @@ -435,7 +472,7 @@ LfgCompatibility LFGQueue::CheckCompatibility(GuidList check) for (LfgRolesMap::const_iterator it = debugRoles.begin(); it != debugRoles.end(); ++it) o << ", " << it->first.GetRawValue() << ": " << GetRolesString(it->second); - TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: (%s) Roles not compatible%s", strGuids.c_str(), o.str().c_str()); + TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: (%s) Roles not compatible%s", GetDetailedMatchRoles(check).c_str(), o.str().c_str()); SetCompatibles(strGuids, LFG_INCOMPATIBLES_NO_ROLES); return LFG_INCOMPATIBLES_NO_ROLES; } @@ -455,7 +492,7 @@ LfgCompatibility LFGQueue::CheckCompatibility(GuidList check) if (proposalDungeons.empty()) { - TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: (%s) No compatible dungeons%s", strGuids.c_str(), o.str().c_str()); + TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: (%s) No compatible dungeons%s", GetDetailedMatchRoles(check).c_str(), o.str().c_str()); SetCompatibles(strGuids, LFG_INCOMPATIBLES_NO_DUNGEONS); return LFG_INCOMPATIBLES_NO_DUNGEONS; } @@ -472,7 +509,7 @@ LfgCompatibility LFGQueue::CheckCompatibility(GuidList check) // Enough players? if (numPlayers != MAXGROUPSIZE) { - TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: (%s) Compatibles but not enough players(%u)", strGuids.c_str(), numPlayers); + TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: (%s) Compatibles but not enough players(%u)", GetDetailedMatchRoles(check).c_str(), numPlayers); LfgCompatibilityData data(LFG_COMPATIBLES_WITH_LESS_PLAYERS); data.roles = proposalRoles; @@ -489,7 +526,7 @@ LfgCompatibility LFGQueue::CheckCompatibility(GuidList check) if (!sLFGMgr->AllQueued(check)) { - TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: (%s) Group MATCH but can't create proposal!", strGuids.c_str()); + TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: (%s) Group MATCH but can't create proposal!", GetDetailedMatchRoles(check).c_str()); SetCompatibles(strGuids, LFG_COMPATIBLES_BAD_STATES); return LFG_COMPATIBLES_BAD_STATES; } @@ -531,7 +568,7 @@ LfgCompatibility LFGQueue::CheckCompatibility(GuidList check) sLFGMgr->AddProposal(proposal); - TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: (%s) MATCH! Group formed", strGuids.c_str()); + TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: (%s) MATCH! Group formed", GetDetailedMatchRoles(check).c_str()); SetCompatibles(strGuids, LFG_COMPATIBLES_MATCH); return LFG_COMPATIBLES_MATCH; } @@ -627,7 +664,23 @@ std::string LFGQueue::DumpCompatibleInfo(bool full /* = false */) const o << "Compatible Map size: " << CompatibleMapStore.size() << "\n"; if (full) for (LfgCompatibleContainer::const_iterator itr = CompatibleMapStore.begin(); itr != CompatibleMapStore.end(); ++itr) - o << "(" << itr->first << "): " << GetCompatibleString(itr->second.compatibility) << "\n"; + { + o << "(" << itr->first << "): " << GetCompatibleString(itr->second.compatibility); + if (!itr->second.roles.empty()) + { + o << " ("; + bool first = true; + for (const auto& role : itr->second.roles) + { + if (!first) + o << "|"; + o << role.first.GetRawValue() << " " << GetRolesString(role.second & uint8(~PLAYER_ROLE_LEADER)); + first = false; + } + o << ")"; + } + o << "\n"; + } return o.str(); } diff --git a/src/server/game/DungeonFinding/LFGQueue.h b/src/server/game/DungeonFinding/LFGQueue.h index 5cd2923bc82..d609406d73d 100644 --- a/src/server/game/DungeonFinding/LFGQueue.h +++ b/src/server/game/DungeonFinding/LFGQueue.h @@ -88,6 +88,7 @@ class LFGQueue public: // Add/Remove from queue + std::string GetDetailedMatchRoles(GuidList const& check) const; void AddToQueue(ObjectGuid guid); void RemoveFromQueue(ObjectGuid guid); void AddQueueData(ObjectGuid guid, time_t joinTime, LfgDungeonSet const& dungeons, LfgRolesMap const& rolesMap); diff --git a/src/server/game/DungeonFinding/LFGScripts.cpp b/src/server/game/DungeonFinding/LFGScripts.cpp index 492b56ef0ac..98b4a4ead51 100644 --- a/src/server/game/DungeonFinding/LFGScripts.cpp +++ b/src/server/game/DungeonFinding/LFGScripts.cpp @@ -44,6 +44,8 @@ void LFGPlayerScript::OnLogout(Player* player) player->GetSession()->SendLfgLfrList(false); sLFGMgr->LeaveLfg(player->GetGUID()); } + else if (player->GetSession()->PlayerDisconnected()) + sLFGMgr->LeaveLfg(player->GetGUID(), true); } void LFGPlayerScript::OnLogin(Player* player, bool /*loginFirst*/) diff --git a/src/server/game/Entities/Object/ObjectGuid.h b/src/server/game/Entities/Object/ObjectGuid.h index 242204201d4..c8cd808285f 100644 --- a/src/server/game/Entities/Object/ObjectGuid.h +++ b/src/server/game/Entities/Object/ObjectGuid.h @@ -94,6 +94,11 @@ class ObjectGuid explicit ObjectGuid(uint64 guid) { _data._guid = guid; } ObjectGuid(HighGuid hi, uint32 entry, uint32 counter) { _data._guid = counter ? uint64(counter) | (uint64(entry) << 32) | (uint64(hi) << ((hi == HIGHGUID_CORPSE || hi == HIGHGUID_AREATRIGGER) ? 48 : 52)) : 0; } ObjectGuid(HighGuid hi, uint32 counter) { _data._guid = counter ? uint64(counter) | (uint64(hi) << ((hi == HIGHGUID_CORPSE || hi == HIGHGUID_AREATRIGGER) ? 48 : 52)) : 0; } + ObjectGuid(ObjectGuid const& r) : _data(r._data) { } + ObjectGuid(ObjectGuid&& r) : _data(r._data) { } + + ObjectGuid& operator=(ObjectGuid const& r) { _data = r._data; return *this; } + ObjectGuid& operator=(ObjectGuid&& r) { _data = r._data; return *this; } operator uint64() const { return _data._guid; } PackedGuidReader ReadAsPacked() { return PackedGuidReader(*this); } diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 5b13b3a68fe..79262bd9237 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -62,7 +62,7 @@ #include "Pet.h" #include "QuestDef.h" #include "ReputationMgr.h" -#include "revision.h" +#include "GitRevision.h" #include "SkillDiscovery.h" #include "SocialMgr.h" #include "Spell.h" @@ -770,7 +770,6 @@ Player::Player(WorldSession* session): Unit(true) m_MirrorTimerFlagsLast = UNDERWATER_NONE; m_isInWater = false; m_drunkTimer = 0; - m_restTime = 0; m_deathTimer = 0; m_deathExpireTime = 0; @@ -800,10 +799,10 @@ Player::Player(WorldSession* session): Unit(true) m_lastpetnumber = 0; ////////////////////Rest System///////////////////// - time_inn_enter = 0; + _restTime = 0; inn_triggerId = 0; m_rest_bonus = 0; - rest_type = REST_TYPE_NO; + _restFlagMask = 0; ////////////////////Rest System///////////////////// m_mailsLoaded = false; @@ -1731,15 +1730,20 @@ void Player::Update(uint32 p_time) if (HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING)) { - if (roll_chance_i(3) && GetTimeInnEnter() > 0) // freeze update + if (roll_chance_i(3) && _restTime > 0) // freeze update { - time_t time_inn = time(NULL)-GetTimeInnEnter(); - if (time_inn >= 10) // freeze update + time_t currTime = time(nullptr); + time_t timeDiff = currTime - _restTime; + if (timeDiff >= 10) // freeze update { - float bubble = 0.125f*sWorld->getRate(RATE_REST_INGAME); - // speed collect rest bonus (section/in hour) - SetRestBonus(GetRestBonus()+ time_inn*((float)GetUInt32Value(PLAYER_NEXT_LEVEL_XP)/72000)*bubble); - UpdateInnerTime(time(NULL)); + _restTime = currTime; + + float bubble = 0.125f * sWorld->getRate(RATE_REST_INGAME); + float extraPerSec = ((float)GetUInt32Value(PLAYER_NEXT_LEVEL_XP) / 72000.0f) * bubble; + + // speed collect rest bonus (section/in hour) + float currRestBonus = GetRestBonus(); + SetRestBonus(currRestBonus + timeDiff * extraPerSec); } } } @@ -1757,14 +1761,11 @@ void Player::Update(uint32 p_time) if (p_time >= m_zoneUpdateTimer) { // On zone update tick check if we are still in an inn if we are supposed to be in one - if (HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING) && GetRestType() == REST_TYPE_IN_TAVERN) + if (HasRestFlag(REST_FLAG_IN_TAVERN)) { AreaTriggerEntry const* atEntry = sAreaTriggerStore.LookupEntry(GetInnTriggerId()); if (!atEntry || !IsInAreaTriggerRadius(atEntry)) - { - RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING); - SetRestType(REST_TYPE_NO); - } + RemoveRestFlag(REST_FLAG_IN_TAVERN); } uint32 newzone, newarea; @@ -1957,12 +1958,6 @@ void Player::setDeathState(DeathState s) SetUInt32Value(PLAYER_SELF_RES_SPELL, 0); } -void Player::InnEnter(time_t time, uint32 triggerId) -{ - inn_triggerId = triggerId; - time_inn_enter = time; -} - bool Player::BuildEnumData(PreparedQueryResult result, ByteBuffer* dataBuffer, ByteBuffer* bitBuffer) { // 0 1 2 3 4 5 6 7 @@ -7630,7 +7625,7 @@ void Player::UpdateArea(uint32 newArea) { // FFA_PVP flags are area and not zone id dependent // so apply them accordingly - m_areaUpdateId = newArea; + m_areaUpdateId = newArea; AreaTableEntry const* area = GetAreaEntryByAreaID(newArea); pvpInfo.IsInFFAPvPArea = area && (area->flags & AREA_FLAG_ARENA); @@ -7652,16 +7647,9 @@ void Player::UpdateArea(uint32 newArea) uint32 const areaRestFlag = (GetTeam() == ALLIANCE) ? AREA_FLAG_REST_ZONE_ALLIANCE : AREA_FLAG_REST_ZONE_HORDE; if (area && area->flags & areaRestFlag) - { - SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING); - SetRestType(REST_TYPE_IN_FACTION_AREA); - InnEnter(time(nullptr), 0); - } - else if (HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING) && GetRestType() == REST_TYPE_IN_FACTION_AREA) - { - RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING); - SetRestType(REST_TYPE_NO); - } + SetRestFlag(REST_FLAG_IN_FACTION_AREA); + else + RemoveRestFlag(REST_FLAG_IN_FACTION_AREA); } void Player::UpdateZone(uint32 newZone, uint32 newArea) @@ -7727,36 +7715,12 @@ void Player::UpdateZone(uint32 newZone, uint32 newArea) if (zone->flags & AREA_FLAG_CAPITAL) // Is in a capital city { if (!pvpInfo.IsHostile || zone->IsSanctuary()) - { - SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING); - SetRestType(REST_TYPE_IN_CITY); - InnEnter(time(nullptr), 0); - } + SetRestFlag(REST_FLAG_IN_CITY); + pvpInfo.IsInNoPvPArea = true; } else - { - if (HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING)) - { - if (GetRestType() == REST_TYPE_IN_TAVERN) // Still inside a tavern or has recently left - { - // check that we are still inside the tavern (in areatrigger radius) - - AreaTriggerEntry const* atEntry = sAreaTriggerStore.LookupEntry(GetInnTriggerId()); - if (!atEntry || !IsInAreaTriggerRadius(atEntry)) - { - RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING); - SetRestType(REST_TYPE_NO); - } - } - else if (GetRestType() != REST_TYPE_IN_FACTION_AREA) // handled in UpdateArea - { - // Recently left a capital city - RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING); - SetRestType(REST_TYPE_NO); - } - } - } + RemoveRestFlag(REST_FLAG_IN_CITY); // Recently left a capital city UpdatePvPState(); @@ -8625,9 +8589,6 @@ void Player::CastItemUseSpell(Item* item, SpellCastTargets const& targets, uint8 return; } - // use triggered flag only for items with many spell casts and for not first cast - uint8 count = 0; - // item spells cast at use for (uint8 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i) { @@ -8648,13 +8609,12 @@ void Player::CastItemUseSpell(Item* item, SpellCastTargets const& targets, uint8 continue; } - Spell* spell = new Spell(this, spellInfo, (count > 0) ? TRIGGERED_FULL_MASK : TRIGGERED_NONE); + Spell* spell = new Spell(this, spellInfo, TRIGGERED_NONE); spell->m_CastItem = item; spell->m_cast_count = cast_count; // set count of casts spell->m_glyphIndex = glyphIndex; // glyph index spell->prepare(&targets); - - ++count; + return; } // Item enchantments spells cast at use @@ -8679,13 +8639,12 @@ void Player::CastItemUseSpell(Item* item, SpellCastTargets const& targets, uint8 continue; } - Spell* spell = new Spell(this, spellInfo, (count > 0) ? TRIGGERED_FULL_MASK : TRIGGERED_NONE); + Spell* spell = new Spell(this, spellInfo, TRIGGERED_NONE); spell->m_CastItem = item; spell->m_cast_count = cast_count; // set count of casts spell->m_glyphIndex = glyphIndex; // glyph index spell->prepare(&targets); - - ++count; + return; } } } @@ -9745,6 +9704,17 @@ void Player::SendInitWorldStates(uint32 zoneid, uint32 areaid) data << uint32(4131) << uint32(0); // 10 WORLDSTATE_ALGALON_DESPAWN_TIMER } break; + // Violet Hold + case 4415: + if (instance && mapid == 608) + instance->FillInitialWorldStates(data); + else + { + data << uint32(3816) << uint32(0); // 9 WORLD_STATE_VH_SHOW + data << uint32(3815) << uint32(100); // 10 WORLD_STATE_VH_PRISON_STATE + data << uint32(3810) << uint32(0); // 11 WORLD_STATE_VH_WAVE_COUNT + } + break; // Zul Aman case 3805: if (instance && mapid == 568) @@ -15188,8 +15158,8 @@ void Player::AddQuest(Quest const* quest, Object* questGiver) PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_QUEST_TRACK); stmt->setUInt32(0, quest_id); stmt->setUInt32(1, GetGUIDLow()); - stmt->setString(2, _HASH); - stmt->setString(3, _DATE); + stmt->setString(2, GitRevision::GetHash()); + stmt->setString(3, GitRevision::GetDate()); // add to Quest Tracker CharacterDatabase.Execute(stmt); @@ -27648,4 +27618,31 @@ bool Player::ValidateAppearance(uint8 race, uint8 class_, uint8 gender, uint8 ha return false; return true; -} \ No newline at end of file +} + +void Player::SetRestFlag(RestFlag restFlag, uint32 triggerId /*= 0*/) +{ + uint32 oldRestMask = _restFlagMask; + _restFlagMask |= restFlag; + + if (!oldRestMask && _restFlagMask) // only set flag/time on the first rest state + { + _restTime = time(nullptr); + SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING); + } + + if (triggerId) + inn_triggerId = triggerId; + } + +void Player::RemoveRestFlag(RestFlag restFlag) +{ + uint32 oldRestMask = _restFlagMask; + _restFlagMask &= ~restFlag; + + if (oldRestMask && !_restFlagMask) // only remove flag/time on the last rest state remove + { + _restTime = 0; + RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING); + } +} diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 63774f3b515..a216db63f09 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -809,12 +809,11 @@ enum ArenaTeamInfoType class InstanceSave; -enum RestType +enum RestFlag { - REST_TYPE_NO = 0, - REST_TYPE_IN_TAVERN = 1, - REST_TYPE_IN_CITY = 2, - REST_TYPE_IN_FACTION_AREA = 3 // used with AREA_FLAG_REST_ZONE_* + REST_FLAG_IN_TAVERN = 0x1, + REST_FLAG_IN_CITY = 0x2, + REST_FLAG_IN_FACTION_AREA = 0x4 }; enum TeleportToOptions @@ -1335,19 +1334,16 @@ class Player : public Unit, public GridObject void setDeathState(DeathState s) override; // overwrite Unit::setDeathState - void InnEnter(time_t time, uint32 triggerId); - float GetRestBonus() const { return m_rest_bonus; } void SetRestBonus(float rest_bonus_new); - RestType GetRestType() const { return rest_type; } - void SetRestType(RestType n_r_type) { rest_type = n_r_type; } + bool HasRestFlag(RestFlag restFlag) const { return (_restFlagMask & restFlag) != 0; } + void SetRestFlag(RestFlag restFlag, uint32 triggerId = 0); + void RemoveRestFlag(RestFlag restFlag); + uint32 GetXPRestBonus(uint32 xp); uint32 GetInnTriggerId() const { return inn_triggerId; } - time_t GetTimeInnEnter() const { return time_inn_enter; } - void UpdateInnerTime (time_t time) { time_inn_enter = time; } - Pet* GetPet() const; Pet* SummonPet(uint32 entry, float x, float y, float z, float ang, PetType petType, uint32 despwtime); void RemovePet(Pet* pet, PetSaveMode mode, bool returnreagent = false); @@ -2282,15 +2278,6 @@ class Player : public Unit, public GridObject // returns true if the player is in active state for outdoor pvp objective capturing, false otherwise bool IsOutdoorPvPActive(); - /*********************************************************/ - /*** REST SYSTEM ***/ - /*********************************************************/ - - bool isRested() const { return GetRestTime() >= 10*IN_MILLISECONDS; } - uint32 GetXPRestBonus(uint32 xp); - uint32 GetRestTime() const { return m_restTime;} - void SetRestTime(uint32 v) { m_restTime = v;} - /*********************************************************/ /*** ENVIROMENTAL SYSTEM ***/ /*********************************************************/ @@ -2768,8 +2755,6 @@ class Player : public Unit, public GridObject uint32 m_deathTimer; time_t m_deathExpireTime; - uint32 m_restTime; - uint32 m_WeaponProficiency; uint32 m_ArmorProficiency; bool m_canParry; @@ -2778,10 +2763,10 @@ class Player : public Unit, public GridObject uint8 m_swingErrorMsg; ////////////////////Rest System///////////////////// - time_t time_inn_enter; + time_t _restTime; uint32 inn_triggerId; float m_rest_bonus; - RestType rest_type; + uint32 _restFlagMask; ////////////////////Rest System///////////////////// // Social diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index c38e3c0ca63..20ad5882609 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -5604,7 +5604,9 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere case 40438: { // Shadow Word: Pain - if (procSpell->SpellFamilyFlags[0] & 0x8000) + if (!procSpell) + return false; + else if (procSpell->SpellFamilyFlags[0] & 0x8000) triggered_spell_id = 40441; // Renew else if (procSpell->SpellFamilyFlags[0] & 0x40) @@ -5645,7 +5647,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere // Priest T10 Healer 2P Bonus case 70770: // Flash Heal - if (procSpell->SpellFamilyFlags[0] & 0x800) + if (procSpell && procSpell->SpellFamilyFlags[0] & 0x800) { triggered_spell_id = 70772; SpellInfo const* blessHealing = sSpellMgr->GetSpellInfo(triggered_spell_id); @@ -5712,10 +5714,13 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere // Healing Touch (Dreamwalker Raiment set) case 28719: { - // mana back - basepoints0 = int32(CalculatePct(procSpell->ManaCost, 30)); - target = this; - triggered_spell_id = 28742; + if (procSpell) + { + // mana back + basepoints0 = int32(CalculatePct(procSpell->ManaCost, 30)); + target = this; + triggered_spell_id = 28742; + } break; } // Healing Touch Refund (Idol of Longevity trinket) @@ -5738,8 +5743,10 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere { float chance; + if (!procSpell) + return false; // Starfire - if (procSpell->SpellFamilyFlags[0] & 0x4) + else if (procSpell->SpellFamilyFlags[0] & 0x4) { triggered_spell_id = 40445; chance = 25.0f; @@ -5769,7 +5776,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere case 70723: { // Wrath & Starfire - if ((procSpell->SpellFamilyFlags[0] & 0x5) && (procEx & PROC_EX_CRITICAL_HIT)) + if (procSpell && (procSpell->SpellFamilyFlags[0] & 0x5) && (procEx & PROC_EX_CRITICAL_HIT)) { triggered_spell_id = 71023; SpellInfo const* triggeredSpell = sSpellMgr->GetSpellInfo(triggered_spell_id); @@ -5785,7 +5792,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere case 70664: { // Proc only from normal Rejuvenation - if (procSpell->SpellVisual[0] != 32) + if (!procSpell || procSpell->SpellVisual[0] != 32) return false; Player* caster = ToPlayer(); @@ -6153,7 +6160,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere case 67228: { // Lava Burst - if (procSpell->SpellFamilyFlags[1] & 0x1000) + if (procSpell && procSpell->SpellFamilyFlags[1] & 0x1000) { triggered_spell_id = 71824; SpellInfo const* triggeredSpell = sSpellMgr->GetSpellInfo(triggered_spell_id); @@ -6167,7 +6174,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere case 70808: { // Chain Heal - if ((procSpell->SpellFamilyFlags[0] & 0x100) && (procEx & PROC_EX_CRITICAL_HIT)) + if (procSpell && (procSpell->SpellFamilyFlags[0] & 0x100) && (procEx & PROC_EX_CRITICAL_HIT)) { triggered_spell_id = 70809; SpellInfo const* triggeredSpell = sSpellMgr->GetSpellInfo(triggered_spell_id); @@ -6364,10 +6371,10 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere if (dummySpell->Id == 61257) { // only for spells and hit/crit (trigger start always) and not start from self cast spells - if (procSpell == 0 || !(procEx & (PROC_EX_NORMAL_HIT|PROC_EX_CRITICAL_HIT)) || this == victim) + if (!procSpell || !(procEx & (PROC_EX_NORMAL_HIT|PROC_EX_CRITICAL_HIT)) || this == victim) return false; // Need snare or root mechanic - if (!(procSpell->GetAllEffectsMechanicMask() & ((1<GetAllEffectsMechanicMask() & ((1< usedMailTemplates; + // Load `quest_details` + // 0 1 2 3 4 5 6 7 8 + result = WorldDatabase.Query("SELECT ID, Emote1, Emote2, Emote3, Emote4, EmoteDelay1, EmoteDelay2, EmoteDelay3, EmoteDelay4 FROM quest_details"); + + if (!result) + { + TC_LOG_ERROR("server.loading", ">> Loaded 0 quest details. DB table `quest_details` is empty."); + } + else + { + do + { + Field* fields = result->Fetch(); + uint32 questId = fields[0].GetUInt32(); + + auto itr = _questTemplates.find(questId); + if (itr != _questTemplates.end()) + itr->second->LoadQuestDetails(fields); + else + TC_LOG_ERROR("server.loading", "Table `quest_details` has data for quest %u but such quest does not exist", questId); + } while (result->NextRow()); + } + + // Load `quest_request_items` + // 0 1 2 3 + result = WorldDatabase.Query("SELECT ID, EmoteOnComplete, EmoteOnIncomplete, CompletionText FROM quest_request_items"); + + if (!result) + { + TC_LOG_ERROR("server.loading", ">> Loaded 0 quest request items. DB table `quest_request_items` is empty."); + } + else + { + do + { + Field* fields = result->Fetch(); + uint32 questId = fields[0].GetUInt32(); + + auto itr = _questTemplates.find(questId); + if (itr != _questTemplates.end()) + itr->second->LoadQuestRequestItems(fields); + else + TC_LOG_ERROR("server.loading", "Table `quest_request_items` has data for quest %u but such quest does not exist", questId); + } while (result->NextRow()); + } + + // Load `quest_offer_reward` + // 0 1 2 3 4 5 6 7 8 9 + result = WorldDatabase.Query("SELECT ID, Emote1, Emote2, Emote3, Emote4, EmoteDelay1, EmoteDelay2, EmoteDelay3, EmoteDelay4, RewardText FROM quest_offer_reward"); + + if (!result) + { + TC_LOG_ERROR("server.loading", ">> Loaded 0 quest reward emotes. DB table `quest_offer_reward` is empty."); + } + else + { + do + { + Field* fields = result->Fetch(); + uint32 questId = fields[0].GetUInt32(); + + auto itr = _questTemplates.find(questId); + if (itr != _questTemplates.end()) + itr->second->LoadQuestOfferReward(fields); + else + TC_LOG_ERROR("server.loading", "Table `quest_offer_reward` has data for quest %u but such quest does not exist", questId); + } while (result->NextRow()); + } + // Load `quest_template_addon` // 0 1 2 3 4 5 6 7 8 result = WorldDatabase.Query("SELECT ID, MaxLevel, AllowableClasses, SourceSpellID, PrevQuestID, NextQuestID, ExclusiveGroup, RewardMailTemplateID, RewardMailDelay, " diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index 27cfc6c8d2b..ef0d1a7d2ed 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -38,10 +38,10 @@ #include "PlayerDump.h" #include "Player.h" #include "ReputationMgr.h" +#include "GitRevision.h" #include "ScriptMgr.h" #include "SharedDefines.h" #include "SocialMgr.h" -#include "SystemConfig.h" #include "UpdateMask.h" #include "Util.h" #include "World.h" @@ -908,7 +908,7 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder) // send server info if (sWorld->getIntConfig(CONFIG_ENABLE_SINFO_LOGIN) == 1) - chH.PSendSysMessage(_FULLVERSION); + chH.PSendSysMessage(GitRevision::GetFullVersion()); TC_LOG_DEBUG("network", "WORLD: Sent server info"); } diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp index 3476db65a62..bd0dc362053 100644 --- a/src/server/game/Handlers/MiscHandler.cpp +++ b/src/server/game/Handlers/MiscHandler.cpp @@ -877,9 +877,7 @@ void WorldSession::HandleAreaTriggerOpcode(WorldPacket& recvData) if (sObjectMgr->IsTavernAreaTrigger(triggerId)) { // set resting flag we are in the inn - player->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING); - player->InnEnter(time(nullptr), atEntry->id); - player->SetRestType(REST_TYPE_IN_TAVERN); + player->SetRestFlag(REST_FLAG_IN_TAVERN, atEntry->id); if (sWorld->IsFFAPvPRealm()) player->RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); diff --git a/src/server/game/Instances/InstanceScript.cpp b/src/server/game/Instances/InstanceScript.cpp index 64614e0d59a..5861db3c8d9 100644 --- a/src/server/game/Instances/InstanceScript.cpp +++ b/src/server/game/Instances/InstanceScript.cpp @@ -319,6 +319,11 @@ bool InstanceScript::SetBossState(uint32 id, EncounterState state) return false; } +bool InstanceScript::_SkipCheckRequiredBosses(Player const* player /*= nullptr*/) const +{ + return player && player->GetSession()->HasPermission(rbac::RBAC_PERM_SKIP_CHECK_INSTANCE_REQUIRED_BOSSES); +} + void InstanceScript::Load(char const* data) { if (!data) diff --git a/src/server/game/Instances/InstanceScript.h b/src/server/game/Instances/InstanceScript.h index 6e66e401718..69d84d0a419 100644 --- a/src/server/game/Instances/InstanceScript.h +++ b/src/server/game/Instances/InstanceScript.h @@ -279,6 +279,8 @@ class InstanceScript : public ZoneScript void WriteSaveDataBossStates(std::ostringstream& data); virtual void WriteSaveDataMore(std::ostringstream& /*data*/) { } + bool _SkipCheckRequiredBosses(Player const* player = nullptr) const; + private: static void LoadObjectData(ObjectData const* creatureData, ObjectInfoMap& objectInfo); diff --git a/src/server/game/Miscellaneous/Language.h b/src/server/game/Miscellaneous/Language.h index b787628cb90..4243d7dee24 100644 --- a/src/server/game/Miscellaneous/Language.h +++ b/src/server/game/Miscellaneous/Language.h @@ -379,7 +379,8 @@ enum TrinityStrings LANG_COMMAND_CHEAT_POWER = 361, LANG_COMMAND_CHEAT_WW = 362, LANG_COMMAND_WHISPEROFFPLAYER = 363, - // Room for more level 2 364-399 not used + LANG_COMMAND_CHEAT_TAXINODES = 364, + // Room for more level 2 365-399 not used // level 3 chat LANG_SCRIPTS_RELOADED = 400, diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h index 3b910a656b5..3d021c9efa7 100644 --- a/src/server/game/Miscellaneous/SharedDefines.h +++ b/src/server/game/Miscellaneous/SharedDefines.h @@ -4104,35 +4104,6 @@ enum PartyResult ERR_PARTY_LFG_TELEPORT_IN_COMBAT = 30 }; -const uint32 MMAP_MAGIC = 0x4d4d4150; // 'MMAP' -#define MMAP_VERSION 5 - -struct MmapTileHeader -{ - uint32 mmapMagic; - uint32 dtVersion; - uint32 mmapVersion; - uint32 size; - bool usesLiquids : 1; - - MmapTileHeader() : mmapMagic(MMAP_MAGIC), dtVersion(DT_NAVMESH_VERSION), - mmapVersion(MMAP_VERSION), size(0), usesLiquids(true) { } -}; - -enum NavTerrain -{ - NAV_EMPTY = 0x00, - NAV_GROUND = 0x01, - NAV_MAGMA = 0x02, - NAV_SLIME = 0x04, - NAV_WATER = 0x08, - NAV_UNUSED1 = 0x10, - NAV_UNUSED2 = 0x20, - NAV_UNUSED3 = 0x40, - NAV_UNUSED4 = 0x80 - // we only have 8 bits -}; - enum DiminishingLevels { DIMINISHING_LEVEL_1 = 0, diff --git a/src/server/game/Movement/MotionMaster.cpp b/src/server/game/Movement/MotionMaster.cpp index d90dc650733..642cefa5963 100644 --- a/src/server/game/Movement/MotionMaster.cpp +++ b/src/server/game/Movement/MotionMaster.cpp @@ -423,6 +423,24 @@ void MotionMaster::MoveCirclePath(float x, float y, float z, float radius, bool init.Launch(); } +void MotionMaster::MoveSmoothPath(uint32 pointId, G3D::Vector3 const* pathPoints, size_t pathSize, bool walk) +{ + Movement::PointsArray path(pathPoints, pathPoints + pathSize); + + Movement::MoveSplineInit init(_owner); + init.MovebyPath(path); + init.SetSmooth(); + init.SetWalk(walk); + init.Launch(); + + // This code is not correct + // EffectMovementGenerator does not affect UNIT_STATE_ROAMING | UNIT_STATE_ROAMING_MOVE + // need to call PointMovementGenerator with various pointIds + Mutate(new EffectMovementGenerator(pointId), MOTION_SLOT_ACTIVE); + //Position pos(pathPoints[pathSize - 1].x, pathPoints[pathSize - 1].y, pathPoints[pathSize - 1].z); + //MovePoint(EVENT_CHARGE_PREPATH, pos, false); +} + void MotionMaster::MoveFall(uint32 id /*=0*/) { // use larger distance for vmap height search than in most other cases diff --git a/src/server/game/Movement/MotionMaster.h b/src/server/game/Movement/MotionMaster.h index c8da50364ba..9a8950de9f7 100644 --- a/src/server/game/Movement/MotionMaster.h +++ b/src/server/game/Movement/MotionMaster.h @@ -185,6 +185,7 @@ class MotionMaster //: private std::stack { MoveJump(pos.m_positionX, pos.m_positionY, pos.m_positionZ, speedXY, speedZ, id); } void MoveJump(float x, float y, float z, float speedXY, float speedZ, uint32 id = EVENT_JUMP); void MoveCirclePath(float x, float y, float z, float radius, bool clockwise, uint8 stepCount); + void MoveSmoothPath(uint32 pointId, G3D::Vector3 const* pathPoints, size_t pathSize, bool walk); void MoveFall(uint32 id = 0); void MoveSeekAssistance(float x, float y, float z); diff --git a/src/server/game/Movement/PathGenerator.h b/src/server/game/Movement/PathGenerator.h index a9a13c37251..71e0e88f0b2 100644 --- a/src/server/game/Movement/PathGenerator.h +++ b/src/server/game/Movement/PathGenerator.h @@ -19,7 +19,7 @@ #ifndef _PATH_GENERATOR_H #define _PATH_GENERATOR_H -#include "SharedDefines.h" +#include "MapDefines.h" #include "DetourNavMesh.h" #include "DetourNavMeshQuery.h" #include "MoveSplineInitArgs.h" diff --git a/src/server/game/Quests/QuestDef.cpp b/src/server/game/Quests/QuestDef.cpp index a58dc42cb3e..61cf96132da 100644 --- a/src/server/game/Quests/QuestDef.cpp +++ b/src/server/game/Quests/QuestDef.cpp @@ -56,26 +56,25 @@ Quest::Quest(Field* questRecord) RewardReputationMask = questRecord[30].GetUInt8(); QuestGiverPortrait = questRecord[31].GetUInt32(); QuestTurnInPortrait = questRecord[32].GetUInt32(); - for (int i = 0; i < QUEST_REWARDS_COUNT; ++i) - RewardItemId[i] = questRecord[33+i].GetUInt32(); for (int i = 0; i < QUEST_REWARDS_COUNT; ++i) - RewardItemIdCount[i] = questRecord[37+i].GetUInt16(); + { + RewardItemId[i] = questRecord[33 + i * 2].GetUInt32(); + RewardItemIdCount[i] = questRecord[34 + i * 2].GetUInt16(); + } for (int i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i) - RewardChoiceItemId[i] = questRecord[41+i].GetUInt32(); - - for (int i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i) - RewardChoiceItemCount[i] = questRecord[47+i].GetUInt16(); + { + RewardChoiceItemId[i] = questRecord[41 + i * 2].GetUInt32(); + RewardChoiceItemCount[i] = questRecord[42 + i * 2].GetUInt16(); + } for (int i = 0; i < QUEST_REPUTATIONS_COUNT; ++i) - RewardFactionId[i] = questRecord[53+i].GetUInt16(); - - for (int i = 0; i < QUEST_REPUTATIONS_COUNT; ++i) - RewardFactionValueId[i] = questRecord[58+i].GetInt32(); - - for (int i = 0; i < QUEST_REPUTATIONS_COUNT; ++i) - RewardFactionValueIdOverride[i] = questRecord[63+i].GetInt32(); + { + RewardFactionId[i] = questRecord[53 + i * 3].GetUInt16(); + RewardFactionValueId[i] = questRecord[54 + i * 3].GetInt32(); + RewardFactionValueIdOverride[i] = questRecord[55 + i * 3].GetInt32(); + } PointMapId = questRecord[68].GetUInt16(); PointX = questRecord[69].GetFloat(); @@ -86,67 +85,50 @@ Quest::Quest(Field* questRecord) Details = questRecord[74].GetString(); EndText = questRecord[75].GetString(); CompletedText = questRecord[76].GetString(); - OfferRewardText = questRecord[77].GetString(); - RequestItemsText = questRecord[78].GetString(); for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i) - RequiredNpcOrGo[i] = questRecord[79+i].GetInt32(); + RequiredNpcOrGo[i] = questRecord[77+i].GetInt32(); for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i) - RequiredNpcOrGoCount[i] = questRecord[83+i].GetUInt16(); + RequiredNpcOrGoCount[i] = questRecord[81+i].GetUInt16(); for (int i = 0; i < QUEST_SOURCE_ITEM_IDS_COUNT; ++i) - RequiredSourceItemId[i] = questRecord[87+i].GetUInt32(); + RequiredSourceItemId[i] = questRecord[85+i].GetUInt32(); for (int i = 0; i < QUEST_SOURCE_ITEM_IDS_COUNT; ++i) - RequiredSourceItemCount[i] = questRecord[91+i].GetUInt16(); + RequiredSourceItemCount[i] = questRecord[89+i].GetUInt16(); for (int i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; ++i) - RequiredItemId[i] = questRecord[95+i].GetUInt32(); + RequiredItemId[i] = questRecord[93+i].GetUInt32(); for (int i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; ++i) - RequiredItemCount[i] = questRecord[101+i].GetUInt16(); + RequiredItemCount[i] = questRecord[99+i].GetUInt16(); - RequiredSpell = questRecord[107].GetUInt32(); + RequiredSpell = questRecord[105].GetUInt32(); for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i) - ObjectiveText[i] = questRecord[108+i].GetString(); + ObjectiveText[i] = questRecord[106+i].GetString(); for (int i = 0; i < QUEST_REWARD_CURRENCY_COUNT; ++i) - RewardCurrencyId[i] = questRecord[112+i].GetUInt16(); + RewardCurrencyId[i] = questRecord[110+i].GetUInt16(); for (int i = 0; i < QUEST_REWARD_CURRENCY_COUNT; ++i) - RewardCurrencyCount[i] = questRecord[116+i].GetUInt8(); + RewardCurrencyCount[i] = questRecord[114+i].GetUInt8(); for (int i = 0; i < QUEST_REQUIRED_CURRENCY_COUNT; ++i) - RequiredCurrencyId[i] = questRecord[120+i].GetUInt16(); + RequiredCurrencyId[i] = questRecord[118+i].GetUInt16(); for (int i = 0; i < QUEST_REQUIRED_CURRENCY_COUNT; ++i) - RequiredCurrencyCount[i] = questRecord[124+i].GetUInt8(); + RequiredCurrencyCount[i] = questRecord[122+i].GetUInt8(); - QuestGiverTextWindow = questRecord[128].GetString(); - QuestGiverTargetName = questRecord[129].GetString(); - QuestTurnTextWindow = questRecord[130].GetString(); - QuestTurnTargetName = questRecord[131].GetString(); - SoundAccept = questRecord[132].GetUInt16(); - SoundTurnIn = questRecord[133].GetUInt16(); + QuestGiverTextWindow = questRecord[126].GetString(); + QuestGiverTargetName = questRecord[127].GetString(); + QuestTurnTextWindow = questRecord[128].GetString(); + QuestTurnTargetName = questRecord[129].GetString(); + SoundAccept = questRecord[130].GetUInt16(); + SoundTurnIn = questRecord[131].GetUInt16(); - for (int i = 0; i < QUEST_EMOTE_COUNT; ++i) - DetailsEmote[i] = questRecord[134+i].GetUInt16(); - - for (int i = 0; i < QUEST_EMOTE_COUNT; ++i) - DetailsEmoteDelay[i] = questRecord[138+i].GetUInt32(); - - EmoteOnIncomplete = questRecord[142].GetUInt16(); - EmoteOnComplete = questRecord[143].GetUInt16(); - - for (int i = 0; i < QUEST_EMOTE_COUNT; ++i) - OfferRewardEmote[i] = questRecord[144+i].GetInt16(); - - for (int i = 0; i < QUEST_EMOTE_COUNT; ++i) - OfferRewardEmoteDelay[i] = questRecord[148+i].GetInt32(); - - //int32 VerifiedBuild = questRecord[152].GetInt32(); + //int32 VerifiedBuild = questRecord[132].GetInt32(); if (SpecialFlags & QUEST_SPECIAL_FLAGS_AUTO_ACCEPT) Flags |= QUEST_FLAGS_AUTO_ACCEPT; @@ -183,6 +165,33 @@ Quest::Quest(Field* questRecord) ++_reqCurrencyCount; } +void Quest::LoadQuestDetails(Field* fields) +{ + for (int i = 0; i < QUEST_EMOTE_COUNT; ++i) + DetailsEmote[i] = fields[1 + i].GetUInt16(); + + for (int i = 0; i < QUEST_EMOTE_COUNT; ++i) + DetailsEmoteDelay[i] = fields[5 + i].GetUInt32(); +} + +void Quest::LoadQuestRequestItems(Field* fields) +{ + EmoteOnComplete = fields[1].GetUInt16(); + EmoteOnIncomplete = fields[2].GetUInt16(); + RequestItemsText = fields[3].GetString(); +} + +void Quest::LoadQuestOfferReward(Field* fields) +{ + for (int i = 0; i < QUEST_EMOTE_COUNT; ++i) + OfferRewardEmote[i] = fields[1 + i].GetUInt16(); + + for (int i = 0; i < QUEST_EMOTE_COUNT; ++i) + OfferRewardEmoteDelay[i] = fields[5 + i].GetUInt32(); + + OfferRewardText = fields[9].GetString(); +} + void Quest::LoadQuestTemplateAddon(Field* fields) { MaxLevel = fields[1].GetUInt8(); diff --git a/src/server/game/Quests/QuestDef.h b/src/server/game/Quests/QuestDef.h index 98b1a29feb8..fe9e3fdd6dd 100644 --- a/src/server/game/Quests/QuestDef.h +++ b/src/server/game/Quests/QuestDef.h @@ -207,6 +207,9 @@ class Quest friend class ObjectMgr; public: Quest(Field* questRecord); + void LoadQuestDetails(Field* fields); + void LoadQuestRequestItems(Field* fields); + void LoadQuestOfferReward(Field* fields); void LoadQuestTemplateAddon(Field* fields); uint32 XPValue(Player* player) const; diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index 8876bf56013..4f01c571c80 100644 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -262,6 +262,7 @@ class WorldSession bool PlayerLogout() const { return m_playerLogout; } bool PlayerLogoutWithSave() const { return m_playerLogout && m_playerSave; } bool PlayerRecentlyLoggedOut() const { return m_playerRecentlyLogout; } + bool PlayerDisconnected() const { return !m_Socket; } void ReadAddonsInfo(WorldPacket& data); void SendAddonsInfo(); diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index b47f1b9e310..b4872de2c3b 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -1359,8 +1359,14 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const for (Unit::AuraApplicationMap::iterator itr = tAuras.begin(); itr != tAuras.end();) { // Use the new aura to see on what stance the target will be - uint32 newStance = (1 << ((newAura ? newAura->GetMiscValue() : 0) -1)); - + uint32 newStance = 0; + if (newAura) + { + if (newAura->GetMiscValue() > 0 && newAura->GetMiscValue() <= 32) //Not null and GetMiscValue is not == FORM_NONE + newStance = 1 << (newAura->GetMiscValue() - 1); + else + TC_LOG_ERROR("spell.aura", "newAura->GetMiscValue() returned value %i for SpellID: %u when it was expecting a value in range [0..31] for a bitshift", newAura->GetMiscValue(), newAura->GetId()); + } // If the stances are not compatible with the spell, remove it if (itr->second->GetBase()->IsRemovedOnShapeLost(target) && !(itr->second->GetBase()->GetSpellInfo()->Stances & newStance)) target->RemoveAura(itr); diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index 344307f5c2d..291252f2b1f 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -3361,6 +3361,19 @@ void SpellMgr::LoadSpellInfoCorrections() //! HACK: This spell break quest complete for alliance and on retail not used °_O spellInfo->Effects[EFFECT_0].Effect = 0; break; + // VIOLET HOLD SPELLS + // + case 54258: // Water Globule (Ichoron) + case 54264: // Water Globule (Ichoron) + case 54265: // Water Globule (Ichoron) + case 54266: // Water Globule (Ichoron) + case 54267: // Water Globule (Ichoron) + // in 3.3.5 there is only one radius in dbc which is 0 yards in this case + // use max radius from 4.3.4 + spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_25_YARDS); + break; + // ENDOF VIOLET HOLD + // // ULDUAR SPELLS // case 62374: // Pursued (Flame Leviathan) diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index b2d2084b2fd..9adbfdb73ea 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -51,11 +51,11 @@ #include "OutdoorPvPMgr.h" #include "Player.h" #include "PoolMgr.h" +#include "GitRevision.h" #include "ScriptMgr.h" #include "SkillDiscovery.h" #include "SkillExtraItems.h" #include "SmartAI.h" -#include "SystemConfig.h" #include "TicketMgr.h" #include "TransportMgr.h" #include "Unit.h" @@ -1421,16 +1421,19 @@ void World::SetInitialWorldSettings() LoadDBCStores(m_dataPath); LoadDB2Stores(m_dataPath); - std::vector mapIds; - for (uint32 mapId = 0; mapId < sMapStore.GetNumRows(); mapId++) - if (sMapStore.LookupEntry(mapId)) - mapIds.push_back(mapId); + std::unordered_map> mapData; + for (MapEntry const* mapEntry : sMapStore) + { + mapData.insert(std::unordered_map>::value_type(mapEntry->MapID, std::vector())); + if (mapEntry->rootPhaseMap != -1) + mapData[mapEntry->rootPhaseMap].push_back(mapEntry->MapID); + } if (VMAP::VMapManager2* vmmgr2 = dynamic_cast(VMAP::VMapFactory::createOrGetVMapManager())) - vmmgr2->InitializeThreadUnsafe(mapIds); + vmmgr2->InitializeThreadUnsafe(mapData); MMAP::MMapManager* mmmgr = MMAP::MMapFactory::createOrGetMMapManager(); - mmmgr->InitializeThreadUnsafe(mapIds); + mmmgr->InitializeThreadUnsafe(mapData); TC_LOG_INFO("server.loading", "Loading SpellInfo store..."); sSpellMgr->LoadSpellInfoStore(); @@ -1860,7 +1863,7 @@ void World::SetInitialWorldSettings() m_startTime = m_gameTime; LoginDatabase.PExecute("INSERT INTO uptime (realmid, starttime, uptime, revision) VALUES(%u, %u, 0, '%s')", - realmHandle.Index, uint32(m_startTime), _FULLVERSION); // One-time query + realmHandle.Index, uint32(m_startTime), GitRevision::GetFullVersion()); // One-time query m_timers[WUPDATE_WEATHERS].SetInterval(1*IN_MILLISECONDS); m_timers[WUPDATE_AUCTIONS].SetInterval(MINUTE*IN_MILLISECONDS); diff --git a/src/server/ipc/CMakeLists.txt b/src/server/ipc/CMakeLists.txt index 95e5e2fc0da..392e1ce1826 100644 --- a/src/server/ipc/CMakeLists.txt +++ b/src/server/ipc/CMakeLists.txt @@ -17,7 +17,7 @@ set(ipc_SRCS include_directories( ${CMAKE_BINARY_DIR} ${CMAKE_SOURCE_DIR}/dep/zmqpp - ${CMAKE_SOURCE_DIR}/src/server/shared/ + ${CMAKE_SOURCE_DIR}/src/common/ ${ZMQ_INCLUDE_DIR} ) diff --git a/src/server/scripts/CMakeLists.txt b/src/server/scripts/CMakeLists.txt index 3d569e35010..ef721deaed4 100644 --- a/src/server/scripts/CMakeLists.txt +++ b/src/server/scripts/CMakeLists.txt @@ -44,34 +44,21 @@ message(STATUS "SCRIPT PREPARATION COMPLETE") message("") include_directories( - ${CMAKE_BINARY_DIR} - ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour - ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour/Include - ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Recast - ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Recast/Include - ${CMAKE_SOURCE_DIR}/dep/g3dlite/include - ${CMAKE_SOURCE_DIR}/dep/SFMT ${CMAKE_SOURCE_DIR}/dep/cppformat - ${CMAKE_SOURCE_DIR}/dep/zlib - ${CMAKE_SOURCE_DIR}/src/server/shared - ${CMAKE_SOURCE_DIR}/src/server/shared/Configuration - ${CMAKE_SOURCE_DIR}/src/server/shared/Cryptography - ${CMAKE_SOURCE_DIR}/src/server/shared/Database - ${CMAKE_SOURCE_DIR}/src/server/shared/DataStores - ${CMAKE_SOURCE_DIR}/src/server/shared/Debugging - ${CMAKE_SOURCE_DIR}/src/server/shared/Dynamic/LinkedReference - ${CMAKE_SOURCE_DIR}/src/server/shared/Dynamic - ${CMAKE_SOURCE_DIR}/src/server/shared/Logging - ${CMAKE_SOURCE_DIR}/src/server/shared/Packets - ${CMAKE_SOURCE_DIR}/src/server/shared/Threading - ${CMAKE_SOURCE_DIR}/src/server/shared/Updater - ${CMAKE_SOURCE_DIR}/src/server/shared/Utilities + ${CMAKE_SOURCE_DIR}/dep/g3dlite/include + ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour/Include + ${CMAKE_SOURCE_DIR}/src/common/ + ${CMAKE_SOURCE_DIR}/src/common/Collision + ${CMAKE_SOURCE_DIR}/src/common/Collision/Management + ${CMAKE_SOURCE_DIR}/src/common/Collision/Maps + ${CMAKE_SOURCE_DIR}/src/common/Collision/Models + ${CMAKE_SOURCE_DIR}/src/common/Configuration + ${CMAKE_SOURCE_DIR}/src/common/Debugging + ${CMAKE_SOURCE_DIR}/src/common/Logging + ${CMAKE_SOURCE_DIR}/src/common/Threading + ${CMAKE_SOURCE_DIR}/src/common/Utilities + ${CMAKE_SOURCE_DIR}/src/server/database/Database ${CMAKE_SOURCE_DIR}/src/server/ipc - ${CMAKE_SOURCE_DIR}/src/server/collision - ${CMAKE_SOURCE_DIR}/src/server/collision/Management - ${CMAKE_SOURCE_DIR}/src/server/collision/Models - ${CMAKE_SOURCE_DIR}/src/server/shared - ${CMAKE_SOURCE_DIR}/src/server/shared/Database ${CMAKE_SOURCE_DIR}/src/server/game/Accounts ${CMAKE_SOURCE_DIR}/src/server/game/Achievements ${CMAKE_SOURCE_DIR}/src/server/game/Addons @@ -85,21 +72,19 @@ include_directories( ${CMAKE_SOURCE_DIR}/src/server/game/Battlefield/Zones ${CMAKE_SOURCE_DIR}/src/server/game/Battlegrounds ${CMAKE_SOURCE_DIR}/src/server/game/Battlegrounds/Zones - ${CMAKE_SOURCE_DIR}/src/server/game/Calendar ${CMAKE_SOURCE_DIR}/src/server/game/Chat ${CMAKE_SOURCE_DIR}/src/server/game/Chat/Channels - ${CMAKE_SOURCE_DIR}/src/server/game/Conditions - ${CMAKE_SOURCE_DIR}/src/server/shared/Configuration ${CMAKE_SOURCE_DIR}/src/server/game/Combat + ${CMAKE_SOURCE_DIR}/src/server/game/Conditions ${CMAKE_SOURCE_DIR}/src/server/game/DataStores ${CMAKE_SOURCE_DIR}/src/server/game/DungeonFinding ${CMAKE_SOURCE_DIR}/src/server/game/Entities/AreaTrigger ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Corpse ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Creature ${CMAKE_SOURCE_DIR}/src/server/game/Entities/DynamicObject + ${CMAKE_SOURCE_DIR}/src/server/game/Entities/GameObject ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Item ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Item/Container - ${CMAKE_SOURCE_DIR}/src/server/game/Entities/GameObject ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Object ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Object/Updates ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Pet @@ -116,19 +101,16 @@ include_directories( ${CMAKE_SOURCE_DIR}/src/server/game/Guilds ${CMAKE_SOURCE_DIR}/src/server/game/Handlers ${CMAKE_SOURCE_DIR}/src/server/game/Instances - ${CMAKE_SOURCE_DIR}/src/server/game/LookingForGroup ${CMAKE_SOURCE_DIR}/src/server/game/Loot ${CMAKE_SOURCE_DIR}/src/server/game/Mails - ${CMAKE_SOURCE_DIR}/src/server/game/Miscellaneous ${CMAKE_SOURCE_DIR}/src/server/game/Maps + ${CMAKE_SOURCE_DIR}/src/server/game/Miscellaneous ${CMAKE_SOURCE_DIR}/src/server/game/Movement ${CMAKE_SOURCE_DIR}/src/server/game/Movement/MovementGenerators ${CMAKE_SOURCE_DIR}/src/server/game/Movement/Spline ${CMAKE_SOURCE_DIR}/src/server/game/Movement/Waypoints - ${CMAKE_SOURCE_DIR}/src/server/game/Opcodes ${CMAKE_SOURCE_DIR}/src/server/game/OutdoorPvP ${CMAKE_SOURCE_DIR}/src/server/game/Pools - ${CMAKE_SOURCE_DIR}/src/server/game/PrecompiledHeaders ${CMAKE_SOURCE_DIR}/src/server/game/Quests ${CMAKE_SOURCE_DIR}/src/server/game/Reputation ${CMAKE_SOURCE_DIR}/src/server/game/Scripting @@ -141,10 +123,13 @@ include_directories( ${CMAKE_SOURCE_DIR}/src/server/game/Tickets ${CMAKE_SOURCE_DIR}/src/server/game/Tools ${CMAKE_SOURCE_DIR}/src/server/game/Warden - ${CMAKE_SOURCE_DIR}/src/server/game/Warden/Modules ${CMAKE_SOURCE_DIR}/src/server/game/Weather ${CMAKE_SOURCE_DIR}/src/server/game/World - ${CMAKE_CURRENT_SOURCE_DIR}/PrecompiledHeaders + ${CMAKE_SOURCE_DIR}/src/server/shared + ${CMAKE_SOURCE_DIR}/src/server/shared/DataStores + ${CMAKE_SOURCE_DIR}/src/server/shared/Dynamic + ${CMAKE_SOURCE_DIR}/src/server/shared/Dynamic/LinkedReference + ${CMAKE_SOURCE_DIR}/src/server/shared/Packets ${MYSQL_INCLUDE_DIR} ${VALGRIND_INCLUDE_DIR} ) @@ -156,8 +141,6 @@ add_library(scripts STATIC ${scripts_STAT_PCH_SRC} ) -add_dependencies(scripts revision.h) - # Generate precompiled header if (USE_SCRIPTPCH) add_cxx_pch(scripts ${scripts_STAT_PCH_HDR} ${scripts_STAT_PCH_SRC}) diff --git a/src/server/scripts/Commands/cs_cheat.cpp b/src/server/scripts/Commands/cs_cheat.cpp index 07fae339996..558a4167554 100644 --- a/src/server/scripts/Commands/cs_cheat.cpp +++ b/src/server/scripts/Commands/cs_cheat.cpp @@ -24,7 +24,6 @@ EndScriptData */ #include "Chat.h" #include "Language.h" -#include "ObjectMgr.h" #include "Player.h" #include "ScriptMgr.h" @@ -166,8 +165,8 @@ public: { Player* player = handler->GetSession()->GetPlayer(); - const char* enabled = "enabled"; - const char* disabled = "disabled"; + const char* enabled = "ON"; + const char* disabled = "OFF"; handler->SendSysMessage(LANG_COMMAND_CHEAT_STATUS); handler->PSendSysMessage(LANG_COMMAND_CHEAT_GOD, player->GetCommandStatus(CHEAT_GOD) ? enabled : disabled); @@ -175,6 +174,8 @@ public: handler->PSendSysMessage(LANG_COMMAND_CHEAT_CT, player->GetCommandStatus(CHEAT_CASTTIME) ? enabled : disabled); handler->PSendSysMessage(LANG_COMMAND_CHEAT_POWER, player->GetCommandStatus(CHEAT_POWER) ? enabled : disabled); handler->PSendSysMessage(LANG_COMMAND_CHEAT_WW, player->GetCommandStatus(CHEAT_WATERWALK) ? enabled : disabled); + handler->PSendSysMessage(LANG_COMMAND_CHEAT_TAXINODES, player->isTaxiCheater() ? enabled : disabled); + return true; } @@ -187,13 +188,7 @@ public: Player* target = handler->GetSession()->GetPlayer(); if (!*args) - { argstr = (target->GetCommandStatus(CHEAT_WATERWALK)) ? "off" : "on"; - if (target->GetCommandStatus(CHEAT_WATERWALK)) - argstr = "off"; - else - argstr = "on"; - } if (argstr == "off") { @@ -215,15 +210,7 @@ public: static bool HandleTaxiCheatCommand(ChatHandler* handler, const char* args) { - if (!*args) - { - handler->SendSysMessage(LANG_USE_BOL); - handler->SetSentErrorMessage(true); - return false; - } - std::string argstr = (char*)args; - Player* chr = handler->getSelectedPlayer(); if (!chr) @@ -231,13 +218,9 @@ public: else if (handler->HasLowerSecurity(chr, ObjectGuid::Empty)) // check online security return false; - if (argstr == "on") + if (!*args) { - chr->SetTaxiCheater(true); - handler->PSendSysMessage(LANG_YOU_GIVE_TAXIS, handler->GetNameLink(chr).c_str()); - if (handler->needReportToTarget(chr)) - ChatHandler(chr->GetSession()).PSendSysMessage(LANG_YOURS_TAXIS_ADDED, handler->GetNameLink().c_str()); - return true; + argstr = (chr->isTaxiCheater()) ? "off" : "on"; } if (argstr == "off") @@ -246,7 +229,14 @@ public: handler->PSendSysMessage(LANG_YOU_REMOVE_TAXIS, handler->GetNameLink(chr).c_str()); if (handler->needReportToTarget(chr)) ChatHandler(chr->GetSession()).PSendSysMessage(LANG_YOURS_TAXIS_REMOVED, handler->GetNameLink().c_str()); - + return true; + } + else if (argstr == "on") + { + chr->SetTaxiCheater(true); + handler->PSendSysMessage(LANG_YOU_GIVE_TAXIS, handler->GetNameLink(chr).c_str()); + if (handler->needReportToTarget(chr)) + ChatHandler(chr->GetSession()).PSendSysMessage(LANG_YOURS_TAXIS_ADDED, handler->GetNameLink().c_str()); return true; } @@ -260,10 +250,11 @@ public: if (!*args) return false; + // std::int flag = (char*)args; int flag = atoi((char*)args); Player* chr = handler->getSelectedPlayer(); - if (chr == NULL) + if (!chr) { handler->SendSysMessage(LANG_NO_CHAR_SELECTED); handler->SetSentErrorMessage(true); diff --git a/src/server/scripts/Commands/cs_debug.cpp b/src/server/scripts/Commands/cs_debug.cpp index 97b87c5fe08..e654f3f7c85 100644 --- a/src/server/scripts/Commands/cs_debug.cpp +++ b/src/server/scripts/Commands/cs_debug.cpp @@ -33,6 +33,7 @@ EndScriptData */ #include "GossipDef.h" #include "Transport.h" #include "Language.h" +#include "MapManager.h" #include @@ -94,6 +95,7 @@ public: { "moveflags", rbac::RBAC_PERM_COMMAND_DEBUG_MOVEFLAGS, false, &HandleDebugMoveflagsCommand, "", NULL }, { "transport", rbac::RBAC_PERM_COMMAND_DEBUG_TRANSPORT, false, &HandleDebugTransportCommand, "", NULL }, { "phase", rbac::RBAC_PERM_COMMAND_DEBUG_PHASE, false, &HandleDebugPhaseCommand, "", NULL }, + { "loadcells", rbac::RBAC_PERM_COMMAND_DEBUG_LOADCELLS, false, &HandleDebugLoadCellsCommand, "", NULL }, { NULL, 0, false, NULL, "", NULL } }; static ChatCommand commandTable[] = @@ -1420,6 +1422,30 @@ public: handler->SendSysMessage("Target is not phased"); return true; } + + static bool HandleDebugLoadCellsCommand(ChatHandler* handler, char const* args) + { + Player* player = handler->GetSession()->GetPlayer(); + if (!player) + return false; + + Map* map = nullptr; + + if (*args) + { + int32 mapId = atoi(args); + map = sMapMgr->FindBaseNonInstanceMap(mapId); + } + if (!map) + map = player->GetMap(); + + for (uint32 cellX = 0; cellX < TOTAL_NUMBER_OF_CELLS_PER_MAP; cellX++) + for (uint32 cellY = 0; cellY < TOTAL_NUMBER_OF_CELLS_PER_MAP; cellY++) + map->LoadGrid((cellX + 0.5f - CENTER_GRID_CELL_ID) * SIZE_OF_GRID_CELL, (cellY + 0.5f - CENTER_GRID_CELL_ID) * SIZE_OF_GRID_CELL); + + handler->PSendSysMessage("Cells loaded (mapId: %u)", map->GetId()); + return true; + } }; void AddSC_debug_commandscript() diff --git a/src/server/scripts/Commands/cs_lfg.cpp b/src/server/scripts/Commands/cs_lfg.cpp index d1662f3a97c..8bb64a454d2 100644 --- a/src/server/scripts/Commands/cs_lfg.cpp +++ b/src/server/scripts/Commands/cs_lfg.cpp @@ -150,7 +150,7 @@ public: static bool HandleLfgQueueInfoCommand(ChatHandler* handler, char const* args) { - handler->SendSysMessage(sLFGMgr->DumpQueueInfo(*args != '\0').c_str()); + handler->SendSysMessage(sLFGMgr->DumpQueueInfo(*args != '\0').c_str(), true); return true; } diff --git a/src/server/scripts/Commands/cs_server.cpp b/src/server/scripts/Commands/cs_server.cpp index 0fecdea5ced..6fa84d1bc75 100644 --- a/src/server/scripts/Commands/cs_server.cpp +++ b/src/server/scripts/Commands/cs_server.cpp @@ -28,7 +28,7 @@ EndScriptData */ #include "ObjectAccessor.h" #include "Player.h" #include "ScriptMgr.h" -#include "SystemConfig.h" +#include "GitRevision.h" class server_commandscript : public CommandScript { @@ -115,7 +115,7 @@ public: std::string uptime = secsToTimeString(sWorld->GetUptime()); uint32 updateTime = sWorld->GetUpdateTime(); - handler->SendSysMessage(_FULLVERSION); + handler->SendSysMessage(GitRevision::GetFullVersion()); handler->PSendSysMessage(LANG_CONNECTED_PLAYERS, playersNum, maxPlayersNum); handler->PSendSysMessage(LANG_CONNECTED_USERS, activeClientsNum, maxActiveClientsNum, queuedClientsNum, maxQueuedClientsNum); handler->PSendSysMessage(LANG_UPTIME, uptime.c_str()); diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/blackrock_depths.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/blackrock_depths.cpp index dd49f01624b..9c9dfe38349 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/blackrock_depths.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/blackrock_depths.cpp @@ -579,105 +579,6 @@ enum DughalQuests #define SAY_DUGHAL_FREE "Thank you, $N! I'm free!!!" #define GOSSIP_DUGHAL "You're free, Dughal! Get out of here!" -/* -class npc_dughal_stormwing : public CreatureScript -{ -public: - npc_dughal_stormwing() : CreatureScript("npc_dughal_stormwing") { } - - CreatureAI* GetAI(Creature* creature) const override - { - npc_dughal_stormwingAI* dughal_stormwingAI = new npc_dughal_stormwingAI(creature); - - dughal_stormwingAI->AddWaypoint(0, 280.42f, -82.86f, -77.12f, 0); - dughal_stormwingAI->AddWaypoint(1, 287.64f, -87.01f, -76.79f, 0); - dughal_stormwingAI->AddWaypoint(2, 354.63f, -64.95f, -67.53f, 0); - - return dughal_stormwingAI; - } - - bool OnGossipSelect(Player* player, Creature* creature, uint32 sender, uint32 action) override - { - player->PlayerTalkClass->ClearMenus(); - if (action == GOSSIP_ACTION_INFO_DEF + 1) - { - player->CLOSE_GOSSIP_MENU(); - CAST_AI(npc_escort::npc_escortAI, (creature->AI()))->Start(false, true, player->GetGUID()); - creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - instance->SetData(DATA_QUEST_JAIL_BREAK, ENCOUNTER_STATE_IN_PROGRESS); - } - return true; - } - - bool OnGossipHello(Player* player, Creature* creature) override - { - if (player->GetQuestStatus(QUEST_JAIL_BREAK) == QUEST_STATUS_INCOMPLETE && instance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_IN_PROGRESS) - { - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_DUGHAL, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - player->SEND_GOSSIP_MENU(2846, creature->GetGUID()); - } - return true; - } - - struct npc_dughal_stormwingAI : public npc_escortAI - { - npc_dughal_stormwingAI(Creature* creature) : npc_escortAI(creature) { } - - void WaypointReached(uint32 waypointId) override - { - switch (waypointId) - { - case 0: - me->Say(SAY_DUGHAL_FREE, LANG_UNIVERSAL, PlayerGUID); - break; - case 1: - instance->SetData(DATA_DUGHAL, ENCOUNTER_STATE_OBJECTIVE_COMPLETED); - break; - case 2: - me->SetVisible(false); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - instance->SetData(DATA_DUGHAL, ENCOUNTER_STATE_ENDED); - break; - } - } - - void EnterCombat(Unit* who) override { } - void Reset() override { } - - void JustDied(Unit* killer) override - { - if (IsBeingEscorted && killer == me) - { - me->SetVisible(false); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - instance->SetData(DATA_DUGHAL, ENCOUNTER_STATE_ENDED); - } - } - - void UpdateAI(uint32 diff) override - { - if (instance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_NOT_STARTED) return; - if ((instance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_IN_PROGRESS || instance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_FAILED || instance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_ENDED)&& instance->GetData(DATA_DUGHAL) == ENCOUNTER_STATE_ENDED) - { - me->SetVisible(false); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - else - { - me->SetVisible(true); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - npc_escortAI::UpdateAI(diff); - } - }; -}; - - */ - // npc_marshal_windsor #define SAY_WINDSOR_AGGRO1 "You locked up the wrong Marshal. Prepare to be destroyed!" #define SAY_WINDSOR_AGGRO2 "I bet you're sorry now, aren't you !?!!" @@ -694,168 +595,6 @@ enum MarshalWindsor NPC_REGINALD_WINDSOR = 9682 }; -/* -Player* playerStart; -class npc_marshal_windsor : public CreatureScript -{ -public: - npc_marshal_windsor() : CreatureScript("npc_marshal_windsor") { } - - CreatureAI* GetAI(Creature* creature) const override - { - npc_marshal_windsorAI* marshal_windsorAI = new npc_marshal_windsorAI(creature); - - marshal_windsorAI->AddWaypoint(0, 316.336f, -225.528f, -77.7258f, 7000); - marshal_windsorAI->AddWaypoint(1, 316.336f, -225.528f, -77.7258f, 2000); - marshal_windsorAI->AddWaypoint(2, 322.96f, -207.13f, -77.87f, 0); - marshal_windsorAI->AddWaypoint(3, 281.05f, -172.16f, -75.12f, 0); - marshal_windsorAI->AddWaypoint(4, 272.19f, -139.14f, -70.61f, 0); - marshal_windsorAI->AddWaypoint(5, 283.62f, -116.09f, -70.21f, 0); - marshal_windsorAI->AddWaypoint(6, 296.18f, -94.30f, -74.08f, 0); - marshal_windsorAI->AddWaypoint(7, 294.57f, -93.11f, -74.08f, 0); - marshal_windsorAI->AddWaypoint(8, 314.31f, -74.31f, -76.09f, 0); - marshal_windsorAI->AddWaypoint(9, 360.22f, -62.93f, -66.77f, 0); - marshal_windsorAI->AddWaypoint(10, 383.38f, -69.40f, -63.25f, 0); - marshal_windsorAI->AddWaypoint(11, 389.99f, -67.86f, -62.57f, 0); - marshal_windsorAI->AddWaypoint(12, 400.98f, -72.01f, -62.31f, 0); - marshal_windsorAI->AddWaypoint(13, 404.22f, -62.30f, -63.50f, 2300); - marshal_windsorAI->AddWaypoint(14, 404.22f, -62.30f, -63.50f, 1500); - marshal_windsorAI->AddWaypoint(15, 407.65f, -51.86f, -63.96f, 0); - marshal_windsorAI->AddWaypoint(16, 403.61f, -51.71f, -63.92f, 1000); - marshal_windsorAI->AddWaypoint(17, 403.61f, -51.71f, -63.92f, 2000); - marshal_windsorAI->AddWaypoint(18, 403.61f, -51.71f, -63.92f, 1000); - marshal_windsorAI->AddWaypoint(19, 403.61f, -51.71f, -63.92f, 0); - - return marshal_windsorAI; - } - - bool OnQuestAccept(Player* player, Creature* creature, Quest const* quest) override - { - if (quest->GetQuestId() == 4322) - { - PlayerStart = player; - if (instance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_NOT_STARTED) - { - CAST_AI(npc_escort::npc_escortAI, (creature->AI()))->Start(true, false, player->GetGUID()); - instance->SetData(DATA_QUEST_JAIL_BREAK, ENCOUNTER_STATE_IN_PROGRESS); - creature->setFaction(11); - } - } - return false; - } - - struct npc_marshal_windsorAI : public npc_escortAI - { - npc_marshal_windsorAI(Creature* creature) : npc_escortAI(creature) - { - instance = creature->GetInstanceScript(); - } - - void WaypointReached(uint32 waypointId) override - { - switch (waypointId) - { - case 1: - me->Say(SAY_WINDSOR_1, LANG_UNIVERSAL, PlayerGUID); - break; - case 7: - me->HandleEmoteCommand(EMOTE_STATE_POINT); - me->Say(SAY_WINDSOR_4_1, LANG_UNIVERSAL, PlayerGUID); - IsOnHold = true; - break; - case 10: - me->setFaction(534); - break; - case 12: - me->Say(SAY_WINDSOR_6, LANG_UNIVERSAL, PlayerGUID); - instance->SetData(DATA_SUPPLY_ROOM, ENCOUNTER_STATE_IN_PROGRESS); - break; - case 13: - me->HandleEmoteCommand(EMOTE_STATE_USESTANDING);//EMOTE_STATE_WORK - break; - case 14: - instance->SetData(DATA_GATE_SR, 0); - me->setFaction(11); - break; - case 16: - me->Say(SAY_WINDSOR_9, LANG_UNIVERSAL, PlayerGUID); - break; - case 17: - me->HandleEmoteCommand(EMOTE_STATE_USESTANDING);//EMOTE_STATE_WORK - break; - case 18: - instance->SetData(DATA_GATE_SC, 0); - break; - case 19: - me->SetVisible(false); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->SummonCreature(NPC_REGINALD_WINDSOR, 403.61f, -51.71f, -63.92f, 3.600434f, TEMPSUMMON_DEAD_DESPAWN, 0); - instance->SetData(DATA_SUPPLY_ROOM, ENCOUNTER_STATE_ENDED); - break; - } - } - - void EnterCombat(Unit* who) override - { - switch (urand(0, 2)) - { - case 0: - me->Say(SAY_WINDSOR_AGGRO1, LANG_UNIVERSAL, PlayerGUID); - break; - case 1: - me->Say(SAY_WINDSOR_AGGRO2, LANG_UNIVERSAL, PlayerGUID); - break; - case 2: - me->Say(SAY_WINDSOR_AGGRO3, LANG_UNIVERSAL, PlayerGUID); - break; - } - } - - void Reset() override { } - - void JustDied(Unit* slayer) override - { - instance->SetData(DATA_QUEST_JAIL_BREAK, ENCOUNTER_STATE_FAILED); - } - - void UpdateAI(uint32 diff) override - { - if (instance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_NOT_STARTED) - return; - - if (instance->GetData(DATA_DUGHAL) == ENCOUNTER_STATE_OBJECTIVE_COMPLETED) - SetEscortPaused(false); - - if (!instance->GetData(DATA_GATE_D) && instance->GetData(DATA_DUGHAL) == ENCOUNTER_STATE_NOT_STARTED) - { - me->Say(SAY_WINDSOR_4_2, LANG_UNIVERSAL, PlayerGUID); - instance->SetData(DATA_DUGHAL, ENCOUNTER_STATE_BEFORE_START); - } - if (instance->GetData(DATA_DUGHAL) == ENCOUNTER_STATE_OBJECTIVE_COMPLETED) - { - me->Say(SAY_WINDSOR_4_3, LANG_UNIVERSAL, PlayerGUID); - instance->SetData(DATA_DUGHAL, ENCOUNTER_STATE_ENDED); - } - if ((instance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_IN_PROGRESS || instance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_FAILED || instance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_ENDED)&& instance->GetData(DATA_SUPPLY_ROOM) == ENCOUNTER_STATE_ENDED) - { - me->SetVisible(false); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - else - { - me->SetVisible(true); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - npc_escortAI::UpdateAI(diff); - } - }; -}; - - */ - // npc_marshal_reginald_windsor #define SAY_REGINALD_WINDSOR_0_1 "Can you feel the power, $N??? It's time to ROCK!" #define SAY_REGINALD_WINDSOR_0_2 "Now we just have to free Tobias and we can get out of here. This way!" @@ -878,320 +617,6 @@ enum MarshalReginaldWindor NPC_CREST_KILLER = 9680 }; -/* -int wp = 0; -class npc_marshal_reginald_windsor : public CreatureScript -{ -public: - npc_marshal_reginald_windsor() : CreatureScript("npc_marshal_reginald_windsor") { } - - CreatureAI* GetAI(Creature* creature) const override - { - npc_marshal_reginald_windsorAI* marshal_reginald_windsorAI = new npc_marshal_reginald_windsorAI(creature); - - marshal_reginald_windsorAI->AddWaypoint(0, 403.61f, -52.71f, -63.92f, 4000); - marshal_reginald_windsorAI->AddWaypoint(1, 403.61f, -52.71f, -63.92f, 4000); - marshal_reginald_windsorAI->AddWaypoint(2, 406.33f, -54.87f, -63.95f, 0); - marshal_reginald_windsorAI->AddWaypoint(3, 407.99f, -73.91f, -62.26f, 0); - marshal_reginald_windsorAI->AddWaypoint(4, 557.03f, -119.71f, -61.83f, 0); - marshal_reginald_windsorAI->AddWaypoint(5, 573.40f, -124.39f, -65.07f, 0); - marshal_reginald_windsorAI->AddWaypoint(6, 593.91f, -130.29f, -69.25f, 0); - marshal_reginald_windsorAI->AddWaypoint(7, 593.21f, -132.16f, -69.25f, 0); - marshal_reginald_windsorAI->AddWaypoint(8, 593.21f, -132.16f, -69.25f, 3000); - marshal_reginald_windsorAI->AddWaypoint(9, 622.81f, -135.55f, -71.92f, 0); - marshal_reginald_windsorAI->AddWaypoint(10, 634.68f, -151.29f, -70.32f, 0); - marshal_reginald_windsorAI->AddWaypoint(11, 635.06f, -153.25f, -70.32f, 0); - marshal_reginald_windsorAI->AddWaypoint(12, 635.06f, -153.25f, -70.32f, 3000); - marshal_reginald_windsorAI->AddWaypoint(13, 635.06f, -153.25f, -70.32f, 1500); - marshal_reginald_windsorAI->AddWaypoint(14, 655.25f, -172.39f, -73.72f, 0); - marshal_reginald_windsorAI->AddWaypoint(15, 654.79f, -226.30f, -83.06f, 0); - marshal_reginald_windsorAI->AddWaypoint(16, 622.85f, -268.85f, -83.96f, 0); - marshal_reginald_windsorAI->AddWaypoint(17, 579.45f, -275.56f, -80.44f, 0); - marshal_reginald_windsorAI->AddWaypoint(18, 561.19f, -266.85f, -75.59f, 0); - marshal_reginald_windsorAI->AddWaypoint(19, 547.91f, -253.92f, -70.34f, 0); - marshal_reginald_windsorAI->AddWaypoint(20, 549.20f, -252.40f, -70.34f, 0); - marshal_reginald_windsorAI->AddWaypoint(21, 549.20f, -252.40f, -70.34f, 4000); - marshal_reginald_windsorAI->AddWaypoint(22, 555.33f, -269.16f, -74.40f, 0); - marshal_reginald_windsorAI->AddWaypoint(23, 554.31f, -270.88f, -74.40f, 0); - marshal_reginald_windsorAI->AddWaypoint(24, 554.31f, -270.88f, -74.40f, 4000); - marshal_reginald_windsorAI->AddWaypoint(25, 536.10f, -249.60f, -67.47f, 0); - marshal_reginald_windsorAI->AddWaypoint(26, 520.94f, -216.65f, -59.28f, 0); - marshal_reginald_windsorAI->AddWaypoint(27, 505.99f, -148.74f, -62.17f, 0); - marshal_reginald_windsorAI->AddWaypoint(28, 484.21f, -56.24f, -62.43f, 0); - marshal_reginald_windsorAI->AddWaypoint(29, 470.39f, -6.01f, -70.10f, 0); - marshal_reginald_windsorAI->AddWaypoint(30, 451.27f, 30.85f, -70.07f, 0); - marshal_reginald_windsorAI->AddWaypoint(31, 452.45f, 29.85f, -70.37f, 1500); - marshal_reginald_windsorAI->AddWaypoint(32, 452.45f, 29.85f, -70.37f, 7000); - marshal_reginald_windsorAI->AddWaypoint(33, 452.45f, 29.85f, -70.37f, 10000); - marshal_reginald_windsorAI->AddWaypoint(34, 451.27f, 31.85f, -70.07f, 0); - - return marshal_reginald_windsorAI; - } - - struct npc_marshal_reginald_windsorAI : public npc_escortAI - { - npc_marshal_reginald_windsorAI(Creature* creature) : npc_escortAI(creature) - { - } - - void WaypointReached(uint32 waypointId) override - { - wp = waypointId; - switch (waypointId) - { - case 0: - me->setFaction(11); - me->Say(SAY_REGINALD_WINDSOR_0_1, LANG_UNIVERSAL, PlayerGUID); - break; - case 1: - me->Say(SAY_REGINALD_WINDSOR_0_2, LANG_UNIVERSAL, PlayerGUID); - break; - case 7: - me->HandleEmoteCommand(EMOTE_STATE_POINT); - me->Say(SAY_REGINALD_WINDSOR_5_1, LANG_UNIVERSAL, PlayerGUID); - IsOnHold=true; - break; - case 8: - me->Say(SAY_REGINALD_WINDSOR_5_2, LANG_UNIVERSAL, PlayerGUID); - break; - case 11: - me->HandleEmoteCommand(EMOTE_STATE_POINT); - me->Say(SAY_REGINALD_WINDSOR_7_1, LANG_UNIVERSAL, PlayerGUID); - IsOnHold=true; - break; - case 12: - me->Say(SAY_REGINALD_WINDSOR_7_2, LANG_UNIVERSAL, PlayerGUID); - break; - case 13: - me->Say(SAY_REGINALD_WINDSOR_7_3, LANG_UNIVERSAL, PlayerGUID); - break; - case 20: - me->HandleEmoteCommand(EMOTE_STATE_POINT); - me->Say(SAY_REGINALD_WINDSOR_13_1, LANG_UNIVERSAL, PlayerGUID); - IsOnHold=true; - break; - case 21: - me->Say(SAY_REGINALD_WINDSOR_13_3, LANG_UNIVERSAL, PlayerGUID); - break; - case 23: - me->HandleEmoteCommand(EMOTE_STATE_POINT); - me->Say(SAY_REGINALD_WINDSOR_14_1, LANG_UNIVERSAL, PlayerGUID); - IsOnHold=true; - break; - case 24: - me->Say(SAY_REGINALD_WINDSOR_14_2, LANG_UNIVERSAL, PlayerGUID); - break; - case 31: - me->Say(SAY_REGINALD_WINDSOR_20_1, LANG_UNIVERSAL, PlayerGUID); - break; - case 32: - me->Say(SAY_REGINALD_WINDSOR_20_2, LANG_UNIVERSAL, PlayerGUID); - PlayerStart->GroupEventHappens(QUEST_JAIL_BREAK, me); - instance->SetData(DATA_SHILL, ENCOUNTER_STATE_ENDED); - break; - } - } - - void MoveInLineOfSight(Unit* who) override - - { - if (HasEscortState(STATE_ESCORT_ESCORTING)) - return; - - if (Player* player = who->ToPlayer()) - { - if (player->GetQuestStatus(4322) == QUEST_STATUS_INCOMPLETE) - { - float Radius = 10.0f; - if (me->IsWithinDistInMap(who, Radius)) - { - SetEscortPaused(false); - Start(true, false, who->GetGUID()); - } - } - } - } - - void EnterCombat(Unit* who) override - { - switch (urand(0, 2)) - { - case 0: - me->Say(SAY_WINDSOR_AGGRO1, LANG_UNIVERSAL, PlayerGUID); - break; - case 1: - me->Say(SAY_WINDSOR_AGGRO2, LANG_UNIVERSAL, PlayerGUID); - break; - case 2: - me->Say(SAY_WINDSOR_AGGRO3, LANG_UNIVERSAL, PlayerGUID); - break; - } - } - void Reset() override { } - - void JustDied(Unit* slayer) override - { - instance->SetData(DATA_QUEST_JAIL_BREAK, ENCOUNTER_STATE_FAILED); - } - - void UpdateAI(uint32 diff) override - { - if (instance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_NOT_STARTED) - return; - - if (wp == 7) - { - if (!instance->GetData(DATA_GATE_J) && instance->GetData(DATA_JAZ) == ENCOUNTER_STATE_NOT_STARTED) - { - instance->SetData(DATA_NPC_JAZ, 1); - instance->SetData(DATA_JAZ, ENCOUNTER_STATE_IN_PROGRESS); - } - if (instance->GetData(DATA_NPC_JAZ) && instance->GetData(DATA_NPC_OGRABISI) && instance->GetData(DATA_JAZ) == ENCOUNTER_STATE_IN_PROGRESS) - { - SetEscortPaused(false); - instance->SetData(DATA_JAZ, ENCOUNTER_STATE_ENDED); - } - } - else if (wp == 11) - { - if (!instance->GetData(DATA_GATE_S) && instance->GetData(DATA_SHILL) == ENCOUNTER_STATE_NOT_STARTED) - { - instance->SetData(DATA_NPC_SHILL, 1); - instance->SetData(DATA_SHILL, ENCOUNTER_STATE_IN_PROGRESS); - } - if (instance->GetData(DATA_NPC_SHILL) && instance->GetData(DATA_SHILL) == ENCOUNTER_STATE_IN_PROGRESS) - { - instance->SetData(DATA_SHILL, ENCOUNTER_STATE_ENDED); - SetEscortPaused(false); - } - } - else if (wp == 20) - { - if (!instance->GetData(DATA_GATE_C) && instance->GetData(DATA_CREST) == ENCOUNTER_STATE_NOT_STARTED) - { - instance->SetData(DATA_NPC_CREST, 1); - me->Say(SAY_REGINALD_WINDSOR_13_2, LANG_UNIVERSAL, PlayerGUID); - instance->SetData(DATA_CREST, ENCOUNTER_STATE_IN_PROGRESS); - } - if (instance->GetData(DATA_NPC_CREST) && instance->GetData(DATA_CREST) == ENCOUNTER_STATE_IN_PROGRESS) - { - SetEscortPaused(false); - instance->SetData(DATA_CREST, ENCOUNTER_STATE_ENDED); - } - } - if (instance->GetData(DATA_TOBIAS) == ENCOUNTER_STATE_OBJECTIVE_COMPLETED) SetEscortPaused(false); - npc_escortAI::UpdateAI(diff); - } - }; -}; -*/ - -// npc_tobias_seecher -#define SAY_TOBIAS_FREE "Thank you! I will run for safety immediately!" - -/* -class npc_tobias_seecher : public CreatureScript -{ -public: - npc_tobias_seecher() : CreatureScript("npc_tobias_seecher") { } - - CreatureAI* GetAI(Creature* creature) const override - { - npc_tobias_seecherAI* tobias_seecherAI = new npc_tobias_seecherAI(creature); - - tobias_seecherAI->AddWaypoint(0, 549.21f, -281.07f, -75.27f); - tobias_seecherAI->AddWaypoint(1, 554.39f, -267.39f, -73.68f); - tobias_seecherAI->AddWaypoint(2, 533.59f, -249.38f, -67.04f); - tobias_seecherAI->AddWaypoint(3, 519.44f, -217.02f, -59.34f); - tobias_seecherAI->AddWaypoint(4, 506.55f, -153.49f, -62.34f); - - return tobias_seecherAI; - } - - bool OnGossipSelect(Player* player, Creature* creature, uint32 sender, uint32 action) override - { - player->PlayerTalkClass->ClearMenus(); - if (action == GOSSIP_ACTION_INFO_DEF + 1) - { - player->CLOSE_GOSSIP_MENU(); - CAST_AI(npc_escort::npc_escortAI, (creature->AI()))->Start(false, true, player->GetGUID()); - creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - instance->SetData(DATA_TOBIAS, ENCOUNTER_STATE_IN_PROGRESS); - } - return true; - } - - bool OnGossipHello(Player* player, Creature* creature) override - { - if (player->GetQuestStatus(QUEST_JAIL_BREAK) == QUEST_STATUS_INCOMPLETE && instance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_IN_PROGRESS) - { - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Get out of here, Tobias, you're free!", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - player->SEND_GOSSIP_MENU(2847, creature->GetGUID()); - } - return true; - } - - struct npc_tobias_seecherAI : public npc_escortAI - { - npc_tobias_seecherAI(Creature* creature) : npc_escortAI(creature) { } - - void EnterCombat(Unit* who) override { } - void Reset() override { } - - void JustDied(Unit* killer) override - { - if (IsBeingEscorted && killer == me) - { - me->SetVisible(false); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - instance->SetData(DATA_TOBIAS, ENCOUNTER_STATE_ENDED); - } - } - - void WaypointReached(uint32 waypointId) override - { - switch (waypointId) - { - case 0: - me->Say(SAY_TOBIAS_FREE, LANG_UNIVERSAL, PlayerGUID); - break; - case 2: - instance->SetData(DATA_TOBIAS, ENCOUNTER_STATE_OBJECTIVE_COMPLETED); - break; - case 4: - me->SetVisible(false); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - instance->SetData(DATA_TOBIAS, ENCOUNTER_STATE_ENDED); - break; - } - } - - void UpdateAI(uint32 diff) override - { - if (instance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_NOT_STARTED) - return; - - if ((instance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_IN_PROGRESS || instance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_FAILED || instance->GetData(DATA_QUEST_JAIL_BREAK) == ENCOUNTER_STATE_ENDED)&& instance->GetData(DATA_TOBIAS) == ENCOUNTER_STATE_ENDED) - { - me->SetVisible(false); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - else - { - me->SetVisible(true); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - npc_escortAI::UpdateAI(diff); - } - }; -}; - -*/ - // npc_rocknot enum RocknotSays { @@ -1349,10 +774,4 @@ void AddSC_blackrock_depths() new npc_kharan_mighthammer(); new npc_lokhtos_darkbargainer(); new npc_rocknot(); - // Fix us - /*new npc_dughal_stormwing(); - new npc_tobias_seecher(); - new npc_marshal_windsor(); - new npc_marshal_reginald_windsor(); - */ } diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/blackwing_lair.h b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/blackwing_lair.h index c79a57d0746..12798833a3f 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/blackwing_lair.h +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/blackwing_lair.h @@ -25,14 +25,18 @@ uint32 const EncounterCount = 8; enum BWLEncounter { - BOSS_RAZORGORE = 0, - BOSS_VAELASTRAZ = 1, - BOSS_BROODLORD = 2, - BOSS_FIREMAW = 3, - BOSS_EBONROC = 4, - BOSS_FLAMEGOR = 5, - BOSS_CHROMAGGUS = 6, - BOSS_NEFARIAN = 7 + // Encounter States/Boss GUIDs + DATA_RAZORGORE_THE_UNTAMED = 0, + DATA_VAELASTRAZ_THE_CORRUPT = 1, + DATA_BROODLORD_LASHLAYER = 2, + DATA_FIREMAW = 3, + DATA_EBONROC = 4, + DATA_FLAMEGOR = 5, + DATA_CHROMAGGUS = 6, + DATA_NEFARIAN = 7, + + // Additional Data + DATA_LORD_VICTOR_NEFARIUS = 8 }; enum CreatureIds @@ -44,7 +48,7 @@ enum CreatureIds NPC_BLACKWING_WARLOCK = 12459, NPC_VAELASTRAZ = 13020, NPC_BROODLORD = 12017, - NPC_FIRENAW = 11983, + NPC_FIREMAW = 11983, NPC_EBONROC = 14601, NPC_FLAMEGOR = 11981, NPC_CHROMAGGUS = 14020, @@ -52,17 +56,14 @@ enum CreatureIds NPC_NEFARIAN = 11583 }; -enum BWLData64 +enum GameObjectIds { - DATA_RAZORGORE_THE_UNTAMED = 1, - DATA_VAELASTRAZ_THE_CORRUPT, - DATA_BROODLORD_LASHLAYER, - DATA_FIRENAW, - DATA_EBONROC, - DATA_FLAMEGOR, - DATA_CHROMAGGUS, - DATA_LORD_VICTOR_NEFARIUS, - DATA_NEFARIAN + GO_BLACK_DRAGON_EGG = 177807, + GO_BOSSGATE01 = 175946, + GO_DRAKE_RIDER_PORTCULLIS = 175185, + GO_ALTERAC_VALLEY_GATE = 180424, + GO_GATE = 185483, + GO_VACCUUM_EXIT_GATE = 181125 }; enum BWLEvents @@ -79,4 +80,4 @@ enum BWLMisc DATA_EGG_EVENT }; -#endif \ No newline at end of file +#endif diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_broodlord_lashlayer.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_broodlord_lashlayer.cpp index 2609cf5fdf8..5ba933005ec 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_broodlord_lashlayer.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_broodlord_lashlayer.cpp @@ -50,16 +50,10 @@ public: struct boss_broodlordAI : public BossAI { - boss_broodlordAI(Creature* creature) : BossAI(creature, BOSS_BROODLORD) { } + boss_broodlordAI(Creature* creature) : BossAI(creature, DATA_BROODLORD_LASHLAYER) { } void EnterCombat(Unit* /*who*/) override { - if (instance->GetBossState(BOSS_VAELASTRAZ) != DONE) - { - EnterEvadeMode(); - return; - } - _EnterCombat(); Talk(SAY_AGGRO); diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_chromaggus.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_chromaggus.cpp index 61d6c052cdf..9a49b96e68e 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_chromaggus.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_chromaggus.cpp @@ -71,7 +71,7 @@ public: struct boss_chromaggusAI : public BossAI { - boss_chromaggusAI(Creature* creature) : BossAI(creature, BOSS_CHROMAGGUS) + boss_chromaggusAI(Creature* creature) : BossAI(creature, DATA_CHROMAGGUS) { Initialize(); @@ -193,11 +193,6 @@ public: void EnterCombat(Unit* /*who*/) override { - if (instance->GetBossState(BOSS_FLAMEGOR) != DONE) - { - EnterEvadeMode(); - return; - } _EnterCombat(); events.ScheduleEvent(EVENT_SHIMMER, 0); diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_ebonroc.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_ebonroc.cpp index 8bd3ae0ebce..7a7e30f7913 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_ebonroc.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_ebonroc.cpp @@ -41,15 +41,10 @@ public: struct boss_ebonrocAI : public BossAI { - boss_ebonrocAI(Creature* creature) : BossAI(creature, BOSS_EBONROC) { } + boss_ebonrocAI(Creature* creature) : BossAI(creature, DATA_EBONROC) { } void EnterCombat(Unit* /*who*/) override { - if (instance->GetBossState(BOSS_BROODLORD) != DONE) - { - EnterEvadeMode(); - return; - } _EnterCombat(); events.ScheduleEvent(EVENT_SHADOWFLAME, urand(10000, 20000)); diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_firemaw.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_firemaw.cpp index e41153796e5..3dcdbfe01df 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_firemaw.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_firemaw.cpp @@ -41,15 +41,10 @@ public: struct boss_firemawAI : public BossAI { - boss_firemawAI(Creature* creature) : BossAI(creature, BOSS_FIREMAW) { } + boss_firemawAI(Creature* creature) : BossAI(creature, DATA_FIREMAW) { } void EnterCombat(Unit* /*who*/) override { - if (instance->GetBossState(BOSS_BROODLORD) != DONE) - { - EnterEvadeMode(); - return; - } _EnterCombat(); events.ScheduleEvent(EVENT_SHADOWFLAME, urand(10000, 20000)); diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_flamegor.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_flamegor.cpp index 011c695b61f..20e69211da2 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_flamegor.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_flamegor.cpp @@ -46,15 +46,10 @@ public: struct boss_flamegorAI : public BossAI { - boss_flamegorAI(Creature* creature) : BossAI(creature, BOSS_FLAMEGOR) { } + boss_flamegorAI(Creature* creature) : BossAI(creature, DATA_FLAMEGOR) { } void EnterCombat(Unit* /*who*/) override { - if (instance->GetBossState(BOSS_BROODLORD) != DONE) - { - EnterEvadeMode(); - return; - } _EnterCombat(); events.ScheduleEvent(EVENT_SHADOWFLAME, urand(10000, 20000)); diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_nefarian.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_nefarian.cpp index 6c0f8cad0f5..cd500610f20 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_nefarian.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_nefarian.cpp @@ -166,7 +166,7 @@ public: struct boss_victor_nefariusAI : public BossAI { - boss_victor_nefariusAI(Creature* creature) : BossAI(creature, BOSS_NEFARIAN) + boss_victor_nefariusAI(Creature* creature) : BossAI(creature, DATA_NEFARIAN) { Initialize(); } @@ -393,7 +393,7 @@ public: struct boss_nefarianAI : public BossAI { - boss_nefarianAI(Creature* creature) : BossAI(creature, BOSS_NEFARIAN) + boss_nefarianAI(Creature* creature) : BossAI(creature, DATA_NEFARIAN) { Initialize(); } @@ -457,7 +457,7 @@ public: { if (canDespawn && DespawnTimer <= diff) { - instance->SetBossState(BOSS_NEFARIAN, FAIL); + instance->SetBossState(DATA_NEFARIAN, FAIL); std::list constructList; me->GetCreatureListWithEntryInGrid(constructList, NPC_BONE_CONSTRUCT, 500.0f); diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_razorgore.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_razorgore.cpp index 8d660fc17d1..1d66964ce6b 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_razorgore.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_razorgore.cpp @@ -68,7 +68,7 @@ public: struct boss_razorgoreAI : public BossAI { - boss_razorgoreAI(Creature* creature) : BossAI(creature, BOSS_RAZORGORE) + boss_razorgoreAI(Creature* creature) : BossAI(creature, DATA_RAZORGORE_THE_UNTAMED) { Initialize(); } @@ -175,7 +175,7 @@ public: { if (InstanceScript* instance = go->GetInstanceScript()) if (instance->GetData(DATA_EGG_EVENT) != DONE) - if (Creature* razor = ObjectAccessor::GetCreature(*go, instance->GetGuidData(DATA_RAZORGORE_THE_UNTAMED))) + if (Creature* razor = instance->GetCreature(DATA_RAZORGORE_THE_UNTAMED)) { razor->Attack(player, true); player->CastSpell(razor, SPELL_MINDCONTROL); diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_vaelastrasz.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_vaelastrasz.cpp index 4a0ead606d7..983b6e33e64 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_vaelastrasz.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_vaelastrasz.cpp @@ -68,7 +68,7 @@ public: struct boss_vaelAI : public BossAI { - boss_vaelAI(Creature* creature) : BossAI(creature, BOSS_VAELASTRAZ) + boss_vaelAI(Creature* creature) : BossAI(creature, DATA_VAELASTRAZ_THE_CORRUPT) { Initialize(); creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/instance_blackwing_lair.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/instance_blackwing_lair.cpp index b8843afef98..9ba255991c0 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/instance_blackwing_lair.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/instance_blackwing_lair.cpp @@ -15,23 +15,36 @@ * with this program. If not, see . */ -#include "ScriptMgr.h" -#include "ScriptedCreature.h" -#include "PassiveAI.h" -#include "blackwing_lair.h" #include "Player.h" +#include "ScriptedCreature.h" +#include "ScriptMgr.h" +#include "blackwing_lair.h" -/* -Blackwing Lair Encounter: -1 - boss_razorgore.cpp -2 - boss_vaelastrasz.cpp -3 - boss_broodlord_lashlayer.cpp -4 - boss_firemaw.cpp -5 - boss_ebonroc.cpp -6 - boss_flamegor.cpp -7 - boss_chromaggus.cpp -8 - boss_nefarian.cpp -*/ +DoorData const doorData[] = +{ + { GO_BOSSGATE01, DATA_RAZORGORE_THE_UNTAMED, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, + { GO_DRAKE_RIDER_PORTCULLIS, DATA_VAELASTRAZ_THE_CORRUPT, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, + { GO_ALTERAC_VALLEY_GATE, DATA_BROODLORD_LASHLAYER, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, + { GO_GATE, DATA_FIREMAW, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, + { GO_GATE, DATA_EBONROC, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, + { GO_GATE, DATA_FLAMEGOR, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, + { GO_VACCUUM_EXIT_GATE, DATA_CHROMAGGUS, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, + { 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE } // END +}; + +ObjectData const creatureData[] = +{ + { NPC_RAZORGORE, DATA_RAZORGORE_THE_UNTAMED }, + { NPC_VAELASTRAZ, DATA_VAELASTRAZ_THE_CORRUPT }, + { NPC_BROODLORD, DATA_BROODLORD_LASHLAYER }, + { NPC_FIREMAW, DATA_FIREMAW }, + { NPC_EBONROC, DATA_EBONROC }, + { NPC_FLAMEGOR, DATA_FLAMEGOR }, + { NPC_CHROMAGGUS, DATA_CHROMAGGUS }, + { NPC_NEFARIAN, DATA_NEFARIAN }, + { NPC_VICTOR_NEFARIUS, DATA_LORD_VICTOR_NEFARIUS }, + { 0, 0 } // END +}; Position const SummonPosition[8] = { @@ -57,92 +70,84 @@ public: instance_blackwing_lair_InstanceMapScript(Map* map) : InstanceScript(map) { SetHeaders(DataHeader); + SetBossNumber(EncounterCount); + LoadDoorData(doorData); + LoadObjectData(creatureData, nullptr); + // Razorgore EggCount = 0; EggEvent = 0; - SetBossNumber(EncounterCount); } void OnCreatureCreate(Creature* creature) override { + InstanceScript::OnCreatureCreate(creature); + switch (creature->GetEntry()) { - case NPC_RAZORGORE: - RazorgoreTheUntamedGUID = creature->GetGUID(); - break; case NPC_BLACKWING_DRAGON: case NPC_BLACKWING_TASKMASTER: case NPC_BLACKWING_LEGIONAIRE: case NPC_BLACKWING_WARLOCK: - if (Creature* razor = instance->GetCreature(RazorgoreTheUntamedGUID)) + if (Creature* razor = GetCreature(DATA_RAZORGORE_THE_UNTAMED)) razor->AI()->JustSummoned(creature); break; - case NPC_VAELASTRAZ: - VaelastraszTheCorruptGUID = creature->GetGUID(); - break; - case NPC_BROODLORD: - BroodlordLashlayerGUID = creature->GetGUID(); - break; - case NPC_FIRENAW: - FiremawGUID = creature->GetGUID(); - break; - case NPC_EBONROC: - EbonrocGUID = creature->GetGUID(); - break; - case NPC_FLAMEGOR: - FlamegorGUID = creature->GetGUID(); - break; - case NPC_CHROMAGGUS: - ChromaggusGUID = creature->GetGUID(); - break; - case NPC_VICTOR_NEFARIUS: - LordVictorNefariusGUID = creature->GetGUID(); - break; - case NPC_NEFARIAN: - NefarianGUID = creature->GetGUID(); + default: break; } } void OnGameObjectCreate(GameObject* go) override { - switch (go->GetEntry()) + InstanceScript::OnGameObjectCreate(go); + + if (go->GetEntry() == GO_BLACK_DRAGON_EGG) { - case 177807: // Egg - if (GetBossState(BOSS_FIREMAW) == DONE) - go->SetLootState(GO_JUST_DEACTIVATED); - else - EggList.push_back(go->GetGUID()); - break; - case 175946: // Door - RazorgoreDoorGUID = go->GetGUID(); - HandleGameObject(ObjectGuid::Empty, GetBossState(BOSS_RAZORGORE) == DONE, go); - break; - case 175185: // Door - VaelastraszDoorGUID = go->GetGUID(); - HandleGameObject(ObjectGuid::Empty, GetBossState(BOSS_VAELASTRAZ) == DONE, go); - break; - case 180424: // Door - BroodlordDoorGUID = go->GetGUID(); - HandleGameObject(ObjectGuid::Empty, GetBossState(BOSS_BROODLORD) == DONE, go); - break; - case 185483: // Door - ChrommagusDoorGUID = go->GetGUID(); - HandleGameObject(ObjectGuid::Empty, GetBossState(BOSS_FIREMAW) == DONE && GetBossState(BOSS_EBONROC) == DONE && GetBossState(BOSS_FLAMEGOR) == DONE, go); - break; - case 181125: // Door - NefarianDoorGUID = go->GetGUID(); - HandleGameObject(ObjectGuid::Empty, GetBossState(BOSS_CHROMAGGUS) == DONE, go); - break; + if (GetBossState(DATA_FIREMAW) == DONE) + go->SetPhaseMask(2, true); + else + EggList.push_back(go->GetGUID()); } } void OnGameObjectRemove(GameObject* go) override { - if (go->GetEntry() == 177807) // Egg + InstanceScript::OnGameObjectRemove(go); + + if (go->GetEntry() == GO_BLACK_DRAGON_EGG) EggList.remove(go->GetGUID()); } + bool CheckRequiredBosses(uint32 bossId, Player const* player /*= nullptr*/) const override + { + if (_SkipCheckRequiredBosses(player)) + return true; + + switch (bossId) + { + case DATA_BROODLORD_LASHLAYER: + if (GetBossState(DATA_VAELASTRAZ_THE_CORRUPT) != DONE) + return false; + break; + case DATA_FIREMAW: + case DATA_EBONROC: + case DATA_FLAMEGOR: + if (GetBossState(DATA_BROODLORD_LASHLAYER) != DONE) + return false; + break; + case DATA_CHROMAGGUS: + if (GetBossState(DATA_FIREMAW) != DONE + || GetBossState(DATA_EBONROC) != DONE + || GetBossState(DATA_FLAMEGOR) != DONE) + return false; + break; + default: + break; + } + + return true; + } + bool SetBossState(uint32 type, EncounterState state) override { if (!InstanceScript::SetBossState(type, state)) @@ -150,40 +155,25 @@ public: switch (type) { - case BOSS_RAZORGORE: - HandleGameObject(RazorgoreDoorGUID, state == DONE); + case DATA_RAZORGORE_THE_UNTAMED: if (state == DONE) { for (GuidList::const_iterator itr = EggList.begin(); itr != EggList.end(); ++itr) - if (GameObject* egg = instance->GetGameObject((*itr))) + if (GameObject* egg = instance->GetGameObject(*itr)) egg->SetLootState(GO_JUST_DEACTIVATED); } SetData(DATA_EGG_EVENT, NOT_STARTED); break; - case BOSS_VAELASTRAZ: - HandleGameObject(VaelastraszDoorGUID, state == DONE); - break; - case BOSS_BROODLORD: - HandleGameObject(BroodlordDoorGUID, state == DONE); - break; - case BOSS_FIREMAW: - case BOSS_EBONROC: - case BOSS_FLAMEGOR: - HandleGameObject(ChrommagusDoorGUID, GetBossState(BOSS_FIREMAW) == DONE && GetBossState(BOSS_EBONROC) == DONE && GetBossState(BOSS_FLAMEGOR) == DONE); - break; - case BOSS_CHROMAGGUS: - HandleGameObject(NefarianDoorGUID, state == DONE); - break; - case BOSS_NEFARIAN: + case DATA_NEFARIAN: switch (state) { case NOT_STARTED: - if (Creature* nefarian = instance->GetCreature(NefarianGUID)) + if (Creature* nefarian = GetCreature(DATA_NEFARIAN)) nefarian->DespawnOrUnsummon(); break; case FAIL: - _events.ScheduleEvent(EVENT_RESPAWN_NEFARIUS, 15*IN_MILLISECONDS*MINUTE); - SetBossState(BOSS_NEFARIAN, NOT_STARTED); + _events.ScheduleEvent(EVENT_RESPAWN_NEFARIUS, 15 * IN_MILLISECONDS * MINUTE); + SetBossState(DATA_NEFARIAN, NOT_STARTED); break; default: break; @@ -193,24 +183,6 @@ public: return true; } - ObjectGuid GetGuidData(uint32 id) const override - { - switch (id) - { - case DATA_RAZORGORE_THE_UNTAMED: return RazorgoreTheUntamedGUID; - case DATA_VAELASTRAZ_THE_CORRUPT: return VaelastraszTheCorruptGUID; - case DATA_BROODLORD_LASHLAYER: return BroodlordLashlayerGUID; - case DATA_FIRENAW: return FiremawGUID; - case DATA_EBONROC: return EbonrocGUID; - case DATA_FLAMEGOR: return FlamegorGUID; - case DATA_CHROMAGGUS: return ChromaggusGUID; - case DATA_LORD_VICTOR_NEFARIUS: return LordVictorNefariusGUID; - case DATA_NEFARIAN: return NefarianGUID; - } - - return ObjectGuid::Empty; - } - void SetData(uint32 type, uint32 data) override { if (type == DATA_EGG_EVENT) @@ -218,7 +190,7 @@ public: switch (data) { case IN_PROGRESS: - _events.ScheduleEvent(EVENT_RAZOR_SPAWN, 45*IN_MILLISECONDS); + _events.ScheduleEvent(EVENT_RAZOR_SPAWN, 45 * IN_MILLISECONDS); EggEvent = data; EggCount = 0; break; @@ -230,13 +202,13 @@ public: case SPECIAL: if (++EggCount == 15) { - if (Creature* razor = instance->GetCreature(RazorgoreTheUntamedGUID)) + if (Creature* razor = GetCreature(DATA_RAZORGORE_THE_UNTAMED)) { SetData(DATA_EGG_EVENT, DONE); razor->RemoveAurasDueToSpell(42013); // MindControl DoRemoveAurasDueToSpellOnPlayers(42013); } - _events.ScheduleEvent(EVENT_RAZOR_PHASE_TWO, IN_MILLISECONDS); + _events.ScheduleEvent(EVENT_RAZOR_PHASE_TWO, 1 * IN_MILLISECONDS); _events.CancelEvent(EVENT_RAZOR_SPAWN); } if (EggEvent == NOT_STARTED) @@ -249,8 +221,8 @@ public: void OnUnitDeath(Unit* unit) override { //! HACK, needed because of buggy CreatureAI after charm - if (unit->GetEntry() == NPC_RAZORGORE && GetBossState(BOSS_RAZORGORE) != DONE) - SetBossState(BOSS_RAZORGORE, DONE); + if (unit->GetEntry() == NPC_RAZORGORE && GetBossState(DATA_RAZORGORE_THE_UNTAMED) != DONE) + SetBossState(DATA_RAZORGORE_THE_UNTAMED, DONE); } void Update(uint32 diff) override @@ -268,15 +240,15 @@ public: for (uint8 i = urand(2, 5); i > 0 ; --i) if (Creature* summon = instance->SummonCreature(Entry[urand(0, 4)], SummonPosition[urand(0, 7)])) summon->SetInCombatWithZone(); - _events.ScheduleEvent(EVENT_RAZOR_SPAWN, urand(12, 17)*IN_MILLISECONDS); + _events.ScheduleEvent(EVENT_RAZOR_SPAWN, urand(12, 17) * IN_MILLISECONDS); break; case EVENT_RAZOR_PHASE_TWO: _events.CancelEvent(EVENT_RAZOR_SPAWN); - if (Creature* razor = instance->GetCreature(RazorgoreTheUntamedGUID)) + if (Creature* razor = GetCreature(DATA_RAZORGORE_THE_UNTAMED)) razor->AI()->DoAction(ACTION_PHASE_TWO); break; case EVENT_RESPAWN_NEFARIUS: - if (Creature* nefarius = instance->GetCreature(LordVictorNefariusGUID)) + if (Creature* nefarius = GetCreature(DATA_LORD_VICTOR_NEFARIUS)) { nefarius->SetPhaseMask(1, true); nefarius->setActive(true); @@ -291,34 +263,11 @@ public: protected: // Misc EventMap _events; + // Razorgore uint8 EggCount; uint32 EggEvent; - ObjectGuid RazorgoreTheUntamedGUID; - ObjectGuid RazorgoreDoorGUID; GuidList EggList; - - // Vaelastrasz the Corrupt - ObjectGuid VaelastraszTheCorruptGUID; - ObjectGuid VaelastraszDoorGUID; - - // Broodlord Lashlayer - ObjectGuid BroodlordLashlayerGUID; - ObjectGuid BroodlordDoorGUID; - - // 3 Dragons - ObjectGuid FiremawGUID; - ObjectGuid EbonrocGUID; - ObjectGuid FlamegorGUID; - ObjectGuid ChrommagusDoorGUID; - - // Chormaggus - ObjectGuid ChromaggusGUID; - ObjectGuid NefarianDoorGUID; - - // Nefarian - ObjectGuid LordVictorNefariusGUID; - ObjectGuid NefarianGUID; }; InstanceScript* GetInstanceScript(InstanceMap* map) const override diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_ragnaros.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_ragnaros.cpp index 9fd81b6a0f6..e2202a7e526 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_ragnaros.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_ragnaros.cpp @@ -86,6 +86,7 @@ class boss_ragnaros : public CreatureScript _introState = 0; me->SetReactState(REACT_PASSIVE); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + SetCombatMovement(false); } void Initialize() diff --git a/src/server/scripts/EasternKingdoms/Gnomeregan/gnomeregan.cpp b/src/server/scripts/EasternKingdoms/Gnomeregan/gnomeregan.cpp index 5ad5a3782ae..64513fece8b 100644 --- a/src/server/scripts/EasternKingdoms/Gnomeregan/gnomeregan.cpp +++ b/src/server/scripts/EasternKingdoms/Gnomeregan/gnomeregan.cpp @@ -365,7 +365,7 @@ public: } } - void UpdateEscortAI(const uint32 uiDiff) override + void UpdateEscortAI(uint32 uiDiff) override { if (uiPhase) { diff --git a/src/server/scripts/Kalimdor/OnyxiasLair/boss_onyxia.cpp b/src/server/scripts/Kalimdor/OnyxiasLair/boss_onyxia.cpp index 76fe8819716..65d6565ad9a 100644 --- a/src/server/scripts/Kalimdor/OnyxiasLair/boss_onyxia.cpp +++ b/src/server/scripts/Kalimdor/OnyxiasLair/boss_onyxia.cpp @@ -316,9 +316,20 @@ public: MovePoint = iTemp; } + bool CheckInRoom() override + { + if (me->GetDistance2d(me->GetHomePosition().GetPositionX(), me->GetHomePosition().GetPositionY()) > 95.0f) + { + EnterEvadeMode(); + return false; + } + + return true; + } + void UpdateAI(uint32 diff) override { - if (!UpdateVictim()) + if (!UpdateVictim() || !CheckInRoom()) return; //Common to PHASE_START && PHASE_END diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_cthun.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_cthun.cpp index 5b338dd8860..f967bd6a217 100644 --- a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_cthun.cpp +++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_cthun.cpp @@ -536,8 +536,7 @@ public: void SpawnEyeTentacle(float x, float y) { - Creature* Spawned; - Spawned = DoSpawnCreature(NPC_EYE_TENTACLE, x, y, 0, 0, TEMPSUMMON_CORPSE_DESPAWN, 500); + Creature* Spawned = DoSpawnCreature(NPC_EYE_TENTACLE, x, y, 0, 0, TEMPSUMMON_CORPSE_DESPAWN, 500); if (Spawned && Spawned->AI()) if (Unit* target = SelectRandomNotStomach()) Spawned->AI()->AttackStart(target); diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_twinemperors.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_twinemperors.cpp index 65ffb7fd696..b39ce0307a5 100644 --- a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_twinemperors.cpp +++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_twinemperors.cpp @@ -559,8 +559,7 @@ public: if (ArcaneBurst_Timer <= diff) { - Unit* mvic; - if ((mvic=SelectTarget(SELECT_TARGET_NEAREST, 0, NOMINAL_MELEE_RANGE, true)) != NULL) + if (Unit* mvic = SelectTarget(SELECT_TARGET_NEAREST, 0, NOMINAL_MELEE_RANGE, true)) { DoCast(mvic, SPELL_ARCANEBURST); ArcaneBurst_Timer = 5000; diff --git a/src/server/scripts/Kalimdor/zone_the_barrens.cpp b/src/server/scripts/Kalimdor/zone_the_barrens.cpp index a5e0a816fc9..d282856e1e5 100644 --- a/src/server/scripts/Kalimdor/zone_the_barrens.cpp +++ b/src/server/scripts/Kalimdor/zone_the_barrens.cpp @@ -607,7 +607,7 @@ public: summoned->AI()->AttackStart(me); } - void UpdateEscortAI(const uint32 Diff) override + void UpdateEscortAI(uint32 Diff) override { if (!UpdateVictim()) { diff --git a/src/server/scripts/Kalimdor/zone_winterspring.cpp b/src/server/scripts/Kalimdor/zone_winterspring.cpp index 5cb6e78b399..53eadd4a38b 100644 --- a/src/server/scripts/Kalimdor/zone_winterspring.cpp +++ b/src/server/scripts/Kalimdor/zone_winterspring.cpp @@ -568,7 +568,7 @@ public: } - void UpdateEscortAI(const uint32 diff) override + void UpdateEscortAI(uint32 diff) override { DialogueUpdate(diff); diff --git a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_general_zarithrian.cpp b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_general_zarithrian.cpp index eb6230fabfc..eb004505bab 100644 --- a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_general_zarithrian.cpp +++ b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_general_zarithrian.cpp @@ -263,7 +263,7 @@ class npc_onyx_flamecaller : public CreatureScript } } - void UpdateEscortAI(uint32 const diff) override + void UpdateEscortAI(uint32 diff) override { if (!UpdateVictim()) 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 758b4d25c43..f50a26eae23 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_faction_champions.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_faction_champions.cpp @@ -664,10 +664,9 @@ struct boss_faction_championsAI : public BossAI { std::list const& tList = me->getThreatManager().getThreatList(); std::list::const_iterator iter; - Unit* target; for (iter = tList.begin(); iter!=tList.end(); ++iter) { - target = ObjectAccessor::GetUnit(*me, (*iter)->getUnitGuid()); + Unit* target = ObjectAccessor::GetUnit(*me, (*iter)->getUnitGuid()); if (target && target->getPowerType() == POWER_MANA) return target; } @@ -679,10 +678,9 @@ struct boss_faction_championsAI : public BossAI std::list const& tList = me->getThreatManager().getThreatList(); std::list::const_iterator iter; uint32 count = 0; - Unit* target; for (iter = tList.begin(); iter != tList.end(); ++iter) { - target = ObjectAccessor::GetUnit(*me, (*iter)->getUnitGuid()); + Unit* target = ObjectAccessor::GetUnit(*me, (*iter)->getUnitGuid()); if (target && me->GetDistance2d(target) < distance) ++count; } diff --git a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_krickandick.cpp b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_krickandick.cpp index fd0fff44f66..c19af1cf79d 100644 --- a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_krickandick.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_krickandick.cpp @@ -137,9 +137,8 @@ class boss_ick : public CreatureScript struct boss_ickAI : public BossAI { - boss_ickAI(Creature* creature) : BossAI(creature, DATA_ICK), _vehicle(creature->GetVehicleKit()) + boss_ickAI(Creature* creature) : BossAI(creature, DATA_ICK) { - ASSERT(_vehicle); _tempThreat = 0; } @@ -177,7 +176,8 @@ class boss_ick : public CreatureScript { if (Creature* krick = GetKrick()) { - _vehicle->RemoveAllPassengers(); + if (Vehicle* _vehicle = me->GetVehicleKit()) + _vehicle->RemoveAllPassengers(); if (krick->AI()) krick->AI()->DoAction(ACTION_OUTRO); } @@ -268,7 +268,6 @@ class boss_ick : public CreatureScript } private: - Vehicle* _vehicle; float _tempThreat; }; diff --git a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_scourgelord_tyrannus.cpp b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_scourgelord_tyrannus.cpp index 3384b562860..3e56f9a1753 100644 --- a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_scourgelord_tyrannus.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_scourgelord_tyrannus.cpp @@ -290,9 +290,8 @@ class boss_rimefang : public CreatureScript struct boss_rimefangAI : public ScriptedAI { - boss_rimefangAI(Creature* creature) : ScriptedAI(creature), _vehicle(creature->GetVehicleKit()) + boss_rimefangAI(Creature* creature) : ScriptedAI(creature) { - ASSERT(_vehicle); Initialize(); } @@ -314,7 +313,8 @@ class boss_rimefang : public CreatureScript void JustReachedHome() override { - _vehicle->InstallAllAccessories(false); + if (Vehicle* _vehicle = me->GetVehicleKit()) + _vehicle->InstallAllAccessories(false); } void DoAction(int32 actionId) override @@ -376,7 +376,6 @@ class boss_rimefang : public CreatureScript } private: - Vehicle* _vehicle; ObjectGuid _hoarfrostTargetGUID; EventMap _events; uint8 _currentWaypoint; diff --git a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.cpp b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.cpp index 79f9a6e7c61..f3b70f069c4 100644 --- a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.cpp @@ -110,9 +110,8 @@ class npc_iceborn_protodrake : public CreatureScript struct npc_iceborn_protodrakeAI: public ScriptedAI { - npc_iceborn_protodrakeAI(Creature* creature) : ScriptedAI(creature), _vehicle(creature->GetVehicleKit()) + npc_iceborn_protodrakeAI(Creature* creature) : ScriptedAI(creature) { - ASSERT(_vehicle); Initialize(); } @@ -128,7 +127,8 @@ class npc_iceborn_protodrake : public CreatureScript void EnterCombat(Unit* /*who*/) override { - _vehicle->RemoveAllPassengers(); + if (Vehicle* _vehicle = me->GetVehicleKit()) + _vehicle->RemoveAllPassengers(); } void UpdateAI(uint32 diff) override @@ -148,7 +148,6 @@ class npc_iceborn_protodrake : public CreatureScript } private: - Vehicle* _vehicle; uint32 _frostBreathCooldown; }; diff --git a/src/server/scripts/Northrend/Gundrak/instance_gundrak.cpp b/src/server/scripts/Northrend/Gundrak/instance_gundrak.cpp index 5111247b84c..4438c4ab199 100644 --- a/src/server/scripts/Northrend/Gundrak/instance_gundrak.cpp +++ b/src/server/scripts/Northrend/Gundrak/instance_gundrak.cpp @@ -18,7 +18,6 @@ #include "InstanceScript.h" #include "Player.h" #include "ScriptMgr.h" -#include "WorldSession.h" #include "gundrak.h" #include "EventMap.h" @@ -191,7 +190,7 @@ class instance_gundrak : public InstanceMapScript bool CheckRequiredBosses(uint32 bossId, Player const* player = nullptr) const override { - if (player && player->GetSession()->HasPermission(rbac::RBAC_PERM_SKIP_CHECK_INSTANCE_REQUIRED_BOSSES)) + if (_SkipCheckRequiredBosses(player)) return true; switch (bossId) diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp index 5b13e3ee727..dc3591014cd 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp @@ -411,20 +411,21 @@ class StartMovementEvent : public BasicEvent { public: StartMovementEvent(Creature* summoner, Creature* owner) - : _summoner(summoner), _owner(owner) + : _summonerGuid(summoner->GetGUID()), _owner(owner) { } bool Execute(uint64 /*time*/, uint32 /*diff*/) { _owner->SetReactState(REACT_AGGRESSIVE); - if (Unit* target = _summoner->AI()->SelectTarget(SELECT_TARGET_RANDOM, 0, NonTankTargetSelector(_summoner))) - _owner->AI()->AttackStart(target); + if (Creature* _summoner = ObjectAccessor::GetCreature(*_owner, _summonerGuid)) + if (Unit* target = _summoner->AI()->SelectTarget(SELECT_TARGET_RANDOM, 0, NonTankTargetSelector(_summoner))) + _owner->AI()->AttackStart(target); return true; } private: - Creature* _summoner; + ObjectGuid _summonerGuid; Creature* _owner; }; diff --git a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp index 8c1befe72ff..ab1450a87ea 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp @@ -1140,7 +1140,7 @@ class npc_crok_scourgebane : public CreatureScript } } - void UpdateEscortAI(uint32 const diff) override + void UpdateEscortAI(uint32 diff) override { if (_wipeCheckTimer <= diff) _wipeCheckTimer = 0; diff --git a/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp index 3c66dfaf305..4d75d8edd17 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp @@ -17,7 +17,6 @@ #include "AccountMgr.h" #include "InstanceScript.h" -#include "Map.h" #include "ObjectMgr.h" #include "Player.h" #include "PoolMgr.h" @@ -26,7 +25,6 @@ #include "Transport.h" #include "TransportMgr.h" #include "WorldPacket.h" -#include "WorldSession.h" #include "icecrown_citadel.h" enum EventIds @@ -1111,7 +1109,7 @@ class instance_icecrown_citadel : public InstanceMapScript bool CheckRequiredBosses(uint32 bossId, Player const* player = nullptr) const override { - if (player && player->GetSession()->HasPermission(rbac::RBAC_PERM_SKIP_CHECK_INSTANCE_REQUIRED_BOSSES)) + if (_SkipCheckRequiredBosses(player)) return true; switch (bossId) diff --git a/src/server/scripts/Northrend/Nexus/Nexus/boss_keristrasza.cpp b/src/server/scripts/Northrend/Nexus/Nexus/boss_keristrasza.cpp index 2c9d88eac8a..495cf85b759 100644 --- a/src/server/scripts/Northrend/Nexus/Nexus/boss_keristrasza.cpp +++ b/src/server/scripts/Northrend/Nexus/Nexus/boss_keristrasza.cpp @@ -117,14 +117,12 @@ class boss_keristrasza : public CreatureScript ContainmentSphereGUIDs[1] = instance->GetGuidData(ORMOROKS_CONTAINMET_SPHERE); ContainmentSphereGUIDs[2] = instance->GetGuidData(TELESTRAS_CONTAINMET_SPHERE); - GameObject* ContainmentSpheres[DATA_CONTAINMENT_SPHERES]; - for (uint8 i = 0; i < DATA_CONTAINMENT_SPHERES; ++i) { - ContainmentSpheres[i] = ObjectAccessor::GetGameObject(*me, ContainmentSphereGUIDs[i]); - if (!ContainmentSpheres[i]) + GameObject* ContainmentSphere = ObjectAccessor::GetGameObject(*me, ContainmentSphereGUIDs[i]); + if (!ContainmentSphere) return false; - if (ContainmentSpheres[i]->GetGoState() != GO_STATE_ACTIVE) + if (ContainmentSphere->GetGoState() != GO_STATE_ACTIVE) return false; } if (remove_prison) diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfStone/halls_of_stone.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfStone/halls_of_stone.cpp index 6233c7e8953..86dbe6c16fb 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfStone/halls_of_stone.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfStone/halls_of_stone.cpp @@ -437,7 +437,7 @@ public: return 0; } - void UpdateEscortAI(const uint32 uiDiff) override + void UpdateEscortAI(uint32 uiDiff) override { if (uiPhaseTimer <= uiDiff) { diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfStone/instance_halls_of_stone.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfStone/instance_halls_of_stone.cpp index c67e31c4cc0..227b9c208cc 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfStone/instance_halls_of_stone.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfStone/instance_halls_of_stone.cpp @@ -18,7 +18,6 @@ #include "InstanceScript.h" #include "Player.h" #include "ScriptMgr.h" -#include "WorldSession.h" #include "halls_of_stone.h" DoorData const doorData[] = @@ -172,7 +171,7 @@ class instance_halls_of_stone : public InstanceMapScript bool CheckRequiredBosses(uint32 bossId, Player const* player = nullptr) const override { - if (player && player->GetSession()->HasPermission(rbac::RBAC_PERM_SKIP_CHECK_INSTANCE_REQUIRED_BOSSES)) + if (_SkipCheckRequiredBosses(player)) return true; switch (bossId) diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp index 1a8f278db3c..7b38bf90289 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_flame_leviathan.cpp @@ -224,7 +224,7 @@ class boss_flame_leviathan : public CreatureScript struct boss_flame_leviathanAI : public BossAI { - boss_flame_leviathanAI(Creature* creature) : BossAI(creature, BOSS_LEVIATHAN), vehicle(creature->GetVehicleKit()) + boss_flame_leviathanAI(Creature* creature) : BossAI(creature, BOSS_LEVIATHAN) { Initialize(); } @@ -244,7 +244,6 @@ class boss_flame_leviathan : public CreatureScript void InitializeAI() override { - ASSERT(vehicle); if (!me->isDead()) Reset(); @@ -256,7 +255,6 @@ class boss_flame_leviathan : public CreatureScript me->SetReactState(REACT_PASSIVE); } - Vehicle* vehicle; uint8 ActiveTowersCount; uint8 Shutdown; bool ActiveTowers; @@ -339,7 +337,7 @@ class boss_flame_leviathan : public CreatureScript void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override { if (spell->Id == SPELL_START_THE_ENGINE) - vehicle->InstallAllAccessories(false); + ASSERT_NOTNULL(me->GetVehicleKit())->InstallAllAccessories(false); if (spell->Id == SPELL_ELECTROSHOCK) me->InterruptSpell(CURRENT_CHANNELED_SPELL); @@ -584,16 +582,14 @@ class boss_flame_leviathan_seat : public CreatureScript struct boss_flame_leviathan_seatAI : public ScriptedAI { - boss_flame_leviathan_seatAI(Creature* creature) : ScriptedAI(creature), vehicle(creature->GetVehicleKit()) + boss_flame_leviathan_seatAI(Creature* creature) : ScriptedAI(creature) { - ASSERT(vehicle); me->SetReactState(REACT_PASSIVE); me->SetDisplayId(me->GetCreatureTemplate()->Modelid2); instance = creature->GetInstanceScript(); } InstanceScript* instance; - Vehicle* vehicle; void PassengerBoarded(Unit* who, int8 seatId, bool apply) override { @@ -628,7 +624,7 @@ class boss_flame_leviathan_seat : public CreatureScript if (apply) return; - if (Unit* device = vehicle->GetPassenger(SEAT_DEVICE)) + if (Unit* device = ASSERT_NOTNULL(me->GetVehicleKit())->GetPassenger(SEAT_DEVICE)) { device->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); device->SetUInt32Value(UNIT_FIELD_FLAGS, 0); // unselectable diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp index 05bdb568a2e..818bb0041a9 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp @@ -611,17 +611,16 @@ class boss_freya : public CreatureScript me->DespawnOrUnsummon(7500); me->CastSpell(me, SPELL_KNOCK_ON_WOOD_CREDIT, true); - Creature* Elder[3]; for (uint8 n = 0; n < 3; ++n) { - Elder[n] = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_BRIGHTLEAF + n)); - if (Elder[n] && Elder[n]->IsAlive()) + Creature* Elder = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_BRIGHTLEAF + n)); + if (Elder && Elder->IsAlive()) { - Elder[n]->RemoveAllAuras(); - Elder[n]->AttackStop(); - Elder[n]->CombatStop(true); - Elder[n]->DeleteThreatList(); - Elder[n]->GetAI()->DoAction(ACTION_ELDER_FREYA_KILLED); + Elder->RemoveAllAuras(); + Elder->AttackStop(); + Elder->CombatStop(true); + Elder->DeleteThreatList(); + Elder->GetAI()->DoAction(ACTION_ELDER_FREYA_KILLED); } } } diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_hodir.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_hodir.cpp index 098e7aa34be..4b60107a182 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_hodir.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_hodir.cpp @@ -396,11 +396,11 @@ class boss_hodir : public CreatureScript me->SetControlled(true, UNIT_STATE_STUNNED); me->CombatStop(true); + DoCastAOE(SPELL_KILL_CREDIT, true); /// need to be cast before changing boss faction + /// spell will target enemies only me->setFaction(35); me->DespawnOrUnsummon(10000); - DoCastAOE(SPELL_KILL_CREDIT); - _JustDied(); } } diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_ignis.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_ignis.cpp index d0b87f728c5..a04b53ac495 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_ignis.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_ignis.cpp @@ -117,10 +117,9 @@ class boss_ignis : public CreatureScript struct boss_ignis_AI : public BossAI { - boss_ignis_AI(Creature* creature) : BossAI(creature, BOSS_IGNIS), _vehicle(me->GetVehicleKit()) + boss_ignis_AI(Creature* creature) : BossAI(creature, BOSS_IGNIS) { Initialize(); - ASSERT(_vehicle); } void Initialize() @@ -133,7 +132,7 @@ class boss_ignis : public CreatureScript void Reset() override { _Reset(); - if (_vehicle) + if (Vehicle* _vehicle = me->GetVehicleKit()) _vehicle->RemoveAllPassengers(); instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEVEMENT_IGNIS_START_EVENT); @@ -284,7 +283,6 @@ class boss_ignis : public CreatureScript private: ObjectGuid _slagPotGUID; - Vehicle* _vehicle; time_t _firstConstructKill; bool _shattered; diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_kologarn.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_kologarn.cpp index eb9e310b840..92c7d18a065 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_kologarn.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_kologarn.cpp @@ -100,11 +100,9 @@ class boss_kologarn : public CreatureScript struct boss_kologarnAI : public BossAI { - boss_kologarnAI(Creature* creature) : BossAI(creature, BOSS_KOLOGARN), vehicle(creature->GetVehicleKit()), + boss_kologarnAI(Creature* creature) : BossAI(creature, BOSS_KOLOGARN), left(false), right(false) { - ASSERT(vehicle); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); @@ -113,7 +111,6 @@ class boss_kologarn : public CreatureScript Reset(); } - Vehicle* vehicle; bool left, right; ObjectGuid eyebeamTarget; @@ -128,9 +125,10 @@ class boss_kologarn : public CreatureScript events.ScheduleEvent(EVENT_FOCUSED_EYEBEAM, 21000); events.ScheduleEvent(EVENT_ENRAGE, 600000); - for (uint8 i = 0; i < 2; ++i) - if (Unit* arm = vehicle->GetPassenger(i)) - arm->ToCreature()->SetInCombatWithZone(); + if (Vehicle* vehicle = me->GetVehicleKit()) + for (uint8 i = 0; i < 2; ++i) + if (Unit* arm = vehicle->GetPassenger(i)) + arm->ToCreature()->SetInCombatWithZone(); _EnterCombat(); } @@ -283,7 +281,7 @@ class boss_kologarn : public CreatureScript case EVENT_RESPAWN_LEFT_ARM: case EVENT_RESPAWN_RIGHT_ARM: { - if (vehicle) + if (Vehicle* vehicle = me->GetVehicleKit()) { int8 seat = eventId == EVENT_RESPAWN_LEFT_ARM ? 0 : 1; uint32 entry = eventId == EVENT_RESPAWN_LEFT_ARM ? NPC_LEFT_ARM : NPC_RIGHT_ARM; diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp index d0e4b7be63b..59c28cd3a5a 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp @@ -401,20 +401,21 @@ class StartAttackEvent : public BasicEvent { public: StartAttackEvent(Creature* summoner, Creature* owner) - : _summoner(summoner), _owner(owner) + : _summonerGuid(summoner->GetGUID()), _owner(owner) { } bool Execute(uint64 /*time*/, uint32 /*diff*/) { _owner->SetReactState(REACT_AGGRESSIVE); - if (Unit* target = _summoner->AI()->SelectTarget(SELECT_TARGET_RANDOM, 0, 300.0f)) - _owner->AI()->AttackStart(target); + if (Creature* _summoner = ObjectAccessor::GetCreature(*_owner, _summonerGuid)) + if (Unit* target = _summoner->AI()->SelectTarget(SELECT_TARGET_RANDOM, 0, 300.0f)) + _owner->AI()->AttackStart(target); return true; } private: - Creature* _summoner; + ObjectGuid _summonerGuid; Creature* _owner; }; @@ -695,19 +696,22 @@ class boss_sara : public CreatureScript void DamageTaken(Unit* /*attacker*/, uint32& damage) override { - if (_events.IsInPhase(PHASE_ONE) && damage >= me->GetHealth()) + if (damage >= me->GetHealth()) { - damage = 0; + damage = me->GetHealth() - 1; - if (Creature* voice = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_VOICE_OF_YOGG_SARON))) - voice->AI()->DoAction(ACTION_PHASE_TRANSFORM); + if (_events.IsInPhase(PHASE_ONE)) + { + if (Creature* voice = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_VOICE_OF_YOGG_SARON))) + voice->AI()->DoAction(ACTION_PHASE_TRANSFORM); - Talk(SAY_SARA_TRANSFORM_1); - _events.SetPhase(PHASE_TRANSFORM); - _events.ScheduleEvent(EVENT_TRANSFORM_1, 4700, 0, PHASE_TRANSFORM); - _events.ScheduleEvent(EVENT_TRANSFORM_2, 9500, 0, PHASE_TRANSFORM); - _events.ScheduleEvent(EVENT_TRANSFORM_3, 14300, 0, PHASE_TRANSFORM); - _events.ScheduleEvent(EVENT_TRANSFORM_4, 14500, 0, PHASE_TRANSFORM); + Talk(SAY_SARA_TRANSFORM_1); + _events.SetPhase(PHASE_TRANSFORM); + _events.ScheduleEvent(EVENT_TRANSFORM_1, 4700, 0, PHASE_TRANSFORM); + _events.ScheduleEvent(EVENT_TRANSFORM_2, 9500, 0, PHASE_TRANSFORM); + _events.ScheduleEvent(EVENT_TRANSFORM_3, 14300, 0, PHASE_TRANSFORM); + _events.ScheduleEvent(EVENT_TRANSFORM_4, 14500, 0, PHASE_TRANSFORM); + } } } diff --git a/src/server/scripts/Northrend/VioletHold/boss_cyanigosa.cpp b/src/server/scripts/Northrend/VioletHold/boss_cyanigosa.cpp index dc923e534b0..d3868b8df9c 100644 --- a/src/server/scripts/Northrend/VioletHold/boss_cyanigosa.cpp +++ b/src/server/scripts/Northrend/VioletHold/boss_cyanigosa.cpp @@ -16,11 +16,13 @@ */ #include "ScriptMgr.h" +#include "SpellScript.h" #include "ScriptedCreature.h" #include "violet_hold.h" enum Spells { + SPELL_SUMMON_PLAYER = 21150, SPELL_ARCANE_VACUUM = 58694, SPELL_BLIZZARD = 58693, SPELL_MANA_DESTRUCTION = 59374, @@ -42,119 +44,91 @@ enum Yells class boss_cyanigosa : public CreatureScript { -public: - boss_cyanigosa() : CreatureScript("boss_cyanigosa") { } + public: + boss_cyanigosa() : CreatureScript("boss_cyanigosa") { } - struct boss_cyanigosaAI : public BossAI - { - boss_cyanigosaAI(Creature* creature) : BossAI(creature, DATA_CYANIGOSA) + struct boss_cyanigosaAI : public BossAI { - Initialize(); - } + boss_cyanigosaAI(Creature* creature) : BossAI(creature, DATA_CYANIGOSA) { } - void Initialize() - { - uiArcaneVacuumTimer = 10000; - uiBlizzardTimer = 15000; - uiManaDestructionTimer = 30000; - uiTailSweepTimer = 20000; - uiUncontrollableEnergyTimer = 25000; - } - - uint32 uiArcaneVacuumTimer; - uint32 uiBlizzardTimer; - uint32 uiManaDestructionTimer; - uint32 uiTailSweepTimer; - uint32 uiUncontrollableEnergyTimer; - - void Reset() override - { - Initialize(); - BossAI::Reset(); - } - - void EnterCombat(Unit* who) override - { - BossAI::EnterCombat(who); - Talk(SAY_AGGRO); - } - - void MoveInLineOfSight(Unit* /*who*/) override { } - - void UpdateAI(uint32 diff) override - { - if (instance->GetData(DATA_REMOVE_NPC) == 1) + void EnterCombat(Unit* who) override { - me->DespawnOrUnsummon(); - instance->SetData(DATA_REMOVE_NPC, 0); + BossAI::EnterCombat(who); + Talk(SAY_AGGRO); } - if (!UpdateVictim()) - return; - - if (uiArcaneVacuumTimer <= diff) + void KilledUnit(Unit* victim) override { - DoCastAOE(SPELL_ARCANE_VACUUM); - uiArcaneVacuumTimer = 10000; - } else uiArcaneVacuumTimer -= diff; + if (victim->GetTypeId() == TYPEID_PLAYER) + Talk(SAY_SLAY); + } - if (uiBlizzardTimer <= diff) + void JustDied(Unit* killer) override { - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(target, SPELL_BLIZZARD); - uiBlizzardTimer = 15000; - } else uiBlizzardTimer -= diff; + BossAI::JustDied(killer); + Talk(SAY_DEATH); + } - if (uiTailSweepTimer <= diff) - { - DoCastVictim(SPELL_TAIL_SWEEP); - uiTailSweepTimer = 20000; - } else uiTailSweepTimer -= diff; + void MoveInLineOfSight(Unit* /*who*/) override { } - if (uiUncontrollableEnergyTimer <= diff) + void UpdateAI(uint32 diff) override { - DoCastVictim(SPELL_UNCONTROLLABLE_ENERGY); - uiUncontrollableEnergyTimer = 25000; - } else uiUncontrollableEnergyTimer -= diff; + if (!UpdateVictim()) + return; - if (IsHeroic()) + scheduler.Update(diff, + std::bind(&BossAI::DoMeleeAttackIfReady, this)); + } + + void ScheduleTasks() override { - if (uiManaDestructionTimer <= diff) + scheduler.Schedule(Seconds(10), [this](TaskContext task) { - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(target, SPELL_MANA_DESTRUCTION); - uiManaDestructionTimer = 30000; - } else uiManaDestructionTimer -= diff; + DoCastAOE(SPELL_ARCANE_VACUUM); + task.Repeat(); + }); + + scheduler.Schedule(Seconds(15), [this](TaskContext task) + { + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 45.0f, true)) + DoCast(target, SPELL_BLIZZARD); + task.Repeat(); + }); + + scheduler.Schedule(Seconds(20), [this](TaskContext task) + { + DoCastVictim(SPELL_TAIL_SWEEP); + task.Repeat(); + }); + + scheduler.Schedule(Seconds(25), [this](TaskContext task) + { + DoCastVictim(SPELL_UNCONTROLLABLE_ENERGY); + task.Repeat(); + }); + + if (IsHeroic()) + { + scheduler.Schedule(Seconds(30), [this](TaskContext task) + { + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 50.0f, true)) + DoCast(target, SPELL_MANA_DESTRUCTION); + task.Repeat(); + }); + } } + }; - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* killer) override + CreatureAI* GetAI(Creature* creature) const override { - BossAI::JustDied(killer); - Talk(SAY_DEATH); + return GetVioletHoldAI(creature); } - - void KilledUnit(Unit* victim) override - { - if (victim->GetTypeId() == TYPEID_PLAYER) - Talk(SAY_SLAY); - } - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI(creature); - } }; class achievement_defenseless : public AchievementCriteriaScript { public: - achievement_defenseless() : AchievementCriteriaScript("achievement_defenseless") - { - } + achievement_defenseless() : AchievementCriteriaScript("achievement_defenseless") { } bool OnCheck(Player* /*player*/, Unit* target) override { @@ -165,10 +139,40 @@ class achievement_defenseless : public AchievementCriteriaScript if (!instance) return false; - if (!instance->GetData(DATA_DEFENSELESS)) - return false; + return instance->GetData(DATA_DEFENSELESS) != 0; + } +}; - return true; +class spell_cyanigosa_arcane_vacuum : public SpellScriptLoader +{ + public: + spell_cyanigosa_arcane_vacuum() : SpellScriptLoader("spell_cyanigosa_arcane_vacuum") { } + + class spell_cyanigosa_arcane_vacuum_SpellScript : public SpellScript + { + PrepareSpellScript(spell_cyanigosa_arcane_vacuum_SpellScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_SUMMON_PLAYER)) + return false; + return true; + } + + void HandleScript(SpellEffIndex /*effIndex*/) + { + GetCaster()->CastSpell(GetHitUnit(), SPELL_SUMMON_PLAYER, true); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_cyanigosa_arcane_vacuum_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_cyanigosa_arcane_vacuum_SpellScript(); } }; @@ -176,4 +180,5 @@ void AddSC_boss_cyanigosa() { new boss_cyanigosa(); new achievement_defenseless(); + new spell_cyanigosa_arcane_vacuum(); } diff --git a/src/server/scripts/Northrend/VioletHold/boss_erekem.cpp b/src/server/scripts/Northrend/VioletHold/boss_erekem.cpp index 8ead8ab559e..cc27bf52118 100644 --- a/src/server/scripts/Northrend/VioletHold/boss_erekem.cpp +++ b/src/server/scripts/Northrend/VioletHold/boss_erekem.cpp @@ -41,269 +41,210 @@ enum Yells SAY_BOTH_ADDS_KILLED = 5 }; -enum ErekemEvents -{ - EVENT_EARTH_SHIELD = 1, - EVENT_CHAIN_HEAL, - EVENT_BLOODLUST, - EVENT_LIGHTNING_BOLT, - EVENT_EARTH_SHOCK, - EVENT_WINDFURY, - EVENT_STORMSTRIKE -}; - class boss_erekem : public CreatureScript { -public: - boss_erekem() : CreatureScript("boss_erekem") { } + public: + boss_erekem() : CreatureScript("boss_erekem") { } - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI(creature); - } - - struct boss_erekemAI : public ScriptedAI - { - boss_erekemAI(Creature* creature) : ScriptedAI(creature) + struct boss_erekemAI : public BossAI { - Initialize(); - instance = creature->GetInstanceScript(); - } - - void Initialize() - { - phase = 0; - breakBondsCd = 0; - } - - void Reset() override - { - Initialize(); - - if (instance->GetData(DATA_WAVE_COUNT) == 6) - instance->SetBossState(DATA_1ST_BOSS_EVENT, NOT_STARTED); - else if (instance->GetData(DATA_WAVE_COUNT) == 12) - instance->SetBossState(DATA_2ND_BOSS_EVENT, NOT_STARTED); - - if (instance->GetData(DATA_MAIN_EVENT_PHASE) == IN_PROGRESS) + boss_erekemAI(Creature* creature) : BossAI(creature, DATA_EREKEM) { - if (Creature* pGuard1 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EREKEM_GUARD_1))) - pGuard1->DespawnOrUnsummon(); - if (Creature* pGuard2 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EREKEM_GUARD_2))) - pGuard2->DespawnOrUnsummon(); - } - else - { - if (Creature* pGuard1 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EREKEM_GUARD_1))) - { - if (!pGuard1->IsAlive()) - pGuard1->Respawn(); - } - if (Creature* pGuard2 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EREKEM_GUARD_2))) - { - if (!pGuard2->IsAlive()) - pGuard2->Respawn(); - } + Initialize(); } - events.Reset(); - } - - void JustReachedHome() override - { - if (Creature* pGuard1 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EREKEM_GUARD_1))) - pGuard1->Respawn(); - - if (Creature* pGuard2 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EREKEM_GUARD_2))) - pGuard2->Respawn(); - } - - void AttackStart(Unit* who) override - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC) || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - if (me->Attack(who, true)) + void Initialize() { - me->AddThreat(who, 0.0f); - me->SetInCombatWith(who); - who->SetInCombatWith(me); - DoStartMovement(who); - - if (Creature* pGuard1 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EREKEM_GUARD_1))) - { - pGuard1->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); - if (!pGuard1->GetVictim() && pGuard1->AI()) - pGuard1->AI()->AttackStart(who); - } - if (Creature* pGuard2 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EREKEM_GUARD_2))) - { - pGuard2->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); - if (!pGuard2->GetVictim() && pGuard2->AI()) - pGuard2->AI()->AttackStart(who); - } + _phase = 0; } - } - void EnterCombat(Unit* /*who*/) override - { - Talk(SAY_AGGRO); - DoCast(me, SPELL_EARTH_SHIELD); + void Reset() override + { + Initialize(); + BossAI::Reset(); + me->SetCanDualWield(false); + } - if (GameObject* door = instance->GetGameObject(DATA_EREKEM_CELL)) - if (door->GetGoState() == GO_STATE_READY) + void EnterCombat(Unit* who) override + { + BossAI::EnterCombat(who); + Talk(SAY_AGGRO); + DoCast(me, SPELL_EARTH_SHIELD); + } + + void MovementInform(uint32 type, uint32 pointId) override + { + if (type == EFFECT_MOTION_TYPE && pointId == POINT_INTRO) + me->SetFacingTo(4.921828f); + } + + void JustReachedHome() override + { + BossAI::JustReachedHome(); + instance->SetData(DATA_HANDLE_CELLS, DATA_EREKEM); + } + + void KilledUnit(Unit* victim) override + { + if (victim->GetTypeId() == TYPEID_PLAYER) + Talk(SAY_SLAY); + } + + void JustDied(Unit* killer) override + { + BossAI::JustDied(killer); + Talk(SAY_DEATH); + } + + bool CheckGuardAuras(Creature* guard) const + { + static uint32 const MechanicImmunityList = + (1 << MECHANIC_SNARE) + | (1 << MECHANIC_ROOT) + | (1 << MECHANIC_FEAR) + | (1 << MECHANIC_STUN) + | (1 << MECHANIC_SLEEP) + | (1 << MECHANIC_CHARM) + | (1 << MECHANIC_SAPPED) + | (1 << MECHANIC_HORROR) + | (1 << MECHANIC_POLYMORPH) + | (1 << MECHANIC_DISORIENTED) + | (1 << MECHANIC_FREEZE) + | (1 << MECHANIC_TURN); + + static std::list const AuraImmunityList = { - EnterEvadeMode(); + SPELL_AURA_MOD_STUN, + SPELL_AURA_MOD_DECREASE_SPEED, + SPELL_AURA_MOD_ROOT, + SPELL_AURA_MOD_CONFUSE, + SPELL_AURA_MOD_FEAR + }; + + if (guard->HasAuraWithMechanic(MechanicImmunityList)) + return true; + + for (AuraType type : AuraImmunityList) + if (guard->HasAuraType(type)) + return true; + + return false; + } + + bool CheckGuardAlive() const + { + for (uint32 i = DATA_EREKEM_GUARD_1; i <= DATA_EREKEM_GUARD_2; ++i) + { + if (Creature* guard = ObjectAccessor::GetCreature(*me, instance->GetGuidData(i))) + if (guard->IsAlive()) + return true; + } + + return false; + } + + Unit* GetChainHealTarget() const + { + if (HealthBelowPct(85)) + return me; + + for (uint32 i = DATA_EREKEM_GUARD_1; i <= DATA_EREKEM_GUARD_2; ++i) + { + if (Creature* guard = ObjectAccessor::GetCreature(*me, instance->GetGuidData(i))) + if (guard->IsAlive() && !guard->HealthAbovePct(75)) + return guard; + } + + return nullptr; + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) return; - } - if (instance->GetData(DATA_WAVE_COUNT) == 6) - instance->SetBossState(DATA_1ST_BOSS_EVENT, IN_PROGRESS); - else if (instance->GetData(DATA_WAVE_COUNT) == 12) - instance->SetBossState(DATA_2ND_BOSS_EVENT, IN_PROGRESS); - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_IMMUNE_TO_NPC); - - events.ScheduleEvent(EVENT_EARTH_SHIELD, 20000); - events.ScheduleEvent(EVENT_BLOODLUST, 15000); - events.ScheduleEvent(EVENT_CHAIN_HEAL, 10000); - events.ScheduleEvent(EVENT_LIGHTNING_BOLT, 2000); - } - - void JustDied(Unit* /*killer*/) override - { - Talk(SAY_DEATH); - - if (instance->GetData(DATA_WAVE_COUNT) == 6) - { - instance->SetBossState(DATA_1ST_BOSS_EVENT, DONE); - instance->SetData(DATA_WAVE_COUNT, 7); - } - else if (instance->GetData(DATA_WAVE_COUNT) == 12) - { - instance->SetBossState(DATA_2ND_BOSS_EVENT, DONE); - instance->SetData(DATA_WAVE_COUNT, 13); - } - } - - void KilledUnit(Unit* victim) override - { - if (victim->GetTypeId() == TYPEID_PLAYER) - Talk(SAY_SLAY); - } - - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim()) - return; - - if (phase == 0) - if (Creature* pGuard1 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EREKEM_GUARD_1))) + if (_phase == 0 && !CheckGuardAlive()) { - if (Creature* pGuard2 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EREKEM_GUARD_2))) - { - if (!pGuard1->IsAlive() && !pGuard2->IsAlive()) - { - phase = 1; - DoCastVictim(SPELL_STORMSTRIKE); - DoCast(SPELL_WINDFURY); - events.Reset(); - events.ScheduleEvent(EVENT_EARTH_SHOCK, urand(2000, 8000)); - events.ScheduleEvent(EVENT_WINDFURY, urand(1500, 2000)); - events.ScheduleEvent(EVENT_STORMSTRIKE, urand(1500, 2000)); - } - } + _phase = 1; + me->SetCanDualWield(true); + DoCast(me, SPELL_WINDFURY, true); } - events.Update(diff); - - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - - if (breakBondsCd <= 0) - { - if (Creature* pGuard1 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EREKEM_GUARD_1))) + scheduler.Update(diff, [this] { - if (Creature* pGuard2 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EREKEM_GUARD_2))) - { - if (pGuard1->IsAlive()) - { - if (pGuard1->HasAuraType(SPELL_AURA_MOD_STUN) || pGuard1->HasAuraType(SPELL_AURA_MOD_ROOT) - || pGuard1->HasAuraType(SPELL_AURA_MOD_CONFUSE) || pGuard1->HasAuraType(SPELL_AURA_MOD_PACIFY) - || pGuard1->HasAuraType(SPELL_AURA_MOD_DECREASE_SPEED)) - { - DoCast(SPELL_BREAK_BONDS); - breakBondsCd = 10000; - return; - } - } - if (pGuard2->IsAlive()) - { - if (pGuard2->HasAuraType(SPELL_AURA_MOD_STUN) || pGuard2->HasAuraType(SPELL_AURA_MOD_ROOT) - || pGuard2->HasAuraType(SPELL_AURA_MOD_CONFUSE) || pGuard2->HasAuraType(SPELL_AURA_MOD_PACIFY) - || pGuard2->HasAuraType(SPELL_AURA_MOD_DECREASE_SPEED)) - { - DoCast(SPELL_BREAK_BONDS); - breakBondsCd = 10000; - return; - } - } - } - } + if (_phase == 1) + DoSpellAttackIfReady(SPELL_STORMSTRIKE); + else + DoMeleeAttackIfReady(); + }); } - else - breakBondsCd -= diff; - switch (events.ExecuteEvent()) + void ScheduleTasks() override { - case EVENT_EARTH_SHIELD: + scheduler.Schedule(Seconds(20), [this](TaskContext task) + { if (Unit* ally = DoSelectLowestHpFriendly(30.0f)) DoCast(ally, SPELL_EARTH_SHIELD); - events.ScheduleEvent(EVENT_EARTH_SHIELD, 20000); - break; - case EVENT_BLOODLUST: + + task.Repeat(Seconds(20)); + }); + + scheduler.Schedule(Seconds(2), [this](TaskContext task) + { DoCast(SPELL_BLOODLUST); - events.ScheduleEvent(EVENT_BLOODLUST, urand(35000, 45000)); - break; - case EVENT_LIGHTNING_BOLT: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) + task.Repeat(Seconds(35), Seconds(45)); + }); + + scheduler.Schedule(Seconds(2), [this](TaskContext task) + { + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 40.0f)) DoCast(target, SPELL_LIGHTNING_BOLT); - events.ScheduleEvent(EVENT_LIGHTNING_BOLT, 2500); - break; - case EVENT_CHAIN_HEAL: + + task.Repeat(Milliseconds(2500)); + }); + + scheduler.Schedule(Seconds(10), [this](TaskContext task) + { if (Unit* ally = DoSelectLowestHpFriendly(40.0f)) DoCast(ally, SPELL_CHAIN_HEAL); - { - Creature* pGuard1 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EREKEM_GUARD_1)); - Creature* pGuard2 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EREKEM_GUARD_2)); - events.ScheduleEvent(EVENT_CHAIN_HEAL, ((pGuard1 && !pGuard1->IsAlive()) || (pGuard2 && !pGuard2->IsAlive()) ? 3000 : 8000 + rand() % 3000)); - } - break; - case EVENT_EARTH_SHOCK: + + if (!CheckGuardAlive()) + task.Repeat(Seconds(3)); + else + task.Repeat(Seconds(8), Seconds(11)); + }); + + scheduler.Schedule(Seconds(2), Seconds(8), [this](TaskContext task) + { DoCastVictim(SPELL_EARTH_SHOCK); - events.ScheduleEvent(EVENT_EARTH_SHOCK, urand(8000, 13000)); - break; - case EVENT_WINDFURY: - DoCast(SPELL_WINDFURY); - events.ScheduleEvent(EVENT_WINDFURY, urand(1500, 2000)); - break; - case EVENT_STORMSTRIKE: - DoCastVictim(SPELL_STORMSTRIKE); - events.ScheduleEvent(EVENT_STORMSTRIKE, urand(1500, 2000)); - break; - default: - break; + task.Repeat(Seconds(8), Seconds(13)); + }); + + scheduler.Schedule(Seconds(0), [this](TaskContext task) + { + for (uint32 i = DATA_EREKEM_GUARD_1; i <= DATA_EREKEM_GUARD_2; ++i) + { + Creature* guard = ObjectAccessor::GetCreature(*me, instance->GetGuidData(i)); + + if (guard && guard->IsAlive() && CheckGuardAuras(guard)) + { + DoCastAOE(SPELL_BREAK_BONDS); + task.Repeat(Seconds(10)); + return; + } + } + task.Repeat(Milliseconds(500)); + }); } - DoMeleeAttackIfReady(); - } + private: + uint8 _phase; + }; - private: - EventMap events; - InstanceScript* instance; - uint8 phase; - int32 breakBondsCd; - }; + CreatureAI* GetAI(Creature* creature) const override + { + return GetVioletHoldAI(creature); + } }; enum GuardSpells @@ -315,85 +256,61 @@ enum GuardSpells class npc_erekem_guard : public CreatureScript { -public: - npc_erekem_guard() : CreatureScript("npc_erekem_guard") { } + public: + npc_erekem_guard() : CreatureScript("npc_erekem_guard") { } - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI(creature); - } - - struct npc_erekem_guardAI : public ScriptedAI - { - npc_erekem_guardAI(Creature* creature) : ScriptedAI(creature) + struct npc_erekem_guardAI : public ScriptedAI { - Initialize(); - instance = creature->GetInstanceScript(); - } + npc_erekem_guardAI(Creature* creature) : ScriptedAI(creature) { } - void Initialize() - { - uiStrikeTimer = urand(4000, 8000); - uiHowlingScreechTimer = urand(8000, 13000); - uiGushingWoundTimer = urand(1000, 3000); - } - - uint32 uiGushingWoundTimer; - uint32 uiHowlingScreechTimer; - uint32 uiStrikeTimer; - - InstanceScript* instance; - - void Reset() override - { - Initialize(); - - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_NPC); - } - - void AttackStart(Unit* who) override - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC) || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - if (me->Attack(who, true)) + void Reset() override { - me->AddThreat(who, 0.0f); - me->SetInCombatWith(who); - who->SetInCombatWith(me); - DoStartMovement(who); + scheduler.CancelAll(); } - } - void MoveInLineOfSight(Unit* /*who*/) override { } + void EnterCombat(Unit* /*who*/) override + { + DoZoneInCombat(); + } - void UpdateAI(uint32 diff) override + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + scheduler.Update(diff, + std::bind(&ScriptedAI::DoMeleeAttackIfReady, this)); + } + + void ScheduledTasks() + { + scheduler.Schedule(Seconds(4), Seconds(8), [this](TaskContext task) + { + DoCastVictim(SPELL_STRIKE); + task.Repeat(Seconds(4), Seconds(8)); + }); + + scheduler.Schedule(Seconds(8), Seconds(13), [this](TaskContext task) + { + DoCastAOE(SPELL_HOWLING_SCREECH); + task.Repeat(Seconds(8), Seconds(13)); + }); + + scheduler.Schedule(Seconds(1), Seconds(3), [this](TaskContext task) + { + DoCastVictim(SPELL_GUSHING_WOUND); + task.Repeat(Seconds(7), Seconds(12)); + }); + } + + private: + TaskScheduler scheduler; + }; + + CreatureAI* GetAI(Creature* creature) const override { - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - - if (uiStrikeTimer <= diff) - { - DoCastVictim(SPELL_STRIKE); - uiStrikeTimer = urand(4000, 8000); - } else uiStrikeTimer -= diff; - - if (uiHowlingScreechTimer <= diff) - { - DoCastVictim(SPELL_HOWLING_SCREECH); - uiHowlingScreechTimer = urand(8000, 13000); - } else uiHowlingScreechTimer -= diff; - - if (uiGushingWoundTimer <= diff) - { - DoCastVictim(SPELL_GUSHING_WOUND); - uiGushingWoundTimer = urand(7000, 12000); - } else uiGushingWoundTimer -= diff; + return GetVioletHoldAI(creature); } - }; }; void AddSC_boss_erekem() diff --git a/src/server/scripts/Northrend/VioletHold/boss_ichoron.cpp b/src/server/scripts/Northrend/VioletHold/boss_ichoron.cpp index caf1392ea38..3c29cc1123c 100644 --- a/src/server/scripts/Northrend/VioletHold/boss_ichoron.cpp +++ b/src/server/scripts/Northrend/VioletHold/boss_ichoron.cpp @@ -17,26 +17,32 @@ #include "ScriptMgr.h" #include "ScriptedCreature.h" +#include "SpellAuraEffects.h" +#include "SpellScript.h" #include "violet_hold.h" enum Spells { - SPELL_DRAINED = 59820, - SPELL_FRENZY = 54312, - SPELL_PROTECTIVE_BUBBLE = 54306, SPELL_WATER_BLAST = 54237, SPELL_WATER_BOLT_VOLLEY = 54241, - SPELL_SPLASH = 59516, + SPELL_SPLATTER = 54259, + SPELL_PROTECTIVE_BUBBLE = 54306, + SPELL_FRENZY = 54312, SPELL_BURST = 54379, - SPELL_WATER_GLOBULE = 54268, - SPELL_MERGE = 54269, - SPELL_WATER_GLOBULE_VISUAL = 54260 -}; + SPELL_DRAINED = 59820, + SPELL_THREAT_PROC = 61732, + SPELL_SHRINK = 54297, -enum IchoronCreatures -{ - NPC_ICHOR_GLOBULE = 29321, - NPC_ICHORON_SUMMON_TARGET = 29326 + SPELL_WATER_GLOBULE_SUMMON_1 = 54258, + SPELL_WATER_GLOBULE_SUMMON_2 = 54264, + SPELL_WATER_GLOBULE_SUMMON_3 = 54265, + SPELL_WATER_GLOBULE_SUMMON_4 = 54266, + SPELL_WATER_GLOBULE_SUMMON_5 = 54267, + SPELL_WATER_GLOBULE_TRANSFORM = 54268, + SPELL_WATER_GLOBULE_VISUAL = 54260, + + SPELL_MERGE = 54269, + SPELL_SPLASH = 59516 }; enum Yells @@ -47,483 +53,412 @@ enum Yells SAY_SPAWN = 3, SAY_ENRAGE = 4, SAY_SHATTER = 5, - SAY_BUBBLE = 6 + SAY_BUBBLE = 6, + EMOTE_SHATTER = 7 }; enum Actions { - ACTION_WATER_ELEMENT_HIT = 1 -}; - -enum IchoronEvents -{ - EVENT_WATER_BLAST = 1, - EVENT_WATER_BOLT_VOLLEY -}; - -enum GlobuleEvents -{ - EVENT_GLOBULE_MOVE = 1 + ACTION_WATER_GLOBULE_HIT = 1, + ACTION_PROTECTIVE_BUBBLE_SHATTERED = 2, + ACTION_DRAINED = 3 }; enum Misc { - DATA_GLOBULE_PATH = 0, DATA_DEHYDRATION = 1 }; - -#define MAX_GLOBULE_PATHS 10 - -Position const globulePaths[MAX_GLOBULE_PATHS] = -{ - // first target - { 1861.357f, 804.039f, 44.008f, 6.268f }, - { 1869.375f, 803.976f, 38.781f, 0.009f }, - // second target - { 1888.063f, 763.488f, 47.667f, 1.744f }, - { 1882.865f, 776.385f, 38.824f, 1.882f }, - // third target - { 1935.140f, 817.752f, 52.181f, 1.885f }, - { 1916.642f, 826.337f, 39.139f, 2.851f }, - // fourth target - { 1930.257f, 833.053f, 46.906f, 4.579f }, - { 1916.642f, 826.337f, 39.139f, 2.851f }, - // fifth target - { 1878.248f, 841.883f, 43.334f, 4.717f }, - { 1879.438f, 834.443f, 38.699f, 4.831f } -}; - class boss_ichoron : public CreatureScript { -public: - boss_ichoron() : CreatureScript("boss_ichoron") { } + public: + boss_ichoron() : CreatureScript("boss_ichoron") { } - struct boss_ichoronAI : public ScriptedAI - { - boss_ichoronAI(Creature* creature) : ScriptedAI(creature), m_waterElements(creature) + struct boss_ichoronAI : public BossAI { - Initialize(); - instance = creature->GetInstanceScript(); - } + boss_ichoronAI(Creature* creature) : BossAI(creature, DATA_ICHORON) + { + Initialize(); - void Initialize() - { - bIsExploded = false; - bIsFrenzy = false; - bIsDrained = false; - dehydration = true; - drainedTimer = 50; - burstTimer = 15000; - } + /// for some reason ichoron can't walk back to it's water basin on evade + me->AddUnitState(UNIT_STATE_IGNORE_PATHFINDING); + } - void Reset() override - { - Initialize(); + void Initialize() + { + _isFrenzy = false; + _dehydration = true; + } - events.Reset(); - me->SetVisible(true); - DespawnWaterElements(); + void Reset() override + { + Initialize(); + BossAI::Reset(); - if (instance->GetData(DATA_WAVE_COUNT) == 6) - instance->SetBossState(DATA_1ST_BOSS_EVENT, NOT_STARTED); - else if (instance->GetData(DATA_WAVE_COUNT) == 12) - instance->SetBossState(DATA_2ND_BOSS_EVENT, NOT_STARTED); - } + DoCast(me, SPELL_THREAT_PROC, true); + } - void EnterCombat(Unit* /*who*/) override - { - Talk(SAY_AGGRO); + void EnterCombat(Unit* who) override + { + BossAI::EnterCombat(who); + Talk(SAY_AGGRO); + } - DoCast(me, SPELL_PROTECTIVE_BUBBLE); + void JustReachedHome() override + { + BossAI::JustReachedHome(); + instance->SetData(DATA_HANDLE_CELLS, DATA_ICHORON); + } - if (GameObject* door = instance->GetGameObject(DATA_ICHORON_CELL)) - if (door->GetGoState() == GO_STATE_READY) + void DoAction(int32 actionId) override + { + switch (actionId) { - EnterEvadeMode(); - return; - } + case ACTION_WATER_GLOBULE_HIT: + if (!me->IsAlive()) + break; - if (instance->GetData(DATA_WAVE_COUNT) == 6) - instance->SetBossState(DATA_1ST_BOSS_EVENT, IN_PROGRESS); - else if (instance->GetData(DATA_WAVE_COUNT) == 12) - instance->SetBossState(DATA_2ND_BOSS_EVENT, IN_PROGRESS); - - events.ScheduleEvent(EVENT_WATER_BOLT_VOLLEY, urand(10000, 15000)); - events.ScheduleEvent(EVENT_WATER_BLAST, urand(6000, 9000)); - } - - void AttackStart(Unit* who) override - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC) || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - if (me->Attack(who, true)) - { - me->AddThreat(who, 0.0f); - me->SetInCombatWith(who); - who->SetInCombatWith(me); - DoStartMovement(who); - } - } - - void DoAction(int32 param) override - { - if (!me->IsAlive()) - return; - - switch (param) - { - case ACTION_WATER_ELEMENT_HIT: - { - if (bIsExploded) - DoExplodeCompleted(); - - me->SetHealth(me->GetHealth() + me->CountPctFromMaxHealth(3)); - dehydration = false; - } - break; - } - } - - void DespawnWaterElements() - { - m_waterElements.DespawnAll(); - } - - // call when explode shall stop. - // either when "hit" by a bubble, or when there is no bubble left. - void DoExplodeCompleted() - { - bIsExploded = false; - bIsDrained = false; - - if (!HealthBelowPct(25)) - { - Talk(SAY_BUBBLE); - DoCast(me, SPELL_PROTECTIVE_BUBBLE, true); - } - - me->SetVisible(true); - me->GetMotionMaster()->MoveChase(me->GetVictim()); - } - - uint32 GetData(uint32 type) const override - { - if (type == DATA_DEHYDRATION) - return dehydration ? 1 : 0; - - return 0; - } - - void MoveInLineOfSight(Unit* who) override - { - if (!who->ToCreature()) - return; - - if (who->GetEntry() != NPC_ICHOR_GLOBULE) - return; - - if (!me->IsWithinDist(who, 4.0f, false)) - return; - - if (who->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE)) - return; - - who->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - who->CastSpell(who, SPELL_MERGE); - DoAction(ACTION_WATER_ELEMENT_HIT); - who->ToCreature()->DespawnOrUnsummon(1000); - } - - void JustDied(Unit* /*killer*/) override - { - Talk(SAY_DEATH); - - if (bIsExploded) - { - bIsExploded = false; - me->SetVisible(true); - } - - DespawnWaterElements(); - - if (instance->GetData(DATA_WAVE_COUNT) == 6) - { - instance->SetBossState(DATA_1ST_BOSS_EVENT, DONE); - instance->SetData(DATA_WAVE_COUNT, 7); - } - else if (instance->GetData(DATA_WAVE_COUNT) == 12) - { - instance->SetBossState(DATA_2ND_BOSS_EVENT, DONE); - instance->SetData(DATA_WAVE_COUNT, 13); - } - } - - void JustSummoned(Creature* summoned) override - { - summoned->SetSpeed(MOVE_RUN, 0.3f); - m_waterElements.Summon(summoned); - - instance->SetGuidData(DATA_ADD_TRASH_MOB, summoned->GetGUID()); - } - - void SummonedCreatureDespawn(Creature* summoned) override - { - m_waterElements.Despawn(summoned); - - if (m_waterElements.empty() && bIsExploded) - { - me->RemoveAllAuras(); - DoExplodeCompleted(); - } - - instance->SetGuidData(DATA_DEL_TRASH_MOB, summoned->GetGUID()); - } - - void KilledUnit(Unit* victim) override - { - if (victim->GetTypeId() == TYPEID_PLAYER) - Talk(SAY_SLAY); - } - - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim()) - return; - - if (!bIsFrenzy && HealthBelowPct(25) && !bIsExploded) - { - Talk(SAY_ENRAGE); - DoCast(me, SPELL_FRENZY, true); - bIsFrenzy = true; - } - - if (!bIsFrenzy) - { - if (!bIsExploded) - { - if (!me->HasAura(SPELL_PROTECTIVE_BUBBLE)) + me->ModifyHealth(int32(me->CountPctFromMaxHealth(3))); + _dehydration = false; + break; + case ACTION_PROTECTIVE_BUBBLE_SHATTERED: { - bIsExploded = true; Talk(SAY_SHATTER); - DoCast(SPELL_BURST); - me->RemoveAllAuras(); - burstTimer = 15000; + Talk(EMOTE_SHATTER); - std::list summonTargets; - GetCreatureListWithEntryInGrid(summonTargets, me, NPC_ICHORON_SUMMON_TARGET, 200.0f); - std::list::iterator itr = summonTargets.begin(); + DoCastAOE(SPELL_SPLATTER, true); + DoCastAOE(SPELL_BURST, true); + DoCast(me, SPELL_DRAINED, true); - for (uint8 i = 0; i < MAX_GLOBULE_PATHS; i++) - { - std::advance(itr, urand(0, summonTargets.size() - 1)); // I take a random minion in the list - Position targetPos = (*itr)->GetRandomNearPosition(10.0f); - itr = summonTargets.begin(); - TempSummon* globule = me->SummonCreature(NPC_ICHOR_GLOBULE, targetPos, TEMPSUMMON_CORPSE_DESPAWN); - DoCast(globule, SPELL_WATER_GLOBULE_VISUAL); - - float minDistance = 1000.0f; - uint8 nextPath = 0; - // I move the globules to next position. the 10 positions are in couples, defined in globulePaths, so i have to increase by 2. - for (uint8 gpath = 0; gpath < MAX_GLOBULE_PATHS; gpath += 2) - { - if (globule->GetDistance(globulePaths[gpath]) < minDistance) - { - minDistance = globule->GetDistance(globulePaths[gpath]); - nextPath = gpath; - } - } - - globule->GetAI()->SetData(DATA_GLOBULE_PATH, nextPath); - } - return; - } - - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - - events.Update(diff); - - switch (events.ExecuteEvent()) - { - case EVENT_WATER_BLAST: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) - DoCast(target, SPELL_WATER_BLAST); - events.ScheduleEvent(EVENT_WATER_BLAST, urand(6000, 9000)); - break; - case EVENT_WATER_BOLT_VOLLEY: - DoCast(SPELL_WATER_BOLT_VOLLEY); - events.ScheduleEvent(EVENT_WATER_BOLT_VOLLEY, urand(10000, 15000)); - break; - } - - DoMeleeAttackIfReady(); - } - else if (!bIsDrained) - { - if (drainedTimer <= 0) - { - bIsDrained = true; - drainedTimer = 50; uint32 damage = me->CountPctFromMaxHealth(30); - if (me->GetHealth() < damage) - me->SetHealth(me->CountPctFromMaxHealth(1)); - else + me->LowerPlayerDamageReq(damage); + me->ModifyHealth(-std::min(damage, me->GetHealth() - 1)); + + scheduler.DelayAll(Seconds(15)); + break; + } + case ACTION_DRAINED: + if (HealthAbovePct(30)) { - me->SetHealth(me->GetHealth() - damage); - me->LowerPlayerDamageReq(damage); + Talk(SAY_BUBBLE); + DoCast(me, SPELL_PROTECTIVE_BUBBLE, true); } - DoCast(SPELL_DRAINED); - me->SetVisible(false); - me->AttackStop(); - } - else - drainedTimer -= diff; - } - else if (bIsDrained) - { - if (burstTimer <= 0) - { - DoExplodeCompleted(); - } - else - burstTimer -= diff; + break; + default: + break; } } - else + + uint32 GetData(uint32 type) const override { - if (me->HasUnitState(UNIT_STATE_CASTING)) + if (type == DATA_DEHYDRATION) + return _dehydration ? 1 : 0; + return 0; + } + + void KilledUnit(Unit* victim) override + { + if (victim->GetTypeId() == TYPEID_PLAYER) + Talk(SAY_SLAY); + } + + void JustDied(Unit* killer) override + { + BossAI::JustDied(killer); + Talk(SAY_DEATH); + } + + void JustSummoned(Creature* summon) override + { + summons.Summon(summon); + + if (summon->GetEntry() == NPC_ICHOR_GLOBULE) + DoCast(summon, SPELL_WATER_GLOBULE_VISUAL); + } + + void SummonedCreatureDespawn(Creature* summon) override + { + BossAI::SummonedCreatureDespawn(summon); + + if (summons.empty()) + me->RemoveAurasDueToSpell(SPELL_DRAINED, ObjectGuid::Empty, 0, AURA_REMOVE_BY_EXPIRE); + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) return; - events.Update(diff); - - switch (events.ExecuteEvent()) + if (!_isFrenzy && HealthBelowPct(25) && !me->HasAura(SPELL_DRAINED)) { - case EVENT_WATER_BLAST: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) - DoCast(target, SPELL_WATER_BLAST); - events.ScheduleEvent(EVENT_WATER_BLAST, urand(6000, 9000)); - break; - case EVENT_WATER_BOLT_VOLLEY: - DoCast(SPELL_WATER_BOLT_VOLLEY); - events.ScheduleEvent(EVENT_WATER_BOLT_VOLLEY, urand(10000, 15000)); - break; + Talk(SAY_ENRAGE); + DoCast(me, SPELL_FRENZY, true); + _isFrenzy = true; } - DoMeleeAttackIfReady(); + scheduler.Update(diff, + std::bind(&BossAI::DoMeleeAttackIfReady, this)); } + + void ScheduleTasks() override + { + scheduler.Async([this] + { + DoCast(me, SPELL_SHRINK); + DoCast(me, SPELL_PROTECTIVE_BUBBLE); + }); + + scheduler.Schedule(Seconds(10), Seconds(15), [this](TaskContext task) + { + DoCastAOE(SPELL_WATER_BOLT_VOLLEY); + task.Repeat(Seconds(10), Seconds(15)); + }); + + scheduler.Schedule(Seconds(6), Seconds(9), [this](TaskContext task) + { + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 50.0f)) + DoCast(target, SPELL_WATER_BLAST); + task.Repeat(Seconds(6), Seconds(9)); + }); + } + + private: + bool _isFrenzy; + bool _dehydration; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetVioletHoldAI(creature); } - - private: - InstanceScript* instance; - SummonList m_waterElements; - EventMap events; - bool bIsExploded; - bool bIsFrenzy; - bool bIsDrained; - bool dehydration; - int32 drainedTimer; - int32 burstTimer; - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI(creature); - } }; class npc_ichor_globule : public CreatureScript { -public: - npc_ichor_globule() : CreatureScript("npc_ichor_globule") { } + public: + npc_ichor_globule() : CreatureScript("npc_ichor_globule") { } - struct npc_ichor_globuleAI : public ScriptedAI - { - npc_ichor_globuleAI(Creature* creature) : ScriptedAI(creature) + struct npc_ichor_globuleAI : public ScriptedAI { - Initialize(); - instance = creature->GetInstanceScript(); - } - - void Initialize() - { - pathId = 0; - } - - void Reset() override - { - Initialize(); - events.Reset(); - DoCast(SPELL_WATER_GLOBULE); - me->SetReactState(REACT_PASSIVE); - } - - void SetData(uint32 id, uint32 data) override - { - if (id == DATA_GLOBULE_PATH) + npc_ichor_globuleAI(Creature* creature) : ScriptedAI(creature) { - pathId = data; - me->GetMotionMaster()->MovePoint(0, globulePaths[pathId]); + _instance = creature->GetInstanceScript(); + creature->SetReactState(REACT_PASSIVE); } - } - void MovementInform(uint32 type, uint32 id) override - { - if (type != POINT_MOTION_TYPE) - return; - - switch (id) + void SpellHit(Unit* caster, SpellInfo const* spellInfo) override { - case 0: - me->GetMotionMaster()->Clear(); - events.ScheduleEvent(EVENT_GLOBULE_MOVE, 500); - break; - case 1: - me->GetMotionMaster()->Clear(); - if (Creature* ichoron = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_ICHORON))) - me->GetMotionMaster()->MoveFollow(ichoron, 0.0f, 0.0f); - break; + if (spellInfo->Id == SPELL_WATER_GLOBULE_VISUAL) + { + DoCast(me, SPELL_WATER_GLOBULE_TRANSFORM); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->GetMotionMaster()->MoveFollow(caster, 0.0f, 0.0f); + } } - } - // on retail spell casted on a creature's death are not casted after death but keeping mob at 1 health, casting it and then letting the mob die. - // this feature should be still implemented - void DamageTaken(Unit* /*attacker*/, uint32 &damage) override + void MovementInform(uint32 type, uint32 id) override + { + if (type != FOLLOW_MOTION_TYPE) + return; + + if (_instance->GetObjectGuid(DATA_ICHORON).GetCounter() != id) + return; + + me->CastSpell(me, SPELL_MERGE); + me->DespawnOrUnsummon(1); + } + + // on retail spell casted on a creature's death are not casted after death but keeping mob at 1 health, casting it and then letting the mob die. + // this feature should be still implemented + void DamageTaken(Unit* /*attacker*/, uint32& damage) override + { + if (damage >= me->GetHealth()) + DoCastAOE(SPELL_SPLASH); + } + + void UpdateAI(uint32 /*diff*/) override { } + + private: + InstanceScript* _instance; + }; + + CreatureAI* GetAI(Creature* creature) const override { - int32 actualHp = me->GetHealth(); - actualHp -= damage; - - if (actualHp <= 0) - DoCast(SPELL_SPLASH); + return GetVioletHoldAI(creature); } +}; - void UpdateAI(uint32 diff) override +// 59820 - Drained +class spell_ichoron_drained : public SpellScriptLoader +{ + public: + spell_ichoron_drained() : SpellScriptLoader("spell_ichoron_drained") { } + + class spell_ichoron_drained_AuraScript : public AuraScript { - events.Update(diff); + PrepareAuraScript(spell_ichoron_drained_AuraScript); - if (events.ExecuteEvent() == EVENT_GLOBULE_MOVE) - me->GetMotionMaster()->MovePoint(1, globulePaths[pathId + 1]); + bool Load() override + { + return GetOwner()->GetEntry() == NPC_ICHORON || GetOwner()->GetEntry() == NPC_DUMMY_ICHORON; + } + + void HandleApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + GetTarget()->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_UNK_31); + GetTarget()->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH); + } + + void HandleRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + GetTarget()->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_UNK_31); + GetTarget()->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH); + + if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_EXPIRE) + if (GetTarget()->IsAIEnabled) + GetTarget()->GetAI()->DoAction(ACTION_DRAINED); + } + + void Register() override + { + AfterEffectApply += AuraEffectApplyFn(spell_ichoron_drained_AuraScript::HandleApply, EFFECT_0, SPELL_AURA_MOD_STUN, AURA_EFFECT_HANDLE_REAL); + AfterEffectRemove += AuraEffectRemoveFn(spell_ichoron_drained_AuraScript::HandleRemove, EFFECT_0, SPELL_AURA_MOD_STUN, AURA_EFFECT_HANDLE_REAL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_ichoron_drained_AuraScript(); } +}; - private: - InstanceScript* instance; - EventMap events; - uint8 pathId; - }; +// 54269 - Merge +class spell_ichoron_merge : public SpellScriptLoader +{ + public: + spell_ichoron_merge() : SpellScriptLoader("spell_ichoron_merge") { } - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI(creature); - } + class spell_ichoron_merge_SpellScript : public SpellScript + { + PrepareSpellScript(spell_ichoron_merge_SpellScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_SHRINK)) + return false; + return true; + } + + void HandleScript(SpellEffIndex /*effIndex*/) + { + if (Creature* target = GetHitCreature()) + { + if (Aura* aura = target->GetAura(SPELL_SHRINK)) + aura->ModStackAmount(-1); + + target->AI()->DoAction(ACTION_WATER_GLOBULE_HIT); + } + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_ichoron_merge_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_ichoron_merge_SpellScript(); + } +}; + +// 54306 - Protective Bubble +class spell_ichoron_protective_bubble : public SpellScriptLoader +{ + public: + spell_ichoron_protective_bubble() : SpellScriptLoader("spell_ichoron_protective_bubble") { } + + class spell_ichoron_protective_bubble_AuraScript : public AuraScript + { + PrepareAuraScript(spell_ichoron_protective_bubble_AuraScript); + + bool Load() override + { + return GetOwner()->GetEntry() == NPC_ICHORON || GetOwner()->GetEntry() == NPC_DUMMY_ICHORON; + } + + void HandleShatter(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + //if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_ENEMY_SPELL) + if (GetAura()->GetCharges() <= 1) + if (GetTarget()->IsAIEnabled) + GetTarget()->GetAI()->DoAction(ACTION_PROTECTIVE_BUBBLE_SHATTERED); + } + + void Register() override + { + AfterEffectRemove += AuraEffectRemoveFn(spell_ichoron_protective_bubble_AuraScript::HandleShatter, EFFECT_0, SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN, AURA_EFFECT_HANDLE_REAL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_ichoron_protective_bubble_AuraScript(); + } +}; + +// 54259 - Splatter +class spell_ichoron_splatter : public SpellScriptLoader +{ + public: + spell_ichoron_splatter() : SpellScriptLoader("spell_ichoron_splatter") { } + + class spell_ichoron_splatter_AuraScript : public AuraScript + { + PrepareAuraScript(spell_ichoron_splatter_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_WATER_GLOBULE_SUMMON_1) + || !sSpellMgr->GetSpellInfo(SPELL_WATER_GLOBULE_SUMMON_2) + || !sSpellMgr->GetSpellInfo(SPELL_WATER_GLOBULE_SUMMON_3) + || !sSpellMgr->GetSpellInfo(SPELL_WATER_GLOBULE_SUMMON_4) + || !sSpellMgr->GetSpellInfo(SPELL_WATER_GLOBULE_SUMMON_5) + || !sSpellMgr->GetSpellInfo(SPELL_SHRINK)) + return false; + return true; + } + + void PeriodicTick(AuraEffect const* /*aurEff*/) + { + PreventDefaultAction(); + GetTarget()->CastSpell(GetTarget(), RAND(SPELL_WATER_GLOBULE_SUMMON_1, SPELL_WATER_GLOBULE_SUMMON_2, SPELL_WATER_GLOBULE_SUMMON_3, SPELL_WATER_GLOBULE_SUMMON_4, SPELL_WATER_GLOBULE_SUMMON_5), true); + } + + void HandleRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_EXPIRE) + if (Aura* aura = GetTarget()->GetAura(SPELL_SHRINK)) + aura->ModStackAmount(10); + } + + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_ichoron_splatter_AuraScript::PeriodicTick, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); + AfterEffectRemove += AuraEffectRemoveFn(spell_ichoron_splatter_AuraScript::HandleRemove, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY, AURA_EFFECT_HANDLE_REAL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_ichoron_splatter_AuraScript(); + } }; class achievement_dehydration : public AchievementCriteriaScript { public: - achievement_dehydration() : AchievementCriteriaScript("achievement_dehydration") - { - } + achievement_dehydration() : AchievementCriteriaScript("achievement_dehydration") { } bool OnCheck(Player* /*player*/, Unit* target) override { @@ -542,5 +477,9 @@ void AddSC_boss_ichoron() { new boss_ichoron(); new npc_ichor_globule(); + new spell_ichoron_drained(); + new spell_ichoron_merge(); + new spell_ichoron_protective_bubble(); + new spell_ichoron_splatter(); new achievement_dehydration(); } diff --git a/src/server/scripts/Northrend/VioletHold/boss_lavanthor.cpp b/src/server/scripts/Northrend/VioletHold/boss_lavanthor.cpp index 8b77b512ca4..c3b617f8199 100644 --- a/src/server/scripts/Northrend/VioletHold/boss_lavanthor.cpp +++ b/src/server/scripts/Northrend/VioletHold/boss_lavanthor.cpp @@ -27,130 +27,82 @@ enum Spells SPELL_LAVA_BURN = 54249 }; -enum LavanthorEvents -{ - EVENT_CAUTERIZING_FLAMES = 1, - EVENT_FIREBOLT, - EVENT_FLAME_BREATH, - EVENT_LAVA_BURN -}; - class boss_lavanthor : public CreatureScript { -public: - boss_lavanthor() : CreatureScript("boss_lavanthor") { } + public: + boss_lavanthor() : CreatureScript("boss_lavanthor") { } - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI(creature); - } - - struct boss_lavanthorAI : public ScriptedAI - { - boss_lavanthorAI(Creature* creature) : ScriptedAI(creature) + struct boss_lavanthorAI : public BossAI { - instance = creature->GetInstanceScript(); - } + boss_lavanthorAI(Creature* creature) : BossAI(creature, DATA_LAVANTHOR) { } - void Reset() override - { - if (instance->GetData(DATA_WAVE_COUNT) == 6) - instance->SetBossState(DATA_1ST_BOSS_EVENT, NOT_STARTED); - else if (instance->GetData(DATA_WAVE_COUNT) == 12) - instance->SetBossState(DATA_2ND_BOSS_EVENT, NOT_STARTED); + void Reset() override + { + BossAI::Reset(); + } - events.Reset(); - } + void EnterCombat(Unit* who) override + { + BossAI::EnterCombat(who); + } - void EnterCombat(Unit* /*who*/) override - { - if (GameObject* door = instance->GetGameObject(DATA_LAVANTHOR_CELL)) - if (door->GetGoState() == GO_STATE_READY) - { - EnterEvadeMode(); + void JustReachedHome() override + { + BossAI::JustReachedHome(); + instance->SetData(DATA_HANDLE_CELLS, DATA_LAVANTHOR); + } + + void JustDied(Unit* killer) override + { + BossAI::JustDied(killer); + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) return; - } - if (instance->GetData(DATA_WAVE_COUNT) == 6) - instance->SetBossState(DATA_1ST_BOSS_EVENT, IN_PROGRESS); - else if (instance->GetData(DATA_WAVE_COUNT) == 12) - instance->SetBossState(DATA_2ND_BOSS_EVENT, IN_PROGRESS); - events.ScheduleEvent(EVENT_FIREBOLT, 1000); - events.ScheduleEvent(EVENT_FLAME_BREATH, 5000); - events.ScheduleEvent(EVENT_LAVA_BURN, 10000); - if (IsHeroic()) - events.ScheduleEvent(EVENT_CAUTERIZING_FLAMES, 3000); - } - - void AttackStart(Unit* who) override - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC) || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - if (me->Attack(who, true)) - { - me->AddThreat(who, 0.0f); - me->SetInCombatWith(who); - who->SetInCombatWith(me); - DoStartMovement(who); + scheduler.Update(diff, + std::bind(&BossAI::DoMeleeAttackIfReady, this)); } - } - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - - switch (events.ExecuteEvent()) + void ScheduleTasks() override { - case EVENT_FIREBOLT: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) + scheduler.Schedule(Seconds(1), [this](TaskContext task) + { + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 40.0f, true)) DoCast(target, SPELL_FIREBOLT); - events.ScheduleEvent(EVENT_FIREBOLT, urand(5000, 13000)); - break; - case EVENT_FLAME_BREATH: - DoCast(SPELL_FLAME_BREATH); - events.ScheduleEvent(EVENT_FLAME_BREATH, urand(10000, 15000)); - break; - case EVENT_LAVA_BURN: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) + task.Repeat(Seconds(5), Seconds(13)); + }); + + scheduler.Schedule(Seconds(5), [this](TaskContext task) + { + DoCastVictim(SPELL_FLAME_BREATH); + task.Repeat(Seconds(10), Seconds(15)); + }); + + scheduler.Schedule(Seconds(10), [this](TaskContext task) + { + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 50.0f)) DoCast(target, SPELL_LAVA_BURN); - events.ScheduleEvent(EVENT_LAVA_BURN, urand(15000, 23000)); - break; - case EVENT_CAUTERIZING_FLAMES: - DoCast(SPELL_CAUTERIZING_FLAMES); - events.ScheduleEvent(EVENT_CAUTERIZING_FLAMES, urand(10000, 16000)); - break; - default: - break; + task.Repeat(Seconds(15), Seconds(23)); + }); + + if (IsHeroic()) + { + scheduler.Schedule(Seconds(3), [this](TaskContext task) + { + DoCastAOE(SPELL_CAUTERIZING_FLAMES); + task.Repeat(Seconds(10), Seconds(16)); + }); + } } + }; - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*killer*/) override + CreatureAI* GetAI(Creature* creature) const override { - if (instance->GetData(DATA_WAVE_COUNT) == 6) - { - instance->SetBossState(DATA_1ST_BOSS_EVENT, DONE); - instance->SetData(DATA_WAVE_COUNT, 7); - } - else if (instance->GetData(DATA_WAVE_COUNT) == 12) - { - instance->SetBossState(DATA_2ND_BOSS_EVENT, DONE); - instance->SetData(DATA_WAVE_COUNT, 13); - } + return GetVioletHoldAI(creature); } - - private: - EventMap events; - InstanceScript* instance; - }; }; void AddSC_boss_lavanthor() diff --git a/src/server/scripts/Northrend/VioletHold/boss_moragg.cpp b/src/server/scripts/Northrend/VioletHold/boss_moragg.cpp index e9ee996b65b..41542416468 100644 --- a/src/server/scripts/Northrend/VioletHold/boss_moragg.cpp +++ b/src/server/scripts/Northrend/VioletHold/boss_moragg.cpp @@ -25,8 +25,8 @@ enum Spells { SPELL_CORROSIVE_SALIVA = 54527, SPELL_OPTIC_LINK = 54396, - SPELL_RAY_OF_PAIN = 54438, // NYI missing spelldifficulty - SPELL_RAY_OF_SUFFERING = 54442, // NYI missing spelldifficulty + SPELL_RAY_OF_PAIN = 54438, + SPELL_RAY_OF_SUFFERING = 54442, // Visual SPELL_OPTIC_LINK_LEVEL_1 = 54393, @@ -34,191 +34,107 @@ enum Spells SPELL_OPTIC_LINK_LEVEL_3 = 54395 }; -enum MoraggEvents -{ - EVENT_CORROSIVE_SALIVA = 1, - EVENT_OPTIC_LINK -}; - class boss_moragg : public CreatureScript { -public: - boss_moragg() : CreatureScript("boss_moragg") { } + public: + boss_moragg() : CreatureScript("boss_moragg") { } - struct boss_moraggAI : public ScriptedAI - { - boss_moraggAI(Creature* creature) : ScriptedAI(creature) + struct boss_moraggAI : public BossAI { - instance = creature->GetInstanceScript(); - } + boss_moraggAI(Creature* creature) : BossAI(creature, DATA_MORAGG) { } - void Reset() override - { - events.Reset(); + void Reset() override + { + BossAI::Reset(); + } - if (instance->GetData(DATA_WAVE_COUNT) == 6) - instance->SetBossState(DATA_1ST_BOSS_EVENT, NOT_STARTED); - else if (instance->GetData(DATA_WAVE_COUNT) == 12) - instance->SetBossState(DATA_2ND_BOSS_EVENT, NOT_STARTED); - } + void EnterCombat(Unit* who) override + { + BossAI::EnterCombat(who); + } - void EnterCombat(Unit* /*who*/) override - { - if (GameObject* door = instance->GetGameObject(DATA_MORAGG_CELL)) - if (door->GetGoState() == GO_STATE_READY) - { - EnterEvadeMode(); + void JustReachedHome() override + { + BossAI::JustReachedHome(); + instance->SetData(DATA_HANDLE_CELLS, DATA_MORAGG); + } + + void JustDied(Unit* killer) override + { + BossAI::JustDied(killer); + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) return; - } - if (instance->GetData(DATA_WAVE_COUNT) == 6) - instance->SetBossState(DATA_1ST_BOSS_EVENT, IN_PROGRESS); - else if (instance->GetData(DATA_WAVE_COUNT) == 12) - instance->SetBossState(DATA_2ND_BOSS_EVENT, IN_PROGRESS); - - me->SetInCombatWithZone(); - - DoCast(SPELL_RAY_OF_PAIN); - DoCast(SPELL_RAY_OF_SUFFERING); - events.ScheduleEvent(EVENT_OPTIC_LINK, 15000); - events.ScheduleEvent(EVENT_CORROSIVE_SALIVA, 5000); - } - - void AttackStart(Unit* who) override - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC) || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - if (me->Attack(who, true)) - { - me->AddThreat(who, 0.0f); - me->SetInCombatWith(who); - who->SetInCombatWith(me); - DoStartMovement(who); + scheduler.Update(diff, + std::bind(&BossAI::DoMeleeAttackIfReady, this)); } - } - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - - switch (events.ExecuteEvent()) + void ScheduleTasks() override { - case EVENT_OPTIC_LINK: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) + scheduler.Async([this] + { + DoCast(me, SPELL_RAY_OF_PAIN); + DoCast(me, SPELL_RAY_OF_SUFFERING); + }); + + scheduler.Schedule(Seconds(15), [this](TaskContext task) + { + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 50.0f, true)) DoCast(target, SPELL_OPTIC_LINK); - events.ScheduleEvent(EVENT_OPTIC_LINK, 25000); - break; - case EVENT_CORROSIVE_SALIVA: + task.Repeat(Seconds(25)); + }); + + scheduler.Schedule(Seconds(5), [this](TaskContext task) + { DoCastVictim(SPELL_CORROSIVE_SALIVA); - events.ScheduleEvent(EVENT_CORROSIVE_SALIVA, 10000); - break; - default: - break; + task.Repeat(Seconds(10)); + }); } + }; - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*killer*/) override + CreatureAI* GetAI(Creature* creature) const override { - if (instance->GetData(DATA_WAVE_COUNT) == 6) - { - instance->SetBossState(DATA_1ST_BOSS_EVENT, DONE); - instance->SetData(DATA_WAVE_COUNT, 7); - } - else if (instance->GetData(DATA_WAVE_COUNT) == 12) - { - instance->SetBossState(DATA_2ND_BOSS_EVENT, DONE); - instance->SetData(DATA_WAVE_COUNT, 13); - } + return GetVioletHoldAI(creature); } - - private: - EventMap events; - InstanceScript* instance; - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI(creature); - } }; -class spell_moragg_ray_of_suffering : public SpellScriptLoader +class spell_moragg_ray : public SpellScriptLoader { -public: - spell_moragg_ray_of_suffering() : SpellScriptLoader("spell_moragg_ray_of_suffering") { } + public: + spell_moragg_ray() : SpellScriptLoader("spell_moragg_ray") { } - class spell_moragg_ray_of_suffering_AuraScript : public AuraScript - { - PrepareAuraScript(spell_moragg_ray_of_suffering_AuraScript); - - void OnPeriodic(AuraEffect const* aurEff) + class spell_moragg_ray_AuraScript : public AuraScript { - PreventDefaultAction(); - std::list players = GetTarget()->getThreatManager().getThreatList(); - if (!players.empty()) + PrepareAuraScript(spell_moragg_ray_AuraScript); + + void OnPeriodic(AuraEffect const* aurEff) { - std::list::iterator itr = players.begin(); - std::advance(itr, urand(0, players.size() - 1)); + PreventDefaultAction(); - uint32 triggerSpell = GetSpellInfo()->Effects[aurEff->GetEffIndex()].TriggerSpell; - GetTarget()->CastCustomSpell(triggerSpell, SPELLVALUE_MAX_TARGETS, 1, (*itr)->getTarget(), TRIGGERED_FULL_MASK, NULL, aurEff); + if (!GetTarget()->IsAIEnabled) + return; + + if (Unit* target = GetTarget()->GetAI()->SelectTarget(SELECT_TARGET_RANDOM, 0, 45.0f, true)) + { + uint32 triggerSpell = GetSpellInfo()->Effects[aurEff->GetEffIndex()].TriggerSpell; + GetTarget()->CastSpell(target, triggerSpell, TRIGGERED_FULL_MASK, nullptr, aurEff); + } } - } - void Register() override - { - OnEffectPeriodic += AuraEffectPeriodicFn(spell_moragg_ray_of_suffering_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); - } - }; - - AuraScript* GetAuraScript() const override - { - return new spell_moragg_ray_of_suffering_AuraScript(); - } -}; - -class spell_moragg_ray_of_pain : public SpellScriptLoader -{ -public: - spell_moragg_ray_of_pain() : SpellScriptLoader("spell_moragg_ray_of_pain") { } - - class spell_moragg_ray_of_pain_AuraScript : public AuraScript - { - PrepareAuraScript(spell_moragg_ray_of_pain_AuraScript); - - void OnPeriodic(AuraEffect const* aurEff) - { - PreventDefaultAction(); - std::list players = GetTarget()->getThreatManager().getThreatList(); - if (!players.empty()) + void Register() override { - std::list::iterator itr = players.begin(); - std::advance(itr, urand(0, players.size() - 1)); - - uint32 triggerSpell = GetSpellInfo()->Effects[aurEff->GetEffIndex()].TriggerSpell; - GetTarget()->CastCustomSpell(triggerSpell, SPELLVALUE_MAX_TARGETS, 1, (*itr)->getTarget(), TRIGGERED_FULL_MASK, NULL, aurEff); + OnEffectPeriodic += AuraEffectPeriodicFn(spell_moragg_ray_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); } - } + }; - void Register() override + AuraScript* GetAuraScript() const override { - OnEffectPeriodic += AuraEffectPeriodicFn(spell_moragg_ray_of_pain_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); + return new spell_moragg_ray_AuraScript(); } - }; - - AuraScript* GetAuraScript() const override - { - return new spell_moragg_ray_of_pain_AuraScript(); - } }; class spell_moragg_optic_link : public SpellScriptLoader @@ -232,30 +148,15 @@ public: void OnPeriodic(AuraEffect const* aurEff) { - switch (aurEff->GetTickNumber()) // Different visual based on tick + if (Unit* caster = GetCaster()) { - case 1: - case 2: - case 3: - GetTarget()->CastCustomSpell(SPELL_OPTIC_LINK_LEVEL_1, SPELLVALUE_MAX_TARGETS, 1, (Unit*)NULL, TRIGGERED_FULL_MASK, NULL, aurEff); - break; - case 4: - case 5: - case 6: - case 7: - GetTarget()->CastCustomSpell(SPELL_OPTIC_LINK_LEVEL_1, SPELLVALUE_MAX_TARGETS, 1, (Unit*)NULL, TRIGGERED_FULL_MASK, NULL, aurEff); - GetTarget()->CastCustomSpell(SPELL_OPTIC_LINK_LEVEL_2, SPELLVALUE_MAX_TARGETS, 1, (Unit*)NULL, TRIGGERED_FULL_MASK, NULL, aurEff); - break; - case 8: - case 9: - case 10: - case 11: - GetTarget()->CastCustomSpell(SPELL_OPTIC_LINK_LEVEL_1, SPELLVALUE_MAX_TARGETS, 1, (Unit*)NULL, TRIGGERED_FULL_MASK, NULL, aurEff); - GetTarget()->CastCustomSpell(SPELL_OPTIC_LINK_LEVEL_2, SPELLVALUE_MAX_TARGETS, 1, (Unit*)NULL, TRIGGERED_FULL_MASK, NULL, aurEff); - GetTarget()->CastCustomSpell(SPELL_OPTIC_LINK_LEVEL_3, SPELLVALUE_MAX_TARGETS, 1, (Unit*)NULL, TRIGGERED_FULL_MASK, NULL, aurEff); - break; - default: - break; + if (aurEff->GetTickNumber() >= 8) + caster->CastSpell(GetTarget(), SPELL_OPTIC_LINK_LEVEL_3, TRIGGERED_FULL_MASK, nullptr, aurEff); + + if (aurEff->GetTickNumber() >= 4) + caster->CastSpell(GetTarget(), SPELL_OPTIC_LINK_LEVEL_2, TRIGGERED_FULL_MASK, nullptr, aurEff); + + caster->CastSpell(GetTarget(), SPELL_OPTIC_LINK_LEVEL_1, TRIGGERED_FULL_MASK, nullptr, aurEff); } } @@ -293,7 +194,6 @@ public: void AddSC_boss_moragg() { new boss_moragg(); - new spell_moragg_ray_of_suffering(); - new spell_moragg_ray_of_pain(); + new spell_moragg_ray(); new spell_moragg_optic_link(); } diff --git a/src/server/scripts/Northrend/VioletHold/boss_xevozz.cpp b/src/server/scripts/Northrend/VioletHold/boss_xevozz.cpp index fe0f161cc27..93e74aaca71 100644 --- a/src/server/scripts/Northrend/VioletHold/boss_xevozz.cpp +++ b/src/server/scripts/Northrend/VioletHold/boss_xevozz.cpp @@ -22,25 +22,34 @@ #include "Player.h" #include "violet_hold.h" +/* + * TODO: + * - Implement Ethereal Summon Target + */ + enum Spells { SPELL_ARCANE_BARRAGE_VOLLEY = 54202, SPELL_ARCANE_BUFFET = 54226, - SPELL_SUMMON_ETHEREAL_SPHERE_1 = 54102, - SPELL_SUMMON_ETHEREAL_SPHERE_2 = 61337, - SPELL_SUMMON_ETHEREAL_SPHERE_3 = 54138 + SPELL_SUMMON_TARGET_VISUAL = 54111 }; +static uint32 const EtherealSphereCount = 3; +static uint32 const EtherealSphereSummonSpells[EtherealSphereCount] = { 54102, 54137, 54138 }; +static uint32 const EtherealSphereHeroicSummonSpells[EtherealSphereCount] = { 54102, 54137, 54138 }; + enum NPCs { NPC_ETHEREAL_SPHERE = 29271, - NPC_ETHEREAL_SPHERE2 = 32582 + NPC_ETHEREAL_SPHERE2 = 32582, + NPC_ETHEREAL_SUMMON_TARGET = 29276 }; enum CreatureSpells { SPELL_ARCANE_POWER = 54160, H_SPELL_ARCANE_POWER = 59474, + SPELL_MAGIC_PULL = 50770, SPELL_SUMMON_PLAYERS = 54164, SPELL_POWER_BALL_VISUAL = 54141, SPELL_POWER_BALL_DAMAGE_TRIGGER = 54207 @@ -48,24 +57,17 @@ enum CreatureSpells enum Yells { + // Xevozz SAY_AGGRO = 0, SAY_SLAY = 1, SAY_DEATH = 2, SAY_SPAWN = 3, SAY_CHARGED = 4, SAY_REPEAT_SUMMON = 5, - SAY_SUMMON_ENERGY = 6 -}; + SAY_SUMMON_ENERGY = 6, -enum XevozzEvents -{ - EVENT_ARCANE_BARRAGE = 1, - EVENT_ARCANE_BUFFET, - EVENT_SUMMON_SPHERE, - EVENT_SUMMON_SPHERE_2, - EVENT_RANGE_CHECK, - EVENT_SUMMON_PLAYERS, - EVENT_DESPAWN_SPHERE + // Ethereal Sphere + SAY_ETHEREAL_SPHERE_SUMMON = 0 }; enum SphereActions @@ -75,319 +77,210 @@ enum SphereActions class boss_xevozz : public CreatureScript { -public: - boss_xevozz() : CreatureScript("boss_xevozz") { } + public: + boss_xevozz() : CreatureScript("boss_xevozz") { } - struct boss_xevozzAI : public ScriptedAI - { - boss_xevozzAI(Creature* creature) : ScriptedAI(creature) + struct boss_xevozzAI : public BossAI { - instance = creature->GetInstanceScript(); - } + boss_xevozzAI(Creature* creature) : BossAI(creature, DATA_XEVOZZ) { } - void Reset() override - { - if (instance->GetData(DATA_WAVE_COUNT) == 6) - instance->SetBossState(DATA_1ST_BOSS_EVENT, NOT_STARTED); - else if (instance->GetData(DATA_WAVE_COUNT) == 12) - instance->SetBossState(DATA_2ND_BOSS_EVENT, NOT_STARTED); - - DespawnSphere(); - events.Reset(); - } - - void DespawnSphere() - { - std::list assistList; - GetCreatureListWithEntryInGrid(assistList, me, NPC_ETHEREAL_SPHERE, 150.0f); - GetCreatureListWithEntryInGrid(assistList, me, NPC_ETHEREAL_SPHERE2, 150.0f); - - if (assistList.empty()) - return; - - for (std::list::const_iterator iter = assistList.begin(); iter != assistList.end(); ++iter) + void Reset() override { - if (Creature* pSphere = *iter) - pSphere->Kill(pSphere, false); + BossAI::Reset(); } - } - void JustSummoned(Creature* summoned) override - { - summoned->SetSpeed(MOVE_RUN, 0.5f); - summoned->GetMotionMaster()->MoveFollow(me, 0.0f, 0.0f); - } - - void AttackStart(Unit* who) override - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC) || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - if (me->Attack(who, true)) + void EnterCombat(Unit* who) override { - me->AddThreat(who, 0.0f); - me->SetInCombatWith(who); - who->SetInCombatWith(me); - DoStartMovement(who); + BossAI::EnterCombat(who); + Talk(SAY_AGGRO); } - } - void EnterCombat(Unit* /*who*/) override - { - if (GameObject* door = instance->GetGameObject(DATA_XEVOZZ_CELL)) - if (door->GetGoState() == GO_STATE_READY) - { - EnterEvadeMode(); + void JustReachedHome() override + { + BossAI::JustReachedHome(); + instance->SetData(DATA_HANDLE_CELLS, DATA_XEVOZZ); + } + + void JustSummoned(Creature* summon) override + { + BossAI::JustSummoned(summon); + summon->GetMotionMaster()->MoveFollow(me, 0.0f, 0.0f); + } + + void KilledUnit(Unit* victim) override + { + if (victim->GetTypeId() == TYPEID_PLAYER) + Talk(SAY_SLAY); + } + + void JustDied(Unit* killer) override + { + BossAI::JustDied(killer); + Talk(SAY_DEATH); + } + + void SpellHit(Unit* /*who*/, SpellInfo const* spell) override + { + if (spell->Id == SPELL_ARCANE_POWER || spell->Id == H_SPELL_ARCANE_POWER) + Talk(SAY_SUMMON_ENERGY); + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) return; - } - Talk(SAY_AGGRO); - - if (instance->GetData(DATA_WAVE_COUNT) == 6) - instance->SetBossState(DATA_1ST_BOSS_EVENT, IN_PROGRESS); - else if (instance->GetData(DATA_WAVE_COUNT) == 12) - instance->SetBossState(DATA_2ND_BOSS_EVENT, IN_PROGRESS); - - events.ScheduleEvent(EVENT_SUMMON_SPHERE, 5000); - events.ScheduleEvent(EVENT_ARCANE_BARRAGE, urand(8000, 10000)); - events.ScheduleEvent(EVENT_ARCANE_BUFFET, urand(10000, 11000)); - } - - void JustDied(Unit* /*killer*/) override - { - Talk(SAY_DEATH); - - DespawnSphere(); - - if (instance->GetData(DATA_WAVE_COUNT) == 6) - { - instance->SetBossState(DATA_1ST_BOSS_EVENT, DONE); - instance->SetData(DATA_WAVE_COUNT, 7); + scheduler.Update(diff, + std::bind(&BossAI::DoMeleeAttackIfReady, this)); } - else if (instance->GetData(DATA_WAVE_COUNT) == 12) + + void ScheduleTasks() override { - instance->SetBossState(DATA_2ND_BOSS_EVENT, NOT_STARTED); - instance->SetData(DATA_WAVE_COUNT, 13); - } - } - - void KilledUnit(Unit* victim) override - { - if (victim->GetTypeId() == TYPEID_PLAYER) - Talk(SAY_SLAY); - } - - void SpellHit(Unit* who, const SpellInfo* spell) override - { - if (!who->ToCreature()) - return; - - if ((spell->Id == SPELL_ARCANE_POWER) || (spell->Id == H_SPELL_ARCANE_POWER)) - Talk(SAY_SUMMON_ENERGY); - } - - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - - switch (events.ExecuteEvent()) - { - case EVENT_ARCANE_BARRAGE: - DoCast(SPELL_ARCANE_BARRAGE_VOLLEY); - events.ScheduleEvent(EVENT_ARCANE_BARRAGE, urand(8000, 10000)); - break; - case EVENT_ARCANE_BUFFET: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) - DoCast(target, SPELL_ARCANE_BUFFET); - events.ScheduleEvent(EVENT_ARCANE_BUFFET, urand(15000, 20000)); - break; - case EVENT_SUMMON_SPHERE: - Talk(SAY_REPEAT_SUMMON); - DoCast(SPELL_SUMMON_ETHEREAL_SPHERE_1); - if (IsHeroic()) - events.ScheduleEvent(EVENT_SUMMON_SPHERE_2, 2500); - events.ScheduleEvent(EVENT_SUMMON_PLAYERS, urand(33000, 35000)); - events.ScheduleEvent(EVENT_SUMMON_SPHERE, urand(45000, 47000)); - break; - case EVENT_SUMMON_SPHERE_2: - Talk(SAY_REPEAT_SUMMON); - DoCast(SPELL_SUMMON_ETHEREAL_SPHERE_2); - break; - case EVENT_SUMMON_PLAYERS: + scheduler.Schedule(Seconds(8), Seconds(10), [this](TaskContext task) { - Creature* sphere = me->FindNearestCreature(NPC_ETHEREAL_SPHERE, 150.0f); - if (!sphere) - sphere = me->FindNearestCreature(NPC_ETHEREAL_SPHERE2, 150.0f); - if (sphere) - sphere->GetAI()->DoAction(ACTION_SUMMON); - break; - } - default: - break; + DoCastAOE(SPELL_ARCANE_BARRAGE_VOLLEY); + task.Repeat(Seconds(8), Seconds(10)); + }); + + scheduler.Schedule(Seconds(10), Seconds(11), [this](TaskContext task) + { + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 45.0f, true)) + DoCast(target, SPELL_ARCANE_BUFFET); + task.Repeat(Seconds(15), Seconds(20)); + }); + + scheduler.Schedule(Seconds(5), [this](TaskContext task) + { + Talk(SAY_REPEAT_SUMMON); + + std::list summonSpells = { 0, 1, 2 }; + + uint8 spell = Trinity::Containers::SelectRandomContainerElement(summonSpells); + DoCast(me, EtherealSphereSummonSpells[spell]); + summonSpells.remove(spell); + + if (IsHeroic()) + { + spell = Trinity::Containers::SelectRandomContainerElement(summonSpells); + task.Schedule(Milliseconds(2500), [this, spell](TaskContext /*task*/) + { + DoCast(me, EtherealSphereHeroicSummonSpells[spell]); + }); + } + + task.Schedule(Seconds(33), Seconds(35), [this](TaskContext /*task*/) + { + DummyEntryCheckPredicate pred; + summons.DoAction(ACTION_SUMMON, pred); + }); + + task.Repeat(Seconds(45), Seconds(47)); + }); } + }; - DoMeleeAttackIfReady(); + CreatureAI* GetAI(Creature* creature) const override + { + return GetVioletHoldAI(creature); } - - private: - InstanceScript* instance; - EventMap events; - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI(creature); - } }; class npc_ethereal_sphere : public CreatureScript { -public: - npc_ethereal_sphere() : CreatureScript("npc_ethereal_sphere") { } + public: + npc_ethereal_sphere() : CreatureScript("npc_ethereal_sphere") { } - struct npc_ethereal_sphereAI : public ScriptedAI - { - npc_ethereal_sphereAI(Creature* creature) : ScriptedAI(creature) + struct npc_ethereal_sphereAI : public ScriptedAI { - Initialize(); - instance = creature->GetInstanceScript(); - } - - void Initialize() - { - arcanePower = false; - } - - void Reset() override - { - Initialize(); - events.Reset(); - DoCast(SPELL_POWER_BALL_VISUAL); - DoCast(SPELL_POWER_BALL_DAMAGE_TRIGGER); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); - me->setFaction(16); - events.ScheduleEvent(EVENT_DESPAWN_SPHERE, 40000); - events.ScheduleEvent(EVENT_RANGE_CHECK, 1000); - } - - void DoAction(int32 action) override - { - if (action == ACTION_SUMMON) - DoCast(SPELL_SUMMON_PLAYERS); - } - - void UpdateAI(uint32 diff) override - { - events.Update(diff); - - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - - switch (events.ExecuteEvent()) + npc_ethereal_sphereAI(Creature* creature) : ScriptedAI(creature) { - case EVENT_RANGE_CHECK: - if (Creature* xevozz = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_XEVOZZ))) + instance = creature->GetInstanceScript(); + } + + void Reset() override + { + scheduler.CancelAll(); + ScheduledTasks(); + + DoCast(me, SPELL_POWER_BALL_VISUAL); + DoCast(me, SPELL_POWER_BALL_DAMAGE_TRIGGER); + + me->DespawnOrUnsummon(40000); + } + + void DoAction(int32 action) override + { + if (action == ACTION_SUMMON) + { + Talk(SAY_ETHEREAL_SPHERE_SUMMON); + DoCastAOE(SPELL_SUMMON_PLAYERS); + } + } + + void UpdateAI(uint32 diff) override + { + scheduler.Update(diff); + } + + void ScheduledTasks() + { + scheduler.Schedule(Seconds(1), [this](TaskContext task) + { + if (Creature* xevozz = instance->GetCreature(DATA_XEVOZZ)) { - if (me->IsWithinDist(xevozz, 3.0f) && !arcanePower) + if (me->IsWithinDist(xevozz, 3.0f)) { - DoCast(SPELL_ARCANE_POWER); - arcanePower = true; - events.ScheduleEvent(EVENT_DESPAWN_SPHERE, 8000); + DoCastAOE(SPELL_ARCANE_POWER); + me->DespawnOrUnsummon(8000); + return; } } - events.ScheduleEvent(EVENT_RANGE_CHECK, 1000); - break; - case EVENT_DESPAWN_SPHERE: - me->DespawnOrUnsummon(); - break; + task.Repeat(); + }); } + + private: + InstanceScript* instance; + TaskScheduler scheduler; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetVioletHoldAI(creature); } - - private: - InstanceScript* instance; - EventMap events; - bool arcanePower; - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI(creature); - } }; class spell_xevozz_summon_players : public SpellScriptLoader { -public: - spell_xevozz_summon_players() : SpellScriptLoader("spell_xevozz_summon_players") { } + public: + spell_xevozz_summon_players() : SpellScriptLoader("spell_xevozz_summon_players") { } - class spell_xevozz_summon_players_SpellScript : public SpellScript - { - PrepareSpellScript(spell_xevozz_summon_players_SpellScript); - - void HandleScript(SpellEffIndex /*effIndex*/) + class spell_xevozz_summon_players_SpellScript : public SpellScript { - Unit* target = GetHitUnit(); + PrepareSpellScript(spell_xevozz_summon_players_SpellScript); - if (target) + bool Validate(SpellInfo const* /*spellInfo*/) override { - Position pos = GetOriginalCaster()->GetPosition(); - - target->NearTeleportTo(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation()); - } - } - - void Register() override - { - OnEffectHitTarget += SpellEffectFn(spell_xevozz_summon_players_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY); - } - }; - - SpellScript* GetSpellScript() const override - { - return new spell_xevozz_summon_players_SpellScript(); - } -}; - -class spell_xevozz_summon_ethereal_sphere : public SpellScriptLoader -{ -public: - spell_xevozz_summon_ethereal_sphere() : SpellScriptLoader("spell_xevozz_summon_ethereal_sphere") { } - - class spell_xevozz_summon_ethereal_sphere_SpellScript : public SpellScript - { - PrepareSpellScript(spell_xevozz_summon_ethereal_sphere_SpellScript); - - void HandleScript(SpellDestination& target) - { - Unit* caster = GetOriginalCaster(); - Position pos; - float distance = 0.0f; - - while (distance < 20.0f) - { - pos = caster->GetRandomNearPosition(60.0f); - distance = caster->GetDistance(pos); + if (!sSpellMgr->GetSpellInfo(SPELL_MAGIC_PULL)) + return false; + return true; } - target.Relocate(pos); - } + void HandleScript(SpellEffIndex /*effIndex*/) + { + GetCaster()->CastSpell(GetHitUnit(), SPELL_MAGIC_PULL, true); + } - void Register() override + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_xevozz_summon_players_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY); + } + }; + + SpellScript* GetSpellScript() const override { - OnDestinationTargetSelect += SpellDestinationTargetSelectFn(spell_xevozz_summon_ethereal_sphere_SpellScript::HandleScript, EFFECT_0, TARGET_DEST_DB); + return new spell_xevozz_summon_players_SpellScript(); } - }; - - SpellScript* GetSpellScript() const override - { - return new spell_xevozz_summon_ethereal_sphere_SpellScript(); - } }; void AddSC_boss_xevozz() @@ -395,5 +288,4 @@ void AddSC_boss_xevozz() new boss_xevozz(); new npc_ethereal_sphere(); new spell_xevozz_summon_players(); - new spell_xevozz_summon_ethereal_sphere(); } diff --git a/src/server/scripts/Northrend/VioletHold/boss_zuramat.cpp b/src/server/scripts/Northrend/VioletHold/boss_zuramat.cpp index 446ea264de9..14d7b5fcd95 100644 --- a/src/server/scripts/Northrend/VioletHold/boss_zuramat.cpp +++ b/src/server/scripts/Northrend/VioletHold/boss_zuramat.cpp @@ -25,9 +25,10 @@ enum Spells SPELL_SUMMON_VOID_SENTRY = 54369, SPELL_VOID_SHIFT = 54361, SPELL_VOID_SHIFTED = 54343, - + SPELL_ZURAMAT_ADD = 54341, SPELL_ZURAMAT_ADD_2 = 54342, - H_SPELL_ZURAMAT_ADD_2 = 59747 + SPELL_ZURAMAT_ADD_DUMMY = 54351, + SPELL_SUMMON_VOID_SENTRY_BALL = 58650 }; enum Yells @@ -42,188 +43,172 @@ enum Yells enum Misc { + ACTION_DESPAWN_VOID_SENTRY_BALL = 1, DATA_VOID_DANCE = 2153 }; -enum ZuramatEvents -{ - EVENT_VOID_SHIFT = 1, - EVENT_SUMMON_VOID, - EVENT_SHROUD_OF_DARKNESS -}; - class boss_zuramat : public CreatureScript { -public: - boss_zuramat() : CreatureScript("boss_zuramat") { } + public: + boss_zuramat() : CreatureScript("boss_zuramat") { } - struct boss_zuramatAI : public ScriptedAI - { - boss_zuramatAI(Creature* creature) : ScriptedAI(creature), sentries(me) + struct boss_zuramatAI : public BossAI { - Initialize(); - instance = creature->GetInstanceScript(); - } - - void Initialize() - { - voidDance = true; - } - - void DespawnSentries() - { - sentries.DespawnAll(); - std::list sentrylist; - GetCreatureListWithEntryInGrid(sentrylist, me, NPC_VOID_SENTRY_BALL, 200.0f); - if (!sentrylist.empty()) - for (std::list::const_iterator itr = sentrylist.begin(); itr != sentrylist.end(); ++itr) - (*itr)->DespawnOrUnsummon(); - } - - void Reset() override - { - if (instance->GetData(DATA_WAVE_COUNT) == 6) - instance->SetData(DATA_1ST_BOSS_EVENT, NOT_STARTED); - else if (instance->GetData(DATA_WAVE_COUNT) == 12) - instance->SetData(DATA_2ND_BOSS_EVENT, NOT_STARTED); - - Initialize(); - events.Reset(); - DespawnSentries(); - } - - void AttackStart(Unit* who) override - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC) || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - if (me->Attack(who, true)) + boss_zuramatAI(Creature* creature) : BossAI(creature, DATA_ZURAMAT) { - me->AddThreat(who, 0.0f); - me->SetInCombatWith(who); - who->SetInCombatWith(me); - DoStartMovement(who); + Initialize(); } - } - void EnterCombat(Unit* /*who*/) override - { - if (GameObject* door = instance->GetGameObject(DATA_ZURAMAT_CELL)) - if (door->GetGoState() == GO_STATE_READY) - { - EnterEvadeMode(); + void Initialize() + { + _voidDance = true; + } + + void Reset() override + { + BossAI::Reset(); + Initialize(); + } + + void EnterCombat(Unit* who) override + { + BossAI::EnterCombat(who); + Talk(SAY_AGGRO); + } + + void JustReachedHome() override + { + BossAI::JustReachedHome(); + instance->SetData(DATA_HANDLE_CELLS, DATA_ZURAMAT); + } + + void SummonedCreatureDies(Creature* summon, Unit* /*who*/) override + { + if (summon->GetEntry() == NPC_VOID_SENTRY) + _voidDance = false; + } + + void SummonedCreatureDespawn(Creature* summon) override + { + if (summon->GetEntry() == NPC_VOID_SENTRY) + summon->AI()->DoAction(ACTION_DESPAWN_VOID_SENTRY_BALL); + BossAI::SummonedCreatureDespawn(summon); + } + + uint32 GetData(uint32 type) const override + { + if (type == DATA_VOID_DANCE) + return _voidDance ? 1 : 0; + + return 0; + } + + void JustDied(Unit* killer) override + { + BossAI::JustDied(killer); + Talk(SAY_DEATH); + } + + void KilledUnit(Unit* victim) override + { + if (victim->GetTypeId() == TYPEID_PLAYER) + Talk(SAY_SLAY); + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) return; - } - Talk(SAY_AGGRO); - - if (instance->GetData(DATA_WAVE_COUNT) == 6) - instance->SetBossState(DATA_1ST_BOSS_EVENT, IN_PROGRESS); - else if (instance->GetData(DATA_WAVE_COUNT) == 12) - instance->SetData(DATA_2ND_BOSS_EVENT, IN_PROGRESS); - - me->SetInCombatWithZone(); - events.ScheduleEvent(EVENT_SHROUD_OF_DARKNESS, urand(18000, 20000)); - events.ScheduleEvent(EVENT_VOID_SHIFT, 9000); - events.ScheduleEvent(EVENT_SUMMON_VOID, 4000); - } - - void JustSummoned(Creature* summon) override - { - sentries.Summon(summon); - } - - void SummonedCreatureDies(Creature* summoned, Unit* /*who*/) override - { - if (summoned->GetEntry() == NPC_VOID_SENTRY) - voidDance = false; - } - - uint32 GetData(uint32 type) const override - { - if (type == DATA_VOID_DANCE) - return voidDance ? 1 : 0; - - return 0; - } - - void JustDied(Unit* /*killer*/) override - { - instance->SetData(DATA_ZURAMAT, 1); - - Talk(SAY_DEATH); - - DespawnSentries(); - - if (instance->GetData(DATA_WAVE_COUNT) == 6) - { - instance->SetBossState(DATA_1ST_BOSS_EVENT, DONE); - instance->SetData(DATA_WAVE_COUNT, 7); - } - else if (instance->GetData(DATA_WAVE_COUNT) == 12) - { - instance->SetBossState(DATA_2ND_BOSS_EVENT, DONE); - instance->SetData(DATA_WAVE_COUNT, 13); - } - } - - void KilledUnit(Unit* victim) override - { - if (victim->GetTypeId() == TYPEID_PLAYER) - Talk(SAY_SLAY); - } - - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; - - switch (events.ExecuteEvent()) - { - case EVENT_SUMMON_VOID: - DoCast(SPELL_SUMMON_VOID_SENTRY); - events.ScheduleEvent(EVENT_SUMMON_VOID, urand(7000, 10000)); - break; - case EVENT_VOID_SHIFT: - if (Unit* unit = SelectTarget(SELECT_TARGET_RANDOM, 0)) - DoCast(unit, SPELL_VOID_SHIFT); - events.ScheduleEvent(EVENT_VOID_SHIFT, 15000); - break; - case EVENT_SHROUD_OF_DARKNESS: - DoCast(SPELL_SHROUD_OF_DARKNESS); - events.ScheduleEvent(EVENT_SHROUD_OF_DARKNESS, urand(18000, 20000)); - break; - default: - break; + scheduler.Update(diff, + std::bind(&BossAI::DoMeleeAttackIfReady, this)); } - DoMeleeAttackIfReady(); + void ScheduleTasks() override + { + scheduler.Schedule(Seconds(4), [this](TaskContext task) + { + DoCast(me, SPELL_SUMMON_VOID_SENTRY); + task.Repeat(Seconds(7), Seconds(10)); + }); + + scheduler.Schedule(Seconds(9), [this](TaskContext task) + { + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 60.0f, true)) + DoCast(target, SPELL_VOID_SHIFT); + task.Repeat(Seconds(15)); + }); + + scheduler.Schedule(Seconds(18), Seconds(20), [this](TaskContext task) + { + DoCast(me, SPELL_SHROUD_OF_DARKNESS); + task.Repeat(Seconds(18), Seconds(20)); + }); + } + + private: + bool _voidDance; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetVioletHoldAI(creature); } +}; - private: - InstanceScript* instance; - EventMap events; - SummonList sentries; - bool voidDance; - }; +class npc_void_sentry : public CreatureScript +{ + public: + npc_void_sentry() : CreatureScript("npc_void_sentry") { } - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI(creature); - } + struct npc_void_sentryAI : public ScriptedAI + { + npc_void_sentryAI(Creature* creature) : ScriptedAI(creature), _summons(creature) + { + me->SetReactState(REACT_PASSIVE); + } + + void IsSummonedBy(Unit* /*summoner*/) override + { + me->CastSpell(me, SPELL_SUMMON_VOID_SENTRY_BALL, true); + } + + void JustSummoned(Creature* summon) override + { + _summons.Summon(summon); + summon->SetReactState(REACT_PASSIVE); + } + + void SummonedCreatureDespawn(Creature* summon) override + { + _summons.Despawn(summon); + } + + void DoAction(int32 actionId) override + { + if (actionId == ACTION_DESPAWN_VOID_SENTRY_BALL) + _summons.DespawnAll(); + } + + void JustDied(Unit* /*killer*/) override + { + DoAction(ACTION_DESPAWN_VOID_SENTRY_BALL); + } + + private: + SummonList _summons; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetVioletHoldAI(creature); + } }; class achievement_void_dance : public AchievementCriteriaScript { public: - achievement_void_dance() : AchievementCriteriaScript("achievement_void_dance") - { - } + achievement_void_dance() : AchievementCriteriaScript("achievement_void_dance") { } bool OnCheck(Player* /*player*/, Unit* target) override { @@ -241,5 +226,6 @@ class achievement_void_dance : public AchievementCriteriaScript void AddSC_boss_zuramat() { new boss_zuramat(); + new npc_void_sentry(); new achievement_void_dance(); } diff --git a/src/server/scripts/Northrend/VioletHold/instance_violet_hold.cpp b/src/server/scripts/Northrend/VioletHold/instance_violet_hold.cpp index 652b4815be0..14c3ac58b1f 100644 --- a/src/server/scripts/Northrend/VioletHold/instance_violet_hold.cpp +++ b/src/server/scripts/Northrend/VioletHold/instance_violet_hold.cpp @@ -18,82 +18,150 @@ #include "ScriptMgr.h" #include "ScriptedCreature.h" #include "InstanceScript.h" +#include "WorldPacket.h" #include "violet_hold.h" #include "Player.h" -#include "TemporarySummon.h" -/* Violet Hold encounters: -0 - First boss -1 - Second boss -2 - Cyanigosa*/ +/* + * TODO: + * - replace bosses by dummy npcs also after grid unload + */ -/* Violet hold bosses: -1 - Moragg -2 - Erekem -3 - Ichoron -4 - Lavanthor -5 - Xevozz -6 - Zuramat -7 - Cyanigosa */ +Position const DefenseSystemLocation = { 1888.146f, 803.382f, 58.60389f, 3.071779f }; // sniff -enum AzureSaboteurSpells +Position const CyanigosaSpawnLocation = { 1922.109f, 804.4493f, 52.49254f, 3.176499f }; // sniff +Position const CyanigosaJumpLocation = { 1888.32f, 804.473f, 38.3578f, 0.0f }; // sniff + +Position const SaboteurSpawnLocation = { 1886.251f, 803.0743f, 38.42326f, 3.211406f }; // sniff + +uint32 const PortalPositionsSize = 5; +Position const PortalPositions[PortalPositionsSize] = // sniff { - SABOTEUR_SHIELD_DISRUPTION = 58291, - SABOTEUR_SHIELD_EFFECT = 45775 + { 1877.523f, 850.1788f, 45.36822f, 4.34587f }, // 0 + { 1890.679f, 753.4202f, 48.771f, 1.675516f }, // 1 + { 1936.09f, 803.1875f, 54.09715f, 3.054326f }, // 2 + { 1858.243f, 770.2379f, 40.42146f, 0.9075712f }, // 3 + { 1907.288f, 831.1111f, 40.22015f, 3.560472f } // 4 }; -enum CrystalSpells +uint32 const PortalElitePositionsSize = 3; +Position const PortalElitePositions[PortalElitePositionsSize] = // sniff { - SPELL_ARCANE_LIGHTNING = 57930 + { 1911.281f, 800.9722f, 39.91673f, 3.01942f }, // 5 + { 1926.516f, 763.6616f, 52.35725f, 2.251475f }, // 6 + { 1922.464f, 847.0699f, 48.50161f, 3.961897f } // 7 }; -Position const PortalLocation[] = +uint32 const PortalIntroPositionsSize = 5; +Position const PortalIntroPositions[PortalIntroPositionsSize] = // sniff { - {1877.51f, 850.104f, 44.6599f, 4.7822f }, // WP 1 - {1918.37f, 853.437f, 47.1624f, 4.12294f}, // WP 2 - {1936.07f, 803.198f, 53.3749f, 3.12414f}, // WP 3 - {1927.61f, 758.436f, 51.4533f, 2.20891f}, // WP 4 - {1890.64f, 753.471f, 48.7224f, 1.71042f}, // WP 5 - {1908.31f, 809.657f, 38.7037f, 3.08701f} // WP 6 + { 1877.51f, 850.1042f, 44.65989f, 4.782202f }, // 0 - Intro + { 1890.637f, 753.4705f, 48.72239f, 1.710423f }, // 1 - Intro + { 1936.073f, 803.1979f, 53.37491f, 3.124139f }, // 2 - Intro + { 1886.545f, 803.2014f, 40.40931f, 3.159046f }, // 3 - Boss 1/2 + { 1924.096f, 804.3707f, 54.29256f, 3.228859f } // 4 - Boss 3 }; -Position const ArcaneSphere = {1887.060059f, 806.151001f, 61.321602f, 0.0f}; -Position const BossStartMove1 = {1894.684448f, 739.390503f, 47.668003f, 0.0f}; -Position const BossStartMove2 = {1875.173950f, 860.832703f, 43.333565f, 0.0f}; -Position const BossStartMove21 = {1858.854614f, 855.071411f, 43.333565f, 0.0f}; -Position const BossStartMove22 = {1891.926636f, 863.388977f, 43.333565f, 0.0f}; -Position const BossStartMove3 = {1916.138062f, 778.152222f, 35.772308f, 0.0f}; -Position const BossStartMove4 = {1853.618286f, 758.557617f, 38.657505f, 0.0f}; -Position const BossStartMove5 = {1906.683960f, 842.348022f, 38.637459f, 0.0f}; -Position const BossStartMove6 = {1928.207031f, 852.864441f, 47.200813f, 0.0f}; +uint32 const EncouterPortalsCount = PortalPositionsSize + PortalElitePositionsSize; -Position const CyanigosasSpawnLocation = {1930.281250f, 804.407715f, 52.410946f, 3.139621f}; -Position const MiddleRoomLocation = {1892.291260f, 805.696838f, 38.438862f, 3.139621f}; -Position const MiddleRoomPortalSaboLocation = {1896.622925f, 804.854126f, 38.504772f, 3.139621f}; +uint32 const MoraggPathSize = 3; +G3D::Vector3 const MoraggPath[MoraggPathSize] = // sniff +{ + { 1893.895f, 728.1261f, 47.75016f }, + { 1892.997f, 738.4987f, 47.66684f }, + { 1889.76f, 758.1089f, 47.66684f } +}; + +uint32 const ErekemPathSize = 3; +G3D::Vector3 const ErekemPath[ErekemPathSize] = // sniff +{ + { 1871.456f, 871.0361f, 43.41524f }, + { 1874.948f, 859.5452f, 43.33349f }, + { 1877.245f, 851.967f, 43.3335f } +}; + +uint32 const ErekemGuardLeftPathSize = 3; +G3D::Vector3 const ErekemGuardLeftPath[ErekemGuardLeftPathSize] = // sniff +{ + { 1853.752f, 862.4528f, 43.41614f }, + { 1866.931f, 854.577f, 43.3335f }, + { 1872.973f, 850.7875f, 43.3335f } +}; + +uint32 const ErekemGuardRightPathSize = 3; +G3D::Vector3 const ErekemGuardRightPath[ErekemGuardRightPathSize] = // sniff +{ + { 1892.418f, 872.2831f, 43.41563f }, + { 1885.639f, 859.0245f, 43.3335f }, + { 1882.432f, 852.2423f, 43.3335f } +}; + +uint32 const IchoronPathSize = 5; +G3D::Vector3 const IchoronPath[IchoronPathSize] = // sniff +{ + { 1942.041f, 749.5228f, 30.95229f }, + { 1930.571f, 762.9065f, 31.98814f }, + { 1923.657f, 770.6718f, 34.07256f }, + { 1910.631f, 784.4096f, 37.09015f }, + { 1906.595f, 788.3828f, 37.99429f } +}; + +uint32 const LavanthorPathSize = 3; +G3D::Vector3 const LavanthorPath[LavanthorPathSize] = // sniff +{ + { 1844.557f, 748.7083f, 38.74205f }, + { 1854.618f, 761.5295f, 38.65631f }, + { 1862.17f, 773.2255f, 38.74879f } +}; + +uint32 const XevozzPathSize = 3; +G3D::Vector3 const XevozzPath[XevozzPathSize] = // sniff +{ + { 1908.417f, 845.8502f, 38.71947f }, + { 1905.557f, 841.3157f, 38.65529f }, + { 1899.453f, 832.533f, 38.70752f } +}; + +uint32 const ZuramatPathSize = 3; +G3D::Vector3 const ZuramatPath[ZuramatPathSize] = // sniff +{ + { 1934.151f, 860.9463f, 47.29499f }, + { 1927.085f, 852.1342f, 47.19214f }, + { 1923.226f, 847.3297f, 47.15541f } +}; -// Cyanigosa's prefight event data enum Yells { - CYANIGOSA_SAY_SPAWN = 0 + SAY_CYANIGOSA_SPAWN = 3, + SAY_XEVOZZ_SPAWN = 3, + SAY_EREKEM_SPAWN = 3, + SAY_ICHORON_SPAWN = 3, + SAY_ZURAMAT_SPAWN = 3, + + SOUND_MORAGG_SPAWN = 10112 }; enum Spells { - CYANIGOSA_SPELL_TRANSFORM = 58668, - CYANIGOSA_BLUE_AURA = 47759, + SPELL_CYANIGOSA_TRANSFORM = 58668, + SPELL_CYANIGOSA_ARCANE_POWER_STATE = 49411, + SPELL_MORAGG_EMOTE_ROAR = 48350, + SPELL_LAVANTHOR_SPECIAL_UNARMED = 33334, + SPELL_ZURAMAT_COSMETIC_CHANNEL_OMNI = 57552 }; ObjectData const creatureData[] = { - { NPC_XEVOZZ, DATA_XEVOZZ }, - { NPC_LAVANTHOR, DATA_LAVANTHOR }, - { NPC_ICHORON, DATA_ICHORON }, - { NPC_ZURAMAT, DATA_ZURAMAT }, - { NPC_EREKEM, DATA_EREKEM }, - { NPC_MORAGG, DATA_MORAGG }, - { NPC_CYANIGOSA, DATA_CYANIGOSA }, - { NPC_SINCLARI, DATA_SINCLARI }, - { 0, 0 } // END + { NPC_XEVOZZ, DATA_XEVOZZ }, + { NPC_LAVANTHOR, DATA_LAVANTHOR }, + { NPC_ICHORON, DATA_ICHORON }, + { NPC_ZURAMAT, DATA_ZURAMAT }, + { NPC_EREKEM, DATA_EREKEM }, + { NPC_MORAGG, DATA_MORAGG }, + { NPC_CYANIGOSA, DATA_CYANIGOSA }, + { NPC_SINCLARI, DATA_SINCLARI }, + { NPC_SINCLARI_TRIGGER, DATA_SINCLARI_TRIGGER }, + { 0, 0 } // END }; ObjectData const gameObjectData[] = @@ -110,598 +178,770 @@ ObjectData const gameObjectData[] = { 0, 0 } // END }; +MinionData const minionData[] = +{ + { NPC_EREKEM_GUARD, DATA_EREKEM }, + { 0, 0, } // END +}; + class instance_violet_hold : public InstanceMapScript { -public: - instance_violet_hold() : InstanceMapScript("instance_violet_hold", 608) { } + public: + instance_violet_hold() : InstanceMapScript(VioletHoldScriptName, 608) { } - struct instance_violet_hold_InstanceMapScript : public InstanceScript - { - instance_violet_hold_InstanceMapScript(Map* map) : InstanceScript(map) + struct instance_violet_hold_InstanceMapScript : public InstanceScript { - SetHeaders(DataHeader); - SetBossNumber(EncounterCount); - LoadObjectData(creatureData, gameObjectData); - - uiRemoveNpc = 0; - - uiDoorIntegrity = 100; - - uiWaveCount = 0; - uiLocation = urand(0, 5); - uiFirstBoss = 0; - uiSecondBoss = 0; - uiCountErekemGuards = 0; - uiCountActivationCrystals = 0; - uiCyanigosaEventPhase = 1; - - uiActivationTimer = 5000; - uiDoorSpellTimer = 2000; - uiCyanigosaEventTimer = 3 * IN_MILLISECONDS; - - bActive = false; - bWiped = false; - bIsDoorSpellCast = false; - bCrystalActivated = false; - defenseless = true; - uiMainEventPhase = NOT_STARTED; - zuramatDead = false; - } - - ObjectGuid uiErekemGuard[2]; - - ObjectGuid uiTeleportationPortal; - ObjectGuid uiSaboteurPortal; - - ObjectGuid uiActivationCrystal[4]; - - uint32 uiActivationTimer; - uint32 uiCyanigosaEventTimer; - uint32 uiDoorSpellTimer; - - GuidSet trashMobs; // to kill with crystal - - uint8 uiWaveCount; - uint8 uiLocation; - uint8 uiFirstBoss; - uint8 uiSecondBoss; - uint8 uiRemoveNpc; - - uint8 uiDoorIntegrity; - - uint8 uiCountErekemGuards; - uint8 uiCountActivationCrystals; - uint8 uiCyanigosaEventPhase; - uint8 uiMainEventPhase; // SPECIAL: pre event animations, IN_PROGRESS: event itself - - bool bActive; - bool bWiped; - bool bIsDoorSpellCast; - bool bCrystalActivated; - bool defenseless; - bool zuramatDead; - - std::list NpcAtDoorCastingList; - - void OnCreatureCreate(Creature* creature) override - { - InstanceScript::OnCreatureCreate(creature); - - switch (creature->GetEntry()) + instance_violet_hold_InstanceMapScript(Map* map) : InstanceScript(map) { - case NPC_EREKEM_GUARD: - if (uiCountErekemGuards < 2) - { - uiErekemGuard[uiCountErekemGuards++] = creature->GetGUID(); - creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NON_ATTACKABLE); - } - break; - case NPC_CYANIGOSA: - creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NON_ATTACKABLE); - break; - default: - break; - case NPC_VOID_SENTRY: - if (zuramatDead) - { - creature->DespawnOrUnsummon(); - zuramatDead = false; - } - break; + SetHeaders(DataHeader); + SetBossNumber(EncounterCount); + LoadObjectData(creatureData, gameObjectData); + LoadMinionData(minionData); + + FirstBossId = 0; + SecondBossId = 0; + + DoorIntegrity = 100; + WaveCount = 0; + EventState = NOT_STARTED; + + LastPortalLocation = urand(0, EncouterPortalsCount - 1); + + Defenseless = true; } - if (creature->GetGUID() == uiFirstBoss || creature->GetGUID() == uiSecondBoss) + void OnCreatureCreate(Creature* creature) override { - creature->AllLootRemovedFromCorpse(); - creature->RemoveLootMode(1); - } - } + InstanceScript::OnCreatureCreate(creature); - void OnGameObjectCreate(GameObject* go) override - { - InstanceScript::OnGameObjectCreate(go); - - switch (go->GetEntry()) - { - case GO_ACTIVATION_CRYSTAL: - if (uiCountActivationCrystals < 4) - uiActivationCrystal[uiCountActivationCrystals++] = go->GetGUID(); - break; - default: - break; - } - } - - bool SetBossState(uint32 type, EncounterState state) override - { - if (!InstanceScript::SetBossState(type, state)) - return false; - - switch (type) - { - case DATA_1ST_BOSS_EVENT: - if (state == DONE) - UpdateEncounterState(ENCOUNTER_CREDIT_KILL_CREATURE, NPC_EREKEM, nullptr); - break; - case DATA_2ND_BOSS_EVENT: - if (state == DONE) - UpdateEncounterState(ENCOUNTER_CREDIT_KILL_CREATURE, NPC_MORAGG, nullptr); - break; - case DATA_CYANIGOSA: - if (state == DONE) - { - uiMainEventPhase = DONE; - if (GameObject* mainDoor = GetGameObject(DATA_MAIN_DOOR)) - mainDoor->SetGoState(GO_STATE_ACTIVE); - } - break; - default: - break; - } - - return true; - } - - void SetData(uint32 type, uint32 data) override - { - switch (type) - { - case DATA_WAVE_COUNT: - uiWaveCount = data; - bActive = true; - break; - case DATA_REMOVE_NPC: - uiRemoveNpc = data; - break; - case DATA_PORTAL_LOCATION: - uiLocation = (uint8)data; - break; - case DATA_DOOR_INTEGRITY: - uiDoorIntegrity = data; - defenseless = false; - DoUpdateWorldState(WORLD_STATE_VH_PRISON_STATE, uiDoorIntegrity); - break; - case DATA_NPC_PRESENCE_AT_DOOR_ADD: - NpcAtDoorCastingList.push_back(data); - break; - case DATA_NPC_PRESENCE_AT_DOOR_REMOVE: - if (!NpcAtDoorCastingList.empty()) - NpcAtDoorCastingList.pop_back(); - break; - case DATA_MAIN_DOOR: - if (GameObject* mainDoor = GetGameObject(type)) - mainDoor->SetGoState(GOState(data)); - break; - case DATA_START_BOSS_ENCOUNTER: - switch (uiWaveCount) - { - case 6: - StartBossEncounter(uiFirstBoss); - break; - case 12: - StartBossEncounter(uiSecondBoss); - break; - } - break; - case DATA_ACTIVATE_CRYSTAL: - ActivateCrystal(); - break; - case DATA_MAIN_EVENT_PHASE: - uiMainEventPhase = data; - if (data == IN_PROGRESS) // Start event - { - if (GameObject* mainDoor = GetGameObject(DATA_MAIN_DOOR)) - mainDoor->SetGoState(GO_STATE_READY); - uiWaveCount = 1; - bActive = true; - for (int i = 0; i < 4; ++i) - if (GameObject* crystal = instance->GetGameObject(uiActivationCrystal[i])) - crystal->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); - uiRemoveNpc = 0; // might not have been reset after a wipe on a boss. - } - break; - case DATA_ZURAMAT: - zuramatDead = true; - break; - } - } - - void SetGuidData(uint32 type, ObjectGuid data) override - { - switch (type) - { - case DATA_ADD_TRASH_MOB: - trashMobs.insert(data); - break; - case DATA_DEL_TRASH_MOB: - trashMobs.erase(data); - break; - } - } - - uint32 GetData(uint32 type) const override - { - switch (type) - { - case DATA_WAVE_COUNT: return uiWaveCount; - case DATA_REMOVE_NPC: return uiRemoveNpc; - case DATA_PORTAL_LOCATION: return uiLocation; - case DATA_DOOR_INTEGRITY: return uiDoorIntegrity; - case DATA_NPC_PRESENCE_AT_DOOR: return NpcAtDoorCastingList.size(); - case DATA_FIRST_BOSS: return uiFirstBoss; - case DATA_SECOND_BOSS: return uiSecondBoss; - case DATA_MAIN_EVENT_PHASE: return uiMainEventPhase; - case DATA_DEFENSELESS: return defenseless ? 1 : 0; - } - - return 0; - } - - ObjectGuid GetGuidData(uint32 type) const override - { - switch (type) - { - case DATA_EREKEM_GUARD_1: return uiErekemGuard[0]; - case DATA_EREKEM_GUARD_2: return uiErekemGuard[1]; - case DATA_TELEPORTATION_PORTAL: return uiTeleportationPortal; - case DATA_SABOTEUR_PORTAL: return uiSaboteurPortal; - } - - return InstanceScript::GetGuidData(type); - } - - void SpawnPortal() - { - SetData(DATA_PORTAL_LOCATION, (GetData(DATA_PORTAL_LOCATION) + urand(1, 5))%6); - if (Creature* sinclari = GetCreature(DATA_SINCLARI)) - if (Creature* portal = sinclari->SummonCreature(NPC_TELEPORTATION_PORTAL, PortalLocation[GetData(DATA_PORTAL_LOCATION)], TEMPSUMMON_CORPSE_DESPAWN)) - uiTeleportationPortal = portal->GetGUID(); - } - - void StartBossEncounter(uint8 uiBoss, bool bForceRespawn = true) - { - Creature* boss = nullptr; - - switch (uiBoss) - { - case BOSS_MORAGG: - HandleGameObject(GetObjectGuid(DATA_MORAGG_CELL), bForceRespawn); - boss = GetCreature(DATA_MORAGG); - if (boss) - boss->GetMotionMaster()->MovePoint(0, BossStartMove1); - break; - case BOSS_EREKEM: - HandleGameObject(GetObjectGuid(DATA_EREKEM_CELL), bForceRespawn); - HandleGameObject(GetObjectGuid(DATA_EREKEM_LEFT_GUARD_CELL), bForceRespawn); - HandleGameObject(GetObjectGuid(DATA_EREKEM_RIGHT_GUARD_CELL), bForceRespawn); - - boss = GetCreature(DATA_EREKEM); - if (boss) - boss->GetMotionMaster()->MovePoint(0, BossStartMove2); - - if (Creature* pGuard1 = instance->GetCreature(uiErekemGuard[0])) - { - if (bForceRespawn) - { - pGuard1->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NON_ATTACKABLE); - pGuard1->GetMotionMaster()->MovePoint(0, BossStartMove21); - } - else - pGuard1->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_NON_ATTACKABLE); - } - - if (Creature* pGuard2 = instance->GetCreature(uiErekemGuard[1])) - { - if (bForceRespawn) - { - pGuard2->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_NON_ATTACKABLE); - pGuard2->GetMotionMaster()->MovePoint(0, BossStartMove22); - } - else - pGuard2->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_NON_ATTACKABLE); - } - break; - case BOSS_ICHORON: - HandleGameObject(GetObjectGuid(DATA_ICHORON_CELL), bForceRespawn); - boss = GetCreature(DATA_ICHORON); - if (boss) - boss->GetMotionMaster()->MovePoint(0, BossStartMove3); - break; - case BOSS_LAVANTHOR: - HandleGameObject(GetObjectGuid(DATA_LAVANTHOR_CELL), bForceRespawn); - boss = GetCreature(DATA_LAVANTHOR); - if (boss) - boss->GetMotionMaster()->MovePoint(0, BossStartMove4); - break; - case BOSS_XEVOZZ: - HandleGameObject(GetObjectGuid(DATA_XEVOZZ_CELL), bForceRespawn); - boss = GetCreature(DATA_XEVOZZ); - if (boss) - boss->GetMotionMaster()->MovePoint(0, BossStartMove5); - break; - case BOSS_ZURAMAT: - HandleGameObject(GetObjectGuid(DATA_ZURAMAT_CELL), bForceRespawn); - boss = GetCreature(DATA_ZURAMAT); - if (boss) - boss->GetMotionMaster()->MovePoint(0, BossStartMove6); - break; - } - - // generic boss state changes - if (boss) - { - boss->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_NON_ATTACKABLE); - boss->SetReactState(REACT_AGGRESSIVE); - - if (!bForceRespawn) + switch (creature->GetEntry()) { - if (boss->isDead()) - { - // respawn but avoid to be looted again - boss->Respawn(); - boss->RemoveLootMode(1); - } - else - boss->GetMotionMaster()->MoveTargetedHome(); - - boss->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_NON_ATTACKABLE); - uiWaveCount = 0; + case NPC_EREKEM_GUARD: + for (uint8 i = 0; i < ErekemGuardCount; ++i) + if (ErekemGuardGUIDs[i].IsEmpty()) + { + ErekemGuardGUIDs[i] = creature->GetGUID(); + break; + } + break; + default: + break; } } - } - void AddWave() - { - DoUpdateWorldState(WORLD_STATE_VH, 1); - DoUpdateWorldState(WORLD_STATE_VH_WAVE_COUNT, uiWaveCount); - - switch (uiWaveCount) + void OnCreatureRemove(Creature* creature) override { - case 6: - if (uiFirstBoss == 0) - uiFirstBoss = urand(1, 6); - if (Creature* sinclari = GetCreature(DATA_SINCLARI)) - { - if (Creature* portal = sinclari->SummonCreature(NPC_TELEPORTATION_PORTAL, MiddleRoomPortalSaboLocation, TEMPSUMMON_CORPSE_DESPAWN)) - uiSaboteurPortal = portal->GetGUID(); - if (Creature* azureSaboteur = sinclari->SummonCreature(NPC_SABOTEOUR, MiddleRoomLocation, TEMPSUMMON_DEAD_DESPAWN)) - azureSaboteur->CastSpell(azureSaboteur, SABOTEUR_SHIELD_EFFECT, false); - } - break; - case 12: - if (uiSecondBoss == 0) - do - { - uiSecondBoss = urand(1, 6); - } while (uiSecondBoss == uiFirstBoss); - if (Creature* sinclari = GetCreature(DATA_SINCLARI)) - { - if (Creature* pPortal = sinclari->SummonCreature(NPC_TELEPORTATION_PORTAL, MiddleRoomPortalSaboLocation, TEMPSUMMON_CORPSE_DESPAWN)) - uiSaboteurPortal = pPortal->GetGUID(); - if (Creature* pAzureSaboteur = sinclari->SummonCreature(NPC_SABOTEOUR, MiddleRoomLocation, TEMPSUMMON_DEAD_DESPAWN)) - pAzureSaboteur->CastSpell(pAzureSaboteur, SABOTEUR_SHIELD_EFFECT, false); - } - break; - case 18: - if (Creature* sinclari = GetCreature(DATA_SINCLARI)) - sinclari->SummonCreature(NPC_CYANIGOSA, CyanigosasSpawnLocation, TEMPSUMMON_DEAD_DESPAWN); - break; - case 1: + InstanceScript::OnCreatureRemove(creature); + + switch (creature->GetEntry()) { - if (GameObject* mainDoor = GetGameObject(DATA_MAIN_DOOR)) - mainDoor->SetGoState(GO_STATE_READY); - DoUpdateWorldState(WORLD_STATE_VH_PRISON_STATE, 100); - // no break + case NPC_EREKEM_GUARD: + for (uint8 i = 0; i < ErekemGuardCount; ++i) + if (ErekemGuardGUIDs[i] == creature->GetGUID()) + { + ErekemGuardGUIDs[i].Clear(); + break; + } + break; + default: + break; } - default: - SpawnPortal(); - break; } - } - void WriteSaveDataMore(std::ostringstream& data) override - { - data << uiFirstBoss << ' ' << uiSecondBoss; - } - - void ReadSaveDataMore(std::istringstream& data) override - { - data >> uiFirstBoss; - data >> uiSecondBoss; - } - - bool CheckWipe() - { - Map::PlayerList const &players = instance->GetPlayers(); - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + void OnGameObjectCreate(GameObject* go) override { - Player* player = itr->GetSource(); - if (player->IsGameMaster()) - continue; + InstanceScript::OnGameObjectCreate(go); - if (player->IsAlive()) + switch (go->GetEntry()) + { + case GO_ACTIVATION_CRYSTAL: + for (uint8 i = 0; i < ActivationCrystalCount; ++i) + if (ActivationCrystalGUIDs[i].IsEmpty()) + { + ActivationCrystalGUIDs[i] = go->GetGUID(); + break; + } + break; + default: + break; + } + } + + void OnGameObjectRemove(GameObject* go) override + { + InstanceScript::OnGameObjectRemove(go); + + switch (go->GetEntry()) + { + case GO_ACTIVATION_CRYSTAL: + for (uint8 i = 0; i < ActivationCrystalCount; ++i) + if (ActivationCrystalGUIDs[i] == go->GetGUID()) + { + ActivationCrystalGUIDs[i].Clear(); + break; + } + break; + default: + break; + } + } + + void FillInitialWorldStates(WorldPacket& data) override + { + data << uint32(WORLD_STATE_VH_SHOW) << uint32(EventState == IN_PROGRESS ? 1 : 0); + data << uint32(WORLD_STATE_VH_PRISON_STATE) << uint32(DoorIntegrity); + data << uint32(WORLD_STATE_VH_WAVE_COUNT) << uint32(WaveCount); + } + + bool CheckRequiredBosses(uint32 bossId, Player const* player = nullptr) const override + { + if (_SkipCheckRequiredBosses(player)) + return true; + + switch (bossId) + { + case DATA_MORAGG: + case DATA_EREKEM: + case DATA_ICHORON: + case DATA_LAVANTHOR: + case DATA_XEVOZZ: + case DATA_ZURAMAT: + /// old code used cell door state to check this + if (!(WaveCount == 6 && FirstBossId == bossId) && !(WaveCount == 12 && SecondBossId == bossId)) + return false; + break; + case DATA_CYANIGOSA: + if (WaveCount < 18) + return false; + break; + default: + break; + } + + return true; + } + + bool SetBossState(uint32 type, EncounterState state) override + { + if (!InstanceScript::SetBossState(type, state)) return false; - } - zuramatDead = false; - return true; - } - - void Update(uint32 diff) override - { - if (!instance->HavePlayers()) - return; - - // portals should spawn if other portal is dead and doors are closed - if (bActive && uiMainEventPhase == IN_PROGRESS) - { - if (uiActivationTimer < diff) + switch (type) { - AddWave(); - bActive = false; - // 1 minute waiting time after each boss fight - uiActivationTimer = (uiWaveCount == 6 || uiWaveCount == 12) ? 60000 : 5000; - } else uiActivationTimer -= diff; + case DATA_1ST_BOSS: + if (state == DONE) + UpdateEncounterState(ENCOUNTER_CREDIT_KILL_CREATURE, NPC_EREKEM, nullptr); + break; + case DATA_2ND_BOSS: + if (state == DONE) + UpdateEncounterState(ENCOUNTER_CREDIT_KILL_CREATURE, NPC_MORAGG, nullptr); + break; + case DATA_CYANIGOSA: + if (state == DONE) + SetData(DATA_MAIN_EVENT_STATE, DONE); + break; + case DATA_MORAGG: + case DATA_EREKEM: + case DATA_ICHORON: + case DATA_LAVANTHOR: + case DATA_XEVOZZ: + case DATA_ZURAMAT: + // this won't work correctly because bossstate was initializd with TO_BE_DECIDED + if (WaveCount == 6) + SetBossState(DATA_1ST_BOSS, state); + else if (WaveCount == 12) + SetBossState(DATA_2ND_BOSS, state); + + if (state == DONE) + SetData(DATA_WAVE_COUNT, WaveCount + 1); + break; + default: + break; + } + + return true; } - // if main event is in progress and players have wiped then reset instance - if (uiMainEventPhase == IN_PROGRESS && CheckWipe()) + void SetData(uint32 type, uint32 data) override { - SetData(DATA_REMOVE_NPC, 1); - StartBossEncounter(uiFirstBoss, false); - StartBossEncounter(uiSecondBoss, false); + switch (type) + { + case DATA_WAVE_COUNT: + WaveCount = data; + if (WaveCount) + { + Scheduler.Schedule(Seconds(IsBossWave(WaveCount - 1) ? 45 : 5), [this](TaskContext /*task*/) + { + AddWave(); + }); + } + break; + case DATA_DOOR_INTEGRITY: + DoorIntegrity = data; + Defenseless = false; + DoUpdateWorldState(WORLD_STATE_VH_PRISON_STATE, DoorIntegrity); + break; + case DATA_START_BOSS_ENCOUNTER: + switch (WaveCount) + { + case 6: + StartBossEncounter(FirstBossId); + break; + case 12: + StartBossEncounter(SecondBossId); + break; + } + break; + case DATA_MAIN_EVENT_STATE: + EventState = data; + if (data == IN_PROGRESS) // Start event + { + DoUpdateWorldState(WORLD_STATE_VH_WAVE_COUNT, WaveCount); + DoUpdateWorldState(WORLD_STATE_VH_PRISON_STATE, DoorIntegrity); + DoUpdateWorldState(WORLD_STATE_VH_SHOW, 1); - SetData(DATA_MAIN_DOOR, GO_STATE_ACTIVE); - SetData(DATA_WAVE_COUNT, 0); - uiMainEventPhase = NOT_STARTED; - uiActivationTimer = 5000; + WaveCount = 1; + Scheduler.Async(std::bind(&instance_violet_hold_InstanceMapScript::AddWave, this)); - for (int i = 0; i < 4; ++i) - if (GameObject* crystal = instance->GetGameObject(uiActivationCrystal[i])) - crystal->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); + for (uint8 i = 0; i < ActivationCrystalCount; ++i) + if (GameObject* crystal = instance->GetGameObject(ActivationCrystalGUIDs[i])) + crystal->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); + } + else if (data == NOT_STARTED) + { + if (GameObject* mainDoor = GetGameObject(DATA_MAIN_DOOR)) + { + mainDoor->SetGoState(GO_STATE_ACTIVE); + mainDoor->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_LOCKED); + } + DoUpdateWorldState(WORLD_STATE_VH_SHOW, 0); + DoUpdateWorldState(WORLD_STATE_VH_WAVE_COUNT, WaveCount); + DoUpdateWorldState(WORLD_STATE_VH_PRISON_STATE, DoorIntegrity); + + for (uint8 i = 0; i < ActivationCrystalCount; ++i) + if (GameObject* crystal = instance->GetGameObject(ActivationCrystalGUIDs[i])) + crystal->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); + } + else if (data == DONE) + { + if (GameObject* mainDoor = GetGameObject(DATA_MAIN_DOOR)) + { + mainDoor->SetGoState(GO_STATE_ACTIVE); + mainDoor->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_LOCKED); + } + + DoUpdateWorldState(WORLD_STATE_VH_SHOW, 0); + + for (uint8 i = 0; i < ActivationCrystalCount; ++i) + if (GameObject* crystal = instance->GetGameObject(ActivationCrystalGUIDs[i])) + crystal->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); + + if (Creature* sinclari = GetCreature(DATA_SINCLARI)) + sinclari->AI()->DoAction(ACTION_SINCLARI_OUTRO); + } + break; + case DATA_HANDLE_CELLS: + HandleCells(data, false); + break; + } + } + + uint32 GetData(uint32 type) const override + { + switch (type) + { + case DATA_1ST_BOSS: + return FirstBossId; + case DATA_2ND_BOSS: + return SecondBossId; + case DATA_MAIN_EVENT_STATE: + return EventState; + case DATA_WAVE_COUNT: + return WaveCount; + case DATA_DOOR_INTEGRITY: + return DoorIntegrity; + case DATA_DEFENSELESS: + return Defenseless ? 1 : 0; + default: + break; + } + + return 0; + } + + ObjectGuid GetGuidData(uint32 type) const override + { + switch (type) + { + case DATA_EREKEM_GUARD_1: + case DATA_EREKEM_GUARD_2: + return ErekemGuardGUIDs[type - DATA_EREKEM_GUARD_1]; + default: + break; + } + + return InstanceScript::GetGuidData(type); + } + + void SpawnPortal() + { + LastPortalLocation = (LastPortalLocation + urand(1, EncouterPortalsCount - 1)) % (EncouterPortalsCount); if (Creature* sinclari = GetCreature(DATA_SINCLARI)) { - sinclari->SetVisible(true); - - std::list GuardList; - sinclari->GetCreatureListWithEntryInGrid(GuardList, NPC_VIOLET_HOLD_GUARD, 40.0f); - if (!GuardList.empty()) + if (LastPortalLocation < PortalPositionsSize) { - for (Creature* guard : GuardList) + if (Creature* portal = sinclari->SummonCreature(NPC_TELEPORTATION_PORTAL, PortalPositions[LastPortalLocation], TEMPSUMMON_CORPSE_DESPAWN)) + portal->AI()->SetData(DATA_PORTAL_LOCATION, LastPortalLocation); + } + else + { + if (Creature* portal = sinclari->SummonCreature(NPC_TELEPORTATION_PORTAL_ELITE, PortalElitePositions[LastPortalLocation - PortalPositionsSize], TEMPSUMMON_CORPSE_DESPAWN)) + portal->AI()->SetData(DATA_PORTAL_LOCATION, LastPortalLocation); + } + } + } + + void HandleCells(uint8 bossId, bool open = true) + { + switch (bossId) + { + case DATA_MORAGG: + HandleGameObject(GetObjectGuid(DATA_MORAGG_CELL), open); + break; + case DATA_EREKEM: + HandleGameObject(GetObjectGuid(DATA_EREKEM_CELL), open); + HandleGameObject(GetObjectGuid(DATA_EREKEM_LEFT_GUARD_CELL), open); + HandleGameObject(GetObjectGuid(DATA_EREKEM_RIGHT_GUARD_CELL), open); + break; + case DATA_ICHORON: + HandleGameObject(GetObjectGuid(DATA_ICHORON_CELL), open); + break; + case DATA_LAVANTHOR: + HandleGameObject(GetObjectGuid(DATA_LAVANTHOR_CELL), open); + break; + case DATA_XEVOZZ: + HandleGameObject(GetObjectGuid(DATA_XEVOZZ_CELL), open); + break; + case DATA_ZURAMAT: + HandleGameObject(GetObjectGuid(DATA_ZURAMAT_CELL), open); + break; + default: + break; + } + } + + void StartBossEncounter(uint8 bossId) + { + switch (bossId) + { + case DATA_MORAGG: + Scheduler.Schedule(Seconds(2), [this](TaskContext task) { - guard->SetVisible(true); - guard->SetReactState(REACT_AGGRESSIVE); - guard->GetMotionMaster()->MovePoint(1, guard->GetHomePosition()); + if (Creature* moragg = GetCreature(DATA_MORAGG)) + { + moragg->PlayDirectSound(SOUND_MORAGG_SPAWN); + moragg->CastSpell(moragg, SPELL_MORAGG_EMOTE_ROAR); + } + + task.Schedule(Seconds(3), [this](TaskContext task) + { + if (Creature* moragg = GetCreature(DATA_MORAGG)) + moragg->GetMotionMaster()->MoveSmoothPath(POINT_INTRO, MoraggPath, MoraggPathSize, true); + + task.Schedule(Seconds(8), [this](TaskContext /*task*/) + { + if (Creature* moragg = GetCreature(DATA_MORAGG)) + { + moragg->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC); + moragg->AI()->DoZoneInCombat(moragg, 200.0f); + } + }); + }); + }); + break; + case DATA_EREKEM: + Scheduler.Schedule(Seconds(3), [this](TaskContext task) + { + if (Creature* erekem = GetCreature(DATA_EREKEM)) + erekem->AI()->Talk(SAY_EREKEM_SPAWN); + + task.Schedule(Seconds(5), [this](TaskContext task) + { + if (Creature* erekem = GetCreature(DATA_EREKEM)) + erekem->GetMotionMaster()->MoveSmoothPath(POINT_INTRO, ErekemPath, ErekemPathSize, true); + + if (Creature* guard = instance->GetCreature(GetGuidData(DATA_EREKEM_GUARD_1))) + guard->GetMotionMaster()->MoveSmoothPath(POINT_INTRO, ErekemGuardLeftPath, ErekemGuardLeftPathSize, true); + if (Creature* guard = instance->GetCreature(GetGuidData(DATA_EREKEM_GUARD_2))) + guard->GetMotionMaster()->MoveSmoothPath(POINT_INTRO, ErekemGuardRightPath, ErekemGuardRightPathSize, true); + + task.Schedule(Seconds(6), [this](TaskContext task) + { + if (Creature* erekem = GetCreature(DATA_EREKEM)) + erekem->HandleEmoteCommand(EMOTE_ONESHOT_ROAR); + + task.Schedule(Seconds(1), [this](TaskContext /*task*/) + { + for (uint32 i = DATA_EREKEM_GUARD_1; i <= DATA_EREKEM_GUARD_2; ++i) + { + if (Creature* guard = instance->GetCreature(GetGuidData(i))) + guard->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC); + } + + if (Creature* erekem = GetCreature(DATA_EREKEM)) + { + erekem->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC); + erekem->AI()->DoZoneInCombat(erekem, 200.0f); + } + }); + }); + }); + }); + break; + case DATA_ICHORON: + Scheduler.Schedule(Seconds(2), [this](TaskContext task) + { + if (Creature* ichoron = GetCreature(DATA_ICHORON)) + ichoron->AI()->Talk(SAY_ICHORON_SPAWN); + + task.Schedule(Seconds(3), [this](TaskContext task) + { + if (Creature* ichoron = GetCreature(DATA_ICHORON)) + ichoron->GetMotionMaster()->MoveSmoothPath(POINT_INTRO, IchoronPath, IchoronPathSize, true); + + task.Schedule(Seconds(14), [this](TaskContext /*task*/) + { + if (Creature* ichoron = GetCreature(DATA_ICHORON)) + { + ichoron->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC); + ichoron->AI()->DoZoneInCombat(ichoron, 200.0f); + } + }); + }); + }); + break; + case DATA_LAVANTHOR: + Scheduler.Schedule(Seconds(1), [this](TaskContext task) + { + if (Creature* lavanthor = GetCreature(DATA_LAVANTHOR)) + lavanthor->CastSpell(lavanthor, SPELL_LAVANTHOR_SPECIAL_UNARMED); + + task.Schedule(Seconds(3), [this](TaskContext task) + { + if (Creature* lavanthor = GetCreature(DATA_LAVANTHOR)) + lavanthor->GetMotionMaster()->MoveSmoothPath(POINT_INTRO, LavanthorPath, LavanthorPathSize, true); + + task.Schedule(Seconds(8), [this](TaskContext /*task*/) + { + if (Creature* lavanthor = GetCreature(DATA_LAVANTHOR)) + { + lavanthor->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC); + lavanthor->AI()->DoZoneInCombat(lavanthor, 200.0f); + } + }); + }); + }); + break; + case DATA_XEVOZZ: + Scheduler.Schedule(Seconds(2), [this](TaskContext task) + { + if (Creature* xevozz = GetCreature(DATA_XEVOZZ)) + xevozz->AI()->Talk(SAY_XEVOZZ_SPAWN); + + task.Schedule(Seconds(3), [this](TaskContext task) + { + if (Creature* xevozz = GetCreature(DATA_XEVOZZ)) + xevozz->HandleEmoteCommand(EMOTE_ONESHOT_TALK_NO_SHEATHE); + + task.Schedule(Seconds(4), [this](TaskContext task) + { + if (Creature* xevozz = GetCreature(DATA_XEVOZZ)) + xevozz->GetMotionMaster()->MoveSmoothPath(POINT_INTRO, XevozzPath, XevozzPathSize, true); + + task.Schedule(Seconds(4), [this](TaskContext /*task*/) + { + if (Creature* xevozz = GetCreature(DATA_XEVOZZ)) + { + xevozz->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC); + xevozz->AI()->DoZoneInCombat(xevozz, 200.0f); + } + }); + }); + }); + }); + break; + case DATA_ZURAMAT: + Scheduler.Schedule(Seconds(2), [this](TaskContext task) + { + if (Creature* zuramat = GetCreature(DATA_ZURAMAT)) + { + zuramat->CastSpell(zuramat, SPELL_ZURAMAT_COSMETIC_CHANNEL_OMNI); + zuramat->AI()->Talk(SAY_ZURAMAT_SPAWN); + } + + task.Schedule(Seconds(6), [this](TaskContext task) + { + if (Creature* zuramat = GetCreature(DATA_ZURAMAT)) + zuramat->GetMotionMaster()->MoveSmoothPath(POINT_INTRO, ZuramatPath, ZuramatPathSize, true); + + task.Schedule(Seconds(4), [this](TaskContext /*task*/) + { + if (Creature* zuramat = GetCreature(DATA_ZURAMAT)) + { + zuramat->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC); + zuramat->AI()->DoZoneInCombat(zuramat, 200.0f); + } + }); + }); + }); + break; + default: + return; + } + + HandleCells(bossId); + } + + void ResetBossEncounter(uint8 bossId) + { + if (bossId < DATA_CYANIGOSA || bossId > DATA_ZURAMAT) + return; + + Creature* boss = GetCreature(bossId); + if (!boss) + return; + + switch (bossId) + { + case DATA_CYANIGOSA: + boss->DespawnOrUnsummon(); + break; + case DATA_EREKEM: + for (uint32 i = DATA_EREKEM_GUARD_1; i <= DATA_EREKEM_GUARD_2; ++i) + { + if (Creature* guard = instance->GetCreature(GetGuidData(i))) + { + if (guard->isDead()) + guard->Respawn(); + + if (GetBossState(bossId) == DONE) + UpdateKilledBoss(guard); + + guard->GetMotionMaster()->MoveTargetedHome(); + guard->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC); + } } - } - sinclari->GetMotionMaster()->MovePoint(1, sinclari->GetHomePosition()); - sinclari->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + // no break + default: + if (boss->isDead()) + { + // respawn and update to a placeholder npc to avoid be looted again + boss->Respawn(); + UpdateKilledBoss(boss); + } + + boss->GetMotionMaster()->MoveTargetedHome(); + boss->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC); + break; } } - // Cyanigosa is spawned but not tranformed, prefight event - Creature* cyanigosa = GetCreature(DATA_CYANIGOSA); - if (cyanigosa && !cyanigosa->HasAura(CYANIGOSA_SPELL_TRANSFORM)) + void AddWave() { - if (uiCyanigosaEventTimer <= diff) + DoUpdateWorldState(WORLD_STATE_VH_WAVE_COUNT, WaveCount); + + switch (WaveCount) { - switch (uiCyanigosaEventPhase) + case 6: + if (FirstBossId == 0) + FirstBossId = urand(DATA_MORAGG, DATA_ZURAMAT); + if (Creature* sinclari = GetCreature(DATA_SINCLARI)) + { + sinclari->SummonCreature(NPC_TELEPORTATION_PORTAL_INTRO, PortalIntroPositions[3], TEMPSUMMON_TIMED_DESPAWN, 3000); + sinclari->SummonCreature(NPC_SABOTEOUR, SaboteurSpawnLocation, TEMPSUMMON_DEAD_DESPAWN); + } + break; + case 12: + if (SecondBossId == 0) + do + { + SecondBossId = urand(DATA_MORAGG, DATA_ZURAMAT); + } while (SecondBossId == FirstBossId); + if (Creature* sinclari = GetCreature(DATA_SINCLARI)) + { + sinclari->SummonCreature(NPC_TELEPORTATION_PORTAL_INTRO, PortalIntroPositions[3], TEMPSUMMON_TIMED_DESPAWN, 3000); + sinclari->SummonCreature(NPC_SABOTEOUR, SaboteurSpawnLocation, TEMPSUMMON_DEAD_DESPAWN); + } + break; + case 18: + if (Creature* sinclari = GetCreature(DATA_SINCLARI)) + { + sinclari->SummonCreature(NPC_TELEPORTATION_PORTAL_INTRO, PortalIntroPositions[4], TEMPSUMMON_TIMED_DESPAWN, 6000); + if (Creature* cyanigosa = sinclari->SummonCreature(NPC_CYANIGOSA, CyanigosaSpawnLocation, TEMPSUMMON_DEAD_DESPAWN)) + cyanigosa->CastSpell(cyanigosa, SPELL_CYANIGOSA_ARCANE_POWER_STATE, true); + ScheduleCyanigosaIntro(); + } + break; + default: + SpawnPortal(); + break; + } + } + + void WriteSaveDataMore(std::ostringstream& data) override + { + data << FirstBossId << ' ' << SecondBossId; + } + + void ReadSaveDataMore(std::istringstream& data) override + { + data >> FirstBossId; + data >> SecondBossId; + } + + bool CheckWipe() const + { + Map::PlayerList const& players = instance->GetPlayers(); + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + { + Player* player = itr->GetSource(); + if (player->IsGameMaster()) + continue; + + if (player->IsAlive()) + return false; + } + + return true; + } + + void UpdateKilledBoss(Creature* boss) + { + switch (boss->GetEntry()) + { + case NPC_XEVOZZ: + boss->UpdateEntry(NPC_DUMMY_XEVOZZ); + break; + case NPC_LAVANTHOR: + boss->UpdateEntry(NPC_DUMMY_LAVANTHOR); + break; + case NPC_ICHORON: + boss->UpdateEntry(NPC_DUMMY_ICHORON); + break; + case NPC_ZURAMAT: + boss->UpdateEntry(NPC_DUMMY_ZURAMAT); + break; + case NPC_EREKEM: + boss->UpdateEntry(NPC_DUMMY_EREKEM); + break; + case NPC_MORAGG: + boss->UpdateEntry(NPC_DUMMY_MORAGG); + break; + case NPC_EREKEM_GUARD: + boss->UpdateEntry(NPC_DUMMY_EREKEM_GUARD); + break; + default: + break; + } + } + + void Update(uint32 diff) override + { + if (!instance->HavePlayers()) + return; + + // if main event is in progress and players have wiped then reset instance + if ((EventState == IN_PROGRESS && CheckWipe()) || EventState == FAIL) + { + ResetBossEncounter(FirstBossId); + ResetBossEncounter(SecondBossId); + ResetBossEncounter(DATA_CYANIGOSA); + + WaveCount = 0; + DoorIntegrity = 100; + Defenseless = true; + SetData(DATA_MAIN_EVENT_STATE, NOT_STARTED); + + Scheduler.CancelAll(); + + if (Creature* sinclari = GetCreature(DATA_SINCLARI)) + sinclari->AI()->EnterEvadeMode(); + } + + Scheduler.Update(diff); + + if (EventState == IN_PROGRESS) + { + // if door is destroyed, event is failed + if (!GetData(DATA_DOOR_INTEGRITY)) + EventState = FAIL; + } + } + + void ScheduleCyanigosaIntro() + { + Scheduler.Schedule(Seconds(2), [this](TaskContext task) + { + if (Creature* cyanigosa = GetCreature(DATA_CYANIGOSA)) + cyanigosa->AI()->Talk(SAY_CYANIGOSA_SPAWN); + + task.Schedule(Seconds(6), [this](TaskContext task) { - case 1: - cyanigosa->CastSpell(cyanigosa, CYANIGOSA_BLUE_AURA, false); - cyanigosa->AI()->Talk(CYANIGOSA_SAY_SPAWN); - uiCyanigosaEventTimer = 7*IN_MILLISECONDS; - ++uiCyanigosaEventPhase; - break; - case 2: - cyanigosa->GetMotionMaster()->MoveJump(MiddleRoomLocation.GetPositionX(), MiddleRoomLocation.GetPositionY(), MiddleRoomLocation.GetPositionZ(), 10.0f, 20.0f); - cyanigosa->CastSpell(cyanigosa, CYANIGOSA_BLUE_AURA, false); - uiCyanigosaEventTimer = 7*IN_MILLISECONDS; - ++uiCyanigosaEventPhase; - break; - case 3: - cyanigosa->RemoveAurasDueToSpell(CYANIGOSA_BLUE_AURA); - cyanigosa->CastSpell(cyanigosa, CYANIGOSA_SPELL_TRANSFORM, 0); - cyanigosa->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_NON_ATTACKABLE); - cyanigosa->SetReactState(REACT_AGGRESSIVE); - uiCyanigosaEventTimer = 2*IN_MILLISECONDS; - ++uiCyanigosaEventPhase; - break; - case 4: - uiCyanigosaEventPhase = 0; - break; - } - } else uiCyanigosaEventTimer -= diff; + if (Creature* cyanigosa = GetCreature(DATA_CYANIGOSA)) + cyanigosa->GetMotionMaster()->MoveJump(CyanigosaJumpLocation, 10.0f, 27.44744f); + + task.Schedule(Seconds(7), [this](TaskContext /*task*/) + { + if (Creature* cyanigosa = GetCreature(DATA_CYANIGOSA)) + { + cyanigosa->RemoveAurasDueToSpell(SPELL_CYANIGOSA_ARCANE_POWER_STATE); + cyanigosa->CastSpell(cyanigosa, SPELL_CYANIGOSA_TRANSFORM, true); + cyanigosa->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC); + } + }); + }); + }); } - // if there are NPCs in front of the prison door, which are casting the door seal spell and doors are active - if (GetData(DATA_NPC_PRESENCE_AT_DOOR) && uiMainEventPhase == IN_PROGRESS) + void ProcessEvent(WorldObject* /*go*/, uint32 eventId) override { - // if door integrity is > 0 then decrase it's integrity state - if (GetData(DATA_DOOR_INTEGRITY)) + if (eventId == EVENT_ACTIVATE_CRYSTAL) { - if (uiDoorSpellTimer < diff) - { - SetData(DATA_DOOR_INTEGRITY, GetData(DATA_DOOR_INTEGRITY)-1); - uiDoorSpellTimer =2000; - } else uiDoorSpellTimer -= diff; - } - // else set door state to active (means door will open and group have failed to sustain mob invasion on the door) - else - { - SetData(DATA_MAIN_DOOR, GO_STATE_ACTIVE); - uiMainEventPhase = FAIL; + instance->SummonCreature(NPC_DEFENSE_SYSTEM, DefenseSystemLocation); + Defenseless = false; } } - } - void ActivateCrystal() - { - // just to make things easier we'll get the gameobject from the map - GameObject* invoker = instance->GetGameObject(uiActivationCrystal[0]); - if (!invoker) - return; - - SpellInfo const* spellInfoLightning = sSpellMgr->GetSpellInfo(SPELL_ARCANE_LIGHTNING); - if (!spellInfoLightning) - return; - - // the orb - TempSummon* trigger = invoker->SummonCreature(NPC_DEFENSE_SYSTEM, ArcaneSphere, TEMPSUMMON_MANUAL_DESPAWN, 0); - if (!trigger) - return; - - // visuals - trigger->CastSpell(trigger, spellInfoLightning, true, 0, 0, trigger->GetGUID()); - - // Kill all mobs registered with SetGuidData(ADD_TRASH_MOB) - for (GuidSet::const_iterator itr = trashMobs.begin(); itr != trashMobs.end();) + static bool IsBossWave(uint8 wave) { - Creature* creature = instance->GetCreature(*itr); - // Increment the iterator before killing the creature because the kill will remove itr from trashMobs - ++itr; - if (creature && creature->IsAlive()) - trigger->Kill(creature); + return wave && ((wave % 6) == 0); } - } - void ProcessEvent(WorldObject* /*go*/, uint32 uiEventId) override + protected: + TaskScheduler Scheduler; + + static uint8 const ErekemGuardCount = 2; + ObjectGuid ErekemGuardGUIDs[ErekemGuardCount]; + + static uint8 const ActivationCrystalCount = 5; + ObjectGuid ActivationCrystalGUIDs[ActivationCrystalCount]; + + uint32 FirstBossId; + uint32 SecondBossId; + + uint8 DoorIntegrity; + uint8 WaveCount; + uint8 EventState; + uint8 LastPortalLocation; + + bool Defenseless; + }; + + InstanceScript* GetInstanceScript(InstanceMap* map) const override { - switch (uiEventId) - { - case EVENT_ACTIVATE_CRYSTAL: - bCrystalActivated = true; // Activation by player's will throw event signal - ActivateCrystal(); - break; - } + return new instance_violet_hold_InstanceMapScript(map); } - }; - - InstanceScript* GetInstanceScript(InstanceMap* map) const override - { - return new instance_violet_hold_InstanceMapScript(map); - } }; void AddSC_instance_violet_hold() diff --git a/src/server/scripts/Northrend/VioletHold/violet_hold.cpp b/src/server/scripts/Northrend/VioletHold/violet_hold.cpp index b05da4b994c..fdb4c4dc3fc 100644 --- a/src/server/scripts/Northrend/VioletHold/violet_hold.cpp +++ b/src/server/scripts/Northrend/VioletHold/violet_hold.cpp @@ -15,36 +15,41 @@ * with this program. If not, see . */ +#include "Player.h" #include "ScriptMgr.h" #include "ScriptedCreature.h" #include "ScriptedGossip.h" #include "ScriptedEscortAI.h" -#include "violet_hold.h" -#include "Player.h" -#include "SpellAuras.h" #include "SpellAuraEffects.h" #include "SpellScript.h" +#include "violet_hold.h" -#define GOSSIP_START_EVENT "Get your people to safety, we'll keep the Blue Dragonflight's forces at bay." -#define GOSSIP_ITEM_1 "Activate the crystals when we get in trouble, right" -#define GOSSIP_I_WANT_IN "I'm not fighting, so send me in now!" -#define SAY_EVENT_LOCK "I'm locking the door. Good luck, and thank you for doing this." -#define SPAWN_TIME 20000 +/* + * TODO: + * - add missing trash emotes + */ -enum PortalCreatures +enum PortalCreatureIds { NPC_AZURE_INVADER_1 = 30661, - NPC_AZURE_INVADER_2 = 30961, NPC_AZURE_SPELLBREAKER_1 = 30662, - NPC_AZURE_SPELLBREAKER_2 = 30962, NPC_AZURE_BINDER_1 = 30663, - NPC_AZURE_BINDER_2 = 30918, NPC_AZURE_MAGE_SLAYER_1 = 30664, + NPC_VETERAN_MAGE_HUNTER = 30665, + NPC_AZURE_CAPTAIN_1 = 30666, + NPC_AZURE_SORCEROR_1 = 30667, + NPC_AZURE_RAIDER_1 = 30668, + + NPC_AZURE_BINDER_2 = 30918, + NPC_AZURE_INVADER_2 = 30961, + NPC_AZURE_SPELLBREAKER_2 = 30962, NPC_AZURE_MAGE_SLAYER_2 = 30963, - NPC_AZURE_CAPTAIN = 30666, - NPC_AZURE_SORCEROR = 30667, - NPC_AZURE_RAIDER = 30668, - NPC_AZURE_STALKER = 32191 + NPC_AZURE_BINDER_3 = 31007, + NPC_AZURE_INVADER_3 = 31008, + NPC_AZURE_SPELLBREAKER_3 = 31009, + NPC_AZURE_MAGE_SLAYER_3 = 31010, + NPC_AZURE_RAIDER_2 = 31118, + NPC_AZURE_STALKER_1 = 32191 }; enum AzureInvaderSpells @@ -103,8 +108,8 @@ enum AzureStalkerSpells enum AzureSaboteurSpells { - SABOTEUR_SHIELD_DISRUPTION = 58291, - SABOTEUR_SHIELD_EFFECT = 45775 + SPELL_SHIELD_DISRUPTION = 58291, + SPELL_TELEPORT_VISUAL = 51347 }; enum TrashDoorSpell @@ -112,19 +117,45 @@ enum TrashDoorSpell SPELL_DESTROY_DOOR_SEAL = 58040 }; -enum Spells +enum DefenseSystemSpells { - SPELL_PORTAL_CHANNEL = 58012, - SPELL_CRYSTAL_ACTIVATION = 57804, // visual effect - SPELL_ARCANE_SPHERE_PASSIVE = 44263 + SPELL_ARCANE_LIGHTNING_DAMAGE = 57912, + SPELL_ARCANE_LIGHTNING_INSTAKILL = 58152, + SPELL_ARCANE_LIGHTNING_DUMMY = 57930 +}; + +enum MiscSpells +{ + SPELL_PORTAL_PERIODIC = 58008, + SPELL_PORTAL_CHANNEL = 58012, + SPELL_CRYSTAL_ACTIVATION = 57804, + + SPELL_TELEPORT_PLAYER = 62138, + SPELL_TELEPORT_PLAYER_EFFECT = 62139 +}; + +enum MiscData +{ + DATA_PORTAL_PERIODIC_TICK = 1 }; enum Sinclari { - SAY_SINCLARI_1 = 0 + // Sinclari + SAY_SINCLARI_INTRO_1 = 0, + SAY_SINCLARI_INTRO_2 = 1, + SAY_SINCLARI_OUTRO = 2, + + GOSSIP_MENU_START_ENCOUNTER = 9998, + GOSSIP_MENU_SEND_ME_IN = 10275, + + // Sinclari Trigger + SAY_SINCLARI_ELITE_SQUAD = 0, + SAY_SINCLARI_PORTAL_GUARDIAN = 1, + SAY_SINCLARI_PORTAL_KEEPER = 2 }; -float FirstPortalWPs [6][3] = +G3D::Vector3 const FirstPortalWPs[6] = { {1877.670288f, 842.280273f, 43.333591f}, {1877.338867f, 834.615356f, 38.762287f}, @@ -135,7 +166,7 @@ float FirstPortalWPs [6][3] = //{1825.736084f, 807.305847f, 44.363785f} }; -float SecondPortalFirstWPs [9][3] = +G3D::Vector3 const SecondPortalFirstWPs[9] = { {1902.561401f, 853.334656f, 47.106117f}, {1895.486084f, 855.376404f, 44.334591f}, @@ -149,7 +180,7 @@ float SecondPortalFirstWPs [9][3] = //{1825.736084f, 807.305847f, 44.363785f} }; -float SecondPortalSecondWPs [8][3] = +G3D::Vector3 const SecondPortalSecondWPs[8] = { {1929.392212f, 837.614990f, 47.136166f}, {1928.290649f, 824.750427f, 45.474411f}, @@ -162,7 +193,7 @@ float SecondPortalSecondWPs [8][3] = //{1825.736084f, 807.305847f, 44.363785f} }; -float ThirdPortalWPs [8][3] = +G3D::Vector3 const ThirdPortalWPs[8] = { {1934.049438f, 815.778503f, 52.408699f}, {1928.290649f, 824.750427f, 45.474411f}, @@ -175,7 +206,7 @@ float ThirdPortalWPs [8][3] = //{1825.736084f, 807.305847f, 44.363785f} }; -float FourthPortalWPs [9][3] = +G3D::Vector3 const FourthPortalWPs[9] = { {1921.658447f, 761.657043f, 50.866741f}, {1910.559814f, 755.780457f, 47.701447f}, @@ -189,7 +220,7 @@ float FourthPortalWPs [9][3] = //{1827.100342f, 801.605957f, 44.363358f} }; -float FifthPortalWPs [6][3] = +G3D::Vector3 const FifthPortalWPs[6] = { {1887.398804f, 763.633240f, 47.666851f}, {1879.020386f, 775.396973f, 38.705990f}, @@ -200,7 +231,7 @@ float FifthPortalWPs [6][3] = //{1827.100342f, 801.605957f, 44.363358f} }; -float SixthPoralWPs [4][3] = +G3D::Vector3 const SixthPoralWPs[4] = { {1888.861084f, 805.074768f, 38.375790f}, {1869.793823f, 804.135804f, 38.647018f}, @@ -209,1308 +240,1188 @@ float SixthPoralWPs [4][3] = //{1826.889648f, 803.929993f, 44.363239f} }; -const float SaboteurFinalPos1[3][3] = +G3D::Vector3 const DefaultPortalWPs[1] = { - {1892.502319f, 777.410767f, 38.630402f}, - {1891.165161f, 762.969421f, 47.666920f}, - {1893.168091f, 740.919189f, 47.666920f} -}; -const float SaboteurFinalPos2[3][3] = -{ - {1882.242676f, 834.818726f, 38.646786f}, - {1879.220825f, 842.224854f, 43.333641f}, - {1873.842896f, 863.892456f, 43.333641f} -}; -const float SaboteurFinalPos3[2][3] = -{ - {1904.298340f, 792.400391f, 38.646782f}, - {1935.716919f, 758.437073f, 30.627895f} -}; -const float SaboteurFinalPos4[3] = -{ - 1855.006104f, 760.641724f, 38.655266f -}; -const float SaboteurFinalPos5[3] = -{ - 1906.667358f, 841.705566f, 38.637894f -}; -const float SaboteurFinalPos6[5][3] = -{ - {1911.437012f, 821.289246f, 38.684128f}, - {1920.734009f, 822.978027f, 41.525414f}, - {1928.262939f, 830.836609f, 44.668266f}, - {1929.338989f, 837.593933f, 47.137596f}, - {1931.063354f, 848.468445f, 47.190434f} - }; - -const Position PortalLocation[] = -{ - { 1877.51f, 850.104f, 44.6599f, 4.7822f }, // WP 1 - { 1936.07f, 803.198f, 53.3749f, 3.12414f }, // WP 3 - { 1890.64f, 753.471f, 48.7224f, 1.71042f }, // WP 5 + { 1843.567017f, 804.288208f, 44.139091f } }; -#define MAX_PRE_EVENT_PORTAL 3 +uint32 const SaboteurMoraggPathSize = 5; +G3D::Vector3 const SaboteurMoraggPath[SaboteurMoraggPathSize] = // sniff +{ + { 1886.251f, 803.0743f, 38.42326f }, + { 1885.71f, 799.8929f, 38.37241f }, + { 1889.505f, 762.3288f, 47.66684f }, + { 1894.542f, 742.1829f, 47.66684f }, + { 1894.603f, 739.9231f, 47.66684f }, +}; -ObjectGuid preEventPortalGUID[MAX_PRE_EVENT_PORTAL] = { ObjectGuid::Empty }; +uint32 const SaboteurErekemPathSize = 5; +G3D::Vector3 const SaboteurErekemPath[SaboteurErekemPathSize] = // sniff +{ + { 1886.251f, 803.0743f, 38.42326f }, + { 1881.047f, 829.6866f, 38.64856f }, + { 1877.585f, 844.6685f, 38.49014f }, + { 1876.085f, 851.6685f, 42.99014f }, + { 1873.747f, 864.1373f, 43.33349f } +}; -const Position MovePosition = { 1806.955566f, 803.851807f, 44.363323f, 0.0f }; -const Position playerTeleportPosition = { 1830.531006f, 803.939758f, 44.340508f, 6.281611f }; -const Position sinclariOutsidePosition = { 1820.429810f, 804.066040f, 44.363998f, 0.0f }; -const Position sinclariCrystalPosition = { 1828.868286f, 798.468811f, 44.363998f, 3.890467f }; +uint32 const SaboteurIchoronPathSize = 3; +G3D::Vector3 const SaboteurIchoronPath[SaboteurIchoronPathSize] = // sniff +{ + { 1886.251f, 803.0743f, 38.42326f }, + { 1888.672f, 801.2348f, 38.42305f }, + { 1901.987f, 793.3254f, 38.65126f } +}; + +uint32 const SaboteurLavanthorPathSize = 3; +G3D::Vector3 const SaboteurLavanthorPath[SaboteurLavanthorPathSize] = // sniff +{ + { 1886.251f, 803.0743f, 38.42326f }, + { 1867.925f, 778.8035f, 38.64702f }, + { 1853.304f, 759.0161f, 38.65761f } +}; + +uint32 const SaboteurXevozzPathSize = 4; +G3D::Vector3 const SaboteurXevozzPath[SaboteurXevozzPathSize] = // sniff +{ + { 1886.251f, 803.0743f, 38.42326f }, + { 1889.096f, 810.0487f, 38.43871f }, + { 1896.547f, 823.5473f, 38.72863f }, + { 1906.666f, 842.3111f, 38.63351f } +}; + +uint32 const SaboteurZuramatPathSize = 7; +G3D::Vector3 const SaboteurZuramatPath[SaboteurZuramatPathSize] = // sniff +{ + { 1886.251f, 803.0743f, 38.42326f }, + { 1889.69f, 807.0032f, 38.39914f }, + { 1906.91f, 818.2574f, 38.86596f }, + { 1929.03f, 824.2713f, 46.09165f }, + { 1928.441f, 842.8891f, 47.15078f }, + { 1927.454f, 851.6091f, 47.19094f }, + { 1927.947f, 852.2986f, 47.19637f } +}; + +Position const SinclariPositions[] = // sniff +{ + { 1829.142f, 798.219f, 44.36212f, 0.122173f }, // 0 - Crystal + { 1820.12f, 803.916f, 44.36466f, 0.0f }, // 1 - Outside + { 1816.185f, 804.0629f, 44.44799f, 3.176499f }, // 2 - Second Spawn Point + { 1827.886f, 804.0555f, 44.36467f, 0.0f } // 3 - Outro +}; + +Position const GuardsMovePosition = { 1802.099f, 803.7724f, 44.36466f, 0.0f }; // sniff class npc_sinclari_vh : public CreatureScript { -public: - npc_sinclari_vh() : CreatureScript("npc_sinclari_vh") { } + public: + npc_sinclari_vh() : CreatureScript("npc_sinclari_vh") { } - bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) override - { - player->PlayerTalkClass->ClearMenus(); - switch (action) + bool OnGossipHello(Player* player, Creature* creature) override { - case GOSSIP_ACTION_INFO_DEF+1: - player->CLOSE_GOSSIP_MENU(); - ENSURE_AI(npc_sinclari_vh::npc_sinclariAI, creature->AI())->uiPhase = 1; - if (InstanceScript* instance = creature->GetInstanceScript()) - instance->SetData(DATA_MAIN_EVENT_PHASE, SPECIAL); - break; - case GOSSIP_ACTION_INFO_DEF+2: - player->SEND_GOSSIP_MENU(13854, creature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+3: - player->NearTeleportTo(playerTeleportPosition.GetPositionX(), playerTeleportPosition.GetPositionY(), playerTeleportPosition.GetPositionZ(), playerTeleportPosition.GetOrientation(), true); - player->CLOSE_GOSSIP_MENU(); - break; - } - return true; - } - - bool OnGossipHello(Player* player, Creature* creature) override - { - if (InstanceScript* instance = creature->GetInstanceScript()) - { - switch (instance->GetData(DATA_MAIN_EVENT_PHASE)) + // override default gossip + if (InstanceScript* instance = creature->GetInstanceScript()) { - case NOT_STARTED: - case FAIL: // Allow to start event if not started or wiped - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_START_EVENT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - player->SEND_GOSSIP_MENU(13853, creature->GetGUID()); - break; - case IN_PROGRESS: // Allow to teleport inside if event is in progress - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_I_WANT_IN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); - player->SEND_GOSSIP_MENU(13853, creature->GetGUID()); - break; - default: - player->SEND_GOSSIP_MENU(13910, creature->GetGUID()); - } - } - return true; - } - - struct npc_sinclariAI : public ScriptedAI - { - npc_sinclariAI(Creature* creature) : ScriptedAI(creature) - { - Initialize(); - instance = creature->GetInstanceScript(); - } - - void Initialize() - { - uiPhase = 0; - uiTimer = 0; - } - - InstanceScript* instance; - - uint8 uiPhase; - uint32 uiTimer; - - void Reset() override - { - Initialize(); - - me->SetReactState(REACT_AGGRESSIVE); - for (uint8 i = 0; i < MAX_PRE_EVENT_PORTAL; i++) - if (TempSummon* summon = me->SummonCreature(NPC_TELEPORTATION_PORTAL, PortalLocation[i], TEMPSUMMON_MANUAL_DESPAWN)) - preEventPortalGUID[i] = summon->GetGUID(); - - std::list GuardList; - me->GetCreatureListWithEntryInGrid(GuardList, NPC_VIOLET_HOLD_GUARD, 40.0f); - if (!GuardList.empty()) - { - for (std::list::const_iterator itr = GuardList.begin(); itr != GuardList.end(); ++itr) + switch (instance->GetData(DATA_MAIN_EVENT_STATE)) { - if (Creature* pGuard = *itr) - { - pGuard->DisappearAndDie(); - pGuard->Respawn(); - pGuard->SetVisible(true); - pGuard->SetReactState(REACT_AGGRESSIVE); - } + case IN_PROGRESS: + player->PrepareGossipMenu(creature, GOSSIP_MENU_SEND_ME_IN, true); + player->SendPreparedGossip(creature); + return true; + case DONE: + return true; // NYI + case NOT_STARTED: + case FAIL: + default: + break; } } + + // load default gossip + return false; } - void UpdateAI(uint32 uiDiff) override + struct npc_sinclariAI : public ScriptedAI { - if (uiPhase) + npc_sinclariAI(Creature* creature) : ScriptedAI(creature), _summons(creature) { - if (uiTimer <= uiDiff) + _instance = creature->GetInstanceScript(); + } + + void Reset() override + { + _summons.DespawnAll(); + for (uint8 i = 0; i < PortalIntroCount; ++i) + if (Creature* summon = me->SummonCreature(NPC_TELEPORTATION_PORTAL_INTRO, PortalIntroPositions[i], TEMPSUMMON_MANUAL_DESPAWN)) + summon->AI()->SetData(DATA_PORTAL_LOCATION, i); + + me->SetVisible(true); + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + + std::list guardList; + me->GetCreatureListWithEntryInGrid(guardList, NPC_VIOLET_HOLD_GUARD, 100.0f); + for (Creature* guard : guardList) { - switch (uiPhase) + guard->Respawn(true); + guard->SetVisible(true); + guard->SetReactState(REACT_AGGRESSIVE); + guard->AI()->EnterEvadeMode(); + } + } + + void sGossipSelect(Player* player, uint32 menuId, uint32 gossipListId) override + { + if (menuId == GOSSIP_MENU_START_ENCOUNTER && gossipListId == 0) + { + me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + _instance->SetData(DATA_MAIN_EVENT_STATE, SPECIAL); + ScheduleIntro(); + player->PlayerTalkClass->SendCloseGossip(); + } + else if (menuId == GOSSIP_MENU_SEND_ME_IN && gossipListId == 0) + { + me->CastSpell(player, SPELL_TELEPORT_PLAYER, true); + player->PlayerTalkClass->SendCloseGossip(); + } + } + + void DoAction(int32 actionId) override + { + if (actionId == ACTION_SINCLARI_OUTRO) + { + me->SetVisible(true); + ScheduleOutro(); + } + } + + void UpdateAI(uint32 diff) override + { + _scheduler.Update(diff); + + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } + + void ScheduleIntro() + { + _scheduler.Schedule(Seconds(1), [this](TaskContext task) + { + switch (task.GetRepeatCounter()) { - case 1: + case 0: me->SetWalk(true); - me->GetMotionMaster()->MovePoint(0, sinclariCrystalPosition); - uiTimer = 1000; - uiPhase = 6; + me->GetMotionMaster()->MovePoint(0, SinclariPositions[0]); + task.Repeat(Seconds(1)); + break; + case 1: + me->HandleEmoteCommand(EMOTE_ONESHOT_USE_STANDING); + me->GetMap()->SummonCreature(NPC_DEFENSE_SYSTEM, DefenseSystemLocation); + task.Repeat(Seconds(3)); break; case 2: - { - me->SetFacingTo(me->GetOrientation() - 3.14f); - Talk(SAY_SINCLARI_1); - uiTimer = 1500; - uiPhase = 7; - break; - } - case 3: - { - std::list GuardList; - me->GetCreatureListWithEntryInGrid(GuardList, NPC_VIOLET_HOLD_GUARD, 40.0f); - if (!GuardList.empty()) - for (std::list::const_iterator itr = GuardList.begin(); itr != GuardList.end(); ++itr) + me->SetFacingTo(SinclariPositions[0].GetOrientation()); + Talk(SAY_SINCLARI_INTRO_1); + + task.Schedule(Seconds(1), [this](TaskContext /*task*/) + { + std::list guardList; + me->GetCreatureListWithEntryInGrid(guardList, NPC_VIOLET_HOLD_GUARD, 100.0f); + for (Creature* guard : guardList) { - if (Creature* pGuard = *itr) - { - pGuard->SetVisible(false); - } + guard->SetReactState(REACT_PASSIVE); + guard->SetWalk(false); + guard->GetMotionMaster()->MovePoint(0, GuardsMovePosition); } - uiTimer = 2000; - uiPhase = 4; + }); + + task.Repeat(Seconds(2)); + break; + case 3: + me->GetMotionMaster()->MovePoint(0, SinclariPositions[1]); + _summons.DespawnAll(); + task.Repeat(Seconds(5)); break; - } case 4: - me->GetMotionMaster()->MovePoint(0, sinclariOutsidePosition); - uiTimer = 4000; - uiPhase = 5; + me->SetFacingTo(SinclariPositions[1].GetOrientation()); + + task.Schedule(Seconds(1), [this](TaskContext /*task*/) + { + std::list guardList; + me->GetCreatureListWithEntryInGrid(guardList, NPC_VIOLET_HOLD_GUARD, 100.0f); + for (Creature* guard : guardList) + guard->SetVisible(false); + }); + + task.Repeat(Seconds(6)); break; case 5: - me->SetFacingTo(0.006673f); - me->Say(SAY_EVENT_LOCK, LANG_UNIVERSAL, me); // need to change to db say - me->SetReactState(REACT_PASSIVE); - uiTimer = 3000; - uiPhase = 8; + Talk(SAY_SINCLARI_INTRO_2); + task.Repeat(Seconds(4)); break; case 6: - me->GetMotionMaster()->MovementExpired(); - me->HandleEmoteCommand(EMOTE_STATE_USE_STANDING); - uiTimer = 2000; - uiPhase = 2; + me->HandleEmoteCommand(EMOTE_ONESHOT_TALK_NO_SHEATHE); + task.Repeat(Seconds(1)); break; case 7: - { - std::list creatures; - GetCreatureListWithEntryInGrid(creatures, me, NPC_TELEPORTATION_PORTAL, 200.0f); - GetCreatureListWithEntryInGrid(creatures, me, NPC_AZURE_BINDER_1, 200.0f); - GetCreatureListWithEntryInGrid(creatures, me, NPC_AZURE_MAGE_SLAYER_1, 200.0f); - GetCreatureListWithEntryInGrid(creatures, me, NPC_AZURE_INVADER_1, 200.0f); - DoCast(SPELL_CRYSTAL_ACTIVATION); - if (!creatures.empty()) + if (GameObject* mainDoor = _instance->GetGameObject(DATA_MAIN_DOOR)) { - for (std::list::iterator itr = creatures.begin(); itr != creatures.end(); ++itr) - (*itr)->DisappearAndDie(); + mainDoor->SetGoState(GO_STATE_READY); + mainDoor->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_LOCKED); } - uiTimer = 500; - uiPhase = 9; - } - break; + task.Repeat(Seconds(5)); + break; case 8: - instance->SetData(DATA_MAIN_EVENT_PHASE, IN_PROGRESS); - uiTimer = 0; - uiPhase = 0; + me->SetVisible(false); + task.Repeat(Seconds(1)); break; case 9: - { - std::list GuardList; - me->GetCreatureListWithEntryInGrid(GuardList, NPC_VIOLET_HOLD_GUARD, 40.0f); - if (!GuardList.empty()) - for (std::list::const_iterator itr = GuardList.begin(); itr != GuardList.end(); ++itr) - { - if (Creature* pGuard = *itr) - { - pGuard->SetReactState(REACT_PASSIVE); - pGuard->SetWalk(false); - pGuard->GetMotionMaster()->MovePoint(0, MovePosition); - } - } - uiTimer = 4000; - uiPhase = 3; - } - break; + _instance->SetData(DATA_MAIN_EVENT_STATE, IN_PROGRESS); + // [1] GUID: Full: 0xF1300077C202E6DD Type: Creature Entry: 30658 Low: 190173 + break; + default: + break; } - } - else uiTimer -= uiDiff; + }); } - if (!UpdateVictim()) - return; + void ScheduleOutro() + { + _scheduler.Schedule(Seconds(4), [this](TaskContext task) + { + Talk(SAY_SINCLARI_OUTRO); + me->GetMotionMaster()->MovePoint(0, SinclariPositions[3]); - DoMeleeAttackIfReady(); + task.Schedule(Seconds(10), [this](TaskContext /*task*/) + { + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + }); + }); + } + + void JustSummoned(Creature* summon) override + { + ScriptedAI::JustSummoned(summon); + _summons.Summon(summon); + } + + void SummonedCreatureDespawn(Creature* summon) override + { + _summons.Despawn(summon); + ScriptedAI::SummonedCreatureDespawn(summon); + } + + private: + InstanceScript* _instance; + TaskScheduler _scheduler; + + SummonList _summons; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetVioletHoldAI(creature); } - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI(creature); - } }; class npc_azure_saboteur : public CreatureScript { -public: - npc_azure_saboteur() : CreatureScript("npc_azure_saboteur") { } + public: + npc_azure_saboteur() : CreatureScript("npc_azure_saboteur") { } - struct npc_azure_saboteurAI : public npc_escortAI - { - npc_azure_saboteurAI(Creature* creature) : npc_escortAI(creature) + struct npc_azure_saboteurAI : public ScriptedAI { - instance = creature->GetInstanceScript(); - bHasGotMovingPoints = false; - uiBoss = 0; - Reset(); - } - - InstanceScript* instance; - bool bHasGotMovingPoints; - uint32 uiBoss; - - void Reset() override - { - if (!uiBoss) - uiBoss = instance->GetData(DATA_WAVE_COUNT) == 6 ? instance->GetData(DATA_FIRST_BOSS) : instance->GetData(DATA_SECOND_BOSS); - me->SetReactState(REACT_PASSIVE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_NON_ATTACKABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - } - - void WaypointReached(uint32 waypointId) override - { - switch (uiBoss) + npc_azure_saboteurAI(Creature* creature) : ScriptedAI(creature) { - case 1: - if (waypointId == 2) - FinishPointReached(); - break; - case 2: - if (waypointId == 2) - FinishPointReached(); - break; - case 3: - if (waypointId == 1) - FinishPointReached(); - break; - case 4: - if (waypointId == 0) - FinishPointReached(); - break; - case 5: - if (waypointId == 0) - FinishPointReached(); - break; - case 6: - if (waypointId == 4) - FinishPointReached(); - break; + _instance = creature->GetInstanceScript(); + + if (_instance->GetData(DATA_WAVE_COUNT) == 6) + _bossId = _instance->GetData(DATA_1ST_BOSS); + else + _bossId = _instance->GetData(DATA_2ND_BOSS); } - } - void UpdateAI(uint32 diff) override - { - if (instance->GetData(DATA_MAIN_EVENT_PHASE) != IN_PROGRESS) - me->CastStop(); - - npc_escortAI::UpdateAI(diff); - - if (!bHasGotMovingPoints) + void StartMovement() { - bHasGotMovingPoints = true; - switch (uiBoss) + uint32 pathSize = 0; + G3D::Vector3 const* path = nullptr; + + switch (_bossId) { - case 1: - for (int i=0;i<3;i++) - AddWaypoint(i, SaboteurFinalPos1[i][0], SaboteurFinalPos1[i][1], SaboteurFinalPos1[i][2], 0); - me->SetHomePosition(SaboteurFinalPos1[2][0], SaboteurFinalPos1[2][1], SaboteurFinalPos1[2][2], 4.762346f); + case DATA_MORAGG: + pathSize = SaboteurMoraggPathSize; + path = SaboteurMoraggPath; break; - case 2: - for (int i=0;i<3;i++) - AddWaypoint(i, SaboteurFinalPos2[i][0], SaboteurFinalPos2[i][1], SaboteurFinalPos2[i][2], 0); - me->SetHomePosition(SaboteurFinalPos2[2][0], SaboteurFinalPos2[2][1], SaboteurFinalPos2[2][2], 1.862674f); + case DATA_EREKEM: + pathSize = SaboteurErekemPathSize; + path = SaboteurErekemPath; break; - case 3: - for (int i=0;i<2;i++) - AddWaypoint(i, SaboteurFinalPos3[i][0], SaboteurFinalPos3[i][1], SaboteurFinalPos3[i][2], 0); - me->SetHomePosition(SaboteurFinalPos3[1][0], SaboteurFinalPos3[1][1], SaboteurFinalPos3[1][2], 5.500638f); + case DATA_ICHORON: + pathSize = SaboteurIchoronPathSize; + path = SaboteurIchoronPath; break; - case 4: - AddWaypoint(0, SaboteurFinalPos4[0], SaboteurFinalPos4[1], SaboteurFinalPos4[2], 0); - me->SetHomePosition(SaboteurFinalPos4[0], SaboteurFinalPos4[1], SaboteurFinalPos4[2], 3.991108f); + case DATA_LAVANTHOR: + pathSize = SaboteurLavanthorPathSize; + path = SaboteurLavanthorPath; break; - case 5: - AddWaypoint(0, SaboteurFinalPos5[0], SaboteurFinalPos5[1], SaboteurFinalPos5[2], 0); - me->SetHomePosition(SaboteurFinalPos5[0], SaboteurFinalPos5[1], SaboteurFinalPos5[2], 1.100841f); + case DATA_XEVOZZ: + pathSize = SaboteurXevozzPathSize; + path = SaboteurXevozzPath; break; - case 6: - for (int i=0;i<5;i++) - AddWaypoint(i, SaboteurFinalPos6[i][0], SaboteurFinalPos6[i][1], SaboteurFinalPos6[i][2], 0); - me->SetHomePosition(SaboteurFinalPos6[4][0], SaboteurFinalPos6[4][1], SaboteurFinalPos6[4][2], 0.983031f); + case DATA_ZURAMAT: + pathSize = SaboteurZuramatPathSize; + path = SaboteurZuramatPath; break; } - SetDespawnAtEnd(false); - Start(true, true); + if (path) + me->GetMotionMaster()->MoveSmoothPath(POINT_INTRO, path, pathSize, false); } - } - void FinishPointReached() + void Reset() override + { + _scheduler.CancelAll(); + _scheduler.Schedule(Seconds(2), [this](TaskContext /*task*/) + { + StartMovement(); + }); + } + + void MovementInform(uint32 type, uint32 pointId) override + { + if (type == EFFECT_MOTION_TYPE && pointId == POINT_INTRO) + { + _scheduler.Schedule(Seconds(0), [this](TaskContext task) + { + me->CastSpell(me, SPELL_SHIELD_DISRUPTION, false); + + if (task.GetRepeatCounter() < 2) + task.Repeat(Seconds(1)); + else + { + task.Schedule(Seconds(2), [this](TaskContext /*task*/) + { + _instance->SetData(DATA_START_BOSS_ENCOUNTER, 1); + me->CastSpell(me, SPELL_TELEPORT_VISUAL, false); + me->DespawnOrUnsummon(1000); + }); + } + }); + } + } + + void UpdateAI(uint32 diff) override + { + _scheduler.Update(diff); + } + + private: + InstanceScript* _instance; + TaskScheduler _scheduler; + + uint32 _bossId; + }; + + CreatureAI* GetAI(Creature* creature) const override { - me->CastSpell(me, SABOTEUR_SHIELD_DISRUPTION, false); - me->DisappearAndDie(); - if (Creature* pSaboPort = ObjectAccessor::GetCreature((*me), instance->GetGuidData(DATA_SABOTEUR_PORTAL))) - pSaboPort->DisappearAndDie(); - instance->SetData(DATA_START_BOSS_ENCOUNTER, 1); + return GetVioletHoldAI(creature); } - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI(creature); - } }; -class npc_teleportation_portal_vh : public CreatureScript +struct npc_violet_hold_teleportation_portal_commonAI : public ScriptedAI { -public: - npc_teleportation_portal_vh() : CreatureScript("npc_teleportation_portal_vh") { } - - struct npc_teleportation_portalAI : public ScriptedAI + npc_violet_hold_teleportation_portal_commonAI(Creature* creature) : ScriptedAI(creature), _summons(me) { - npc_teleportation_portalAI(Creature* creature) : ScriptedAI(creature), listOfMobs(me) + _instance = creature->GetInstanceScript(); + _portalLocation = 0; + } + + void InitializeAI() override + { + ScriptedAI::InitializeAI(); + ScheduleTasks(); + } + + void SetData(uint32 type, uint32 data) override + { + if (type == DATA_PORTAL_LOCATION) + _portalLocation = uint8(data); + } + + void MoveInLineOfSight(Unit* /*who*/) override { } + + void EnterCombat(Unit* /*who*/) override { } + + void JustSummoned(Creature* summon) override + { + _summons.Summon(summon); + summon->AI()->SetData(DATA_PORTAL_LOCATION, _portalLocation); + } + + void SummonedCreatureDies(Creature* summon, Unit* /*killer*/) override + { + _summons.Despawn(summon); + } + + virtual void ScheduleTasks() { } + + void UpdateAI(uint32 diff) override + { + _scheduler.Update(diff); + } + +protected: + InstanceScript* _instance; + SummonList _summons; + TaskScheduler _scheduler; + uint8 _portalLocation; +}; + +class npc_violet_hold_teleportation_portal : public CreatureScript +{ + public: + npc_violet_hold_teleportation_portal() : CreatureScript("npc_violet_hold_teleportation_portal") { } + + struct npc_violet_hold_teleportation_portalAI : public npc_violet_hold_teleportation_portal_commonAI { - Initialize(); - instance = creature->GetInstanceScript(); - uiTypeOfMobsPortal = urand(0, 1); // 0 - elite mobs 1 - portal guardian or portal keeper with regular mobs - - if (instance->GetData(DATA_MAIN_EVENT_PHASE) == NOT_STARTED) - uiTypeOfMobsPortal = 2; - } - - void Initialize() - { - uiSpawnTimer = 10000; - bPortalGuardianOrKeeperOrEliteSpawn = false; - } - - uint32 uiSpawnTimer; - bool bPortalGuardianOrKeeperOrEliteSpawn; - uint8 uiTypeOfMobsPortal; - - SummonList listOfMobs; - - InstanceScript* instance; - - void Reset() override - { - Initialize(); - } - - void EnterCombat(Unit* /*who*/) override { } - - void MoveInLineOfSight(Unit* /*who*/) override { } - - void UpdateAI(uint32 diff) override - { - if (instance->GetData(DATA_MAIN_EVENT_PHASE) == IN_PROGRESS) + npc_violet_hold_teleportation_portalAI(Creature* creature) : npc_violet_hold_teleportation_portal_commonAI(creature) { - if (instance->GetData(DATA_REMOVE_NPC) == 1) - { - me->DespawnOrUnsummon(); - instance->SetData(DATA_REMOVE_NPC, 0); - } } - uint8 uiWaveCount = instance->GetData(DATA_WAVE_COUNT); - if ((uiWaveCount == 6) || (uiWaveCount == 12)) //Don't spawn mobs on boss encounters - return; - - switch (uiTypeOfMobsPortal) + void InitializeAI() override { - // spawn elite mobs and then set portals visibility to make it look like it dissapeard - case 0: - if (!bPortalGuardianOrKeeperOrEliteSpawn) + npc_violet_hold_teleportation_portal_commonAI::InitializeAI(); + me->CastSpell(me, SPELL_PORTAL_PERIODIC, true); + } + + void SetData(uint32 type, uint32 data) override + { + npc_violet_hold_teleportation_portal_commonAI::SetData(type, data); + + if (type == DATA_PORTAL_PERIODIC_TICK) + { + if (data == 1) { - if (uiSpawnTimer <= diff) + uint32 entry = RAND(NPC_PORTAL_GUARDIAN, NPC_PORTAL_KEEPER); + if (Creature* portalKeeper = DoSummon(entry, me, 2.0f, 0, TEMPSUMMON_DEAD_DESPAWN)) + me->CastSpell(portalKeeper, SPELL_PORTAL_CHANNEL, false); + + if (Creature* sinclariTrigger = _instance->GetCreature(DATA_SINCLARI_TRIGGER)) { - bPortalGuardianOrKeeperOrEliteSpawn = true; - uint8 k = uiWaveCount < 12 ? 2 : 3; - for (uint8 i = 0; i < k; ++i) - { - uint32 entry = RAND(NPC_AZURE_CAPTAIN, NPC_AZURE_RAIDER, NPC_AZURE_STALKER, NPC_AZURE_SORCEROR); - DoSummon(entry, me, 2.0f, 20000, TEMPSUMMON_DEAD_DESPAWN); - } - me->SetVisible(false); - } else uiSpawnTimer -= diff; + if (entry == NPC_PORTAL_GUARDIAN) + sinclariTrigger->AI()->Talk(SAY_SINCLARI_PORTAL_GUARDIAN); + else if (entry == NPC_PORTAL_KEEPER) + sinclariTrigger->AI()->Talk(SAY_SINCLARI_PORTAL_KEEPER); + } } else { - // if all spawned elites have died kill portal - if (listOfMobs.empty()) + uint8 k = _instance->GetData(DATA_WAVE_COUNT) < 12 ? 3 : 4; + while (k--) { - me->Kill(me, false); - me->RemoveCorpse(); + uint32 entry = RAND(NPC_AZURE_INVADER_1, NPC_AZURE_INVADER_2, NPC_AZURE_SPELLBREAKER_1, NPC_AZURE_SPELLBREAKER_2, NPC_AZURE_MAGE_SLAYER_1, NPC_AZURE_MAGE_SLAYER_2, NPC_AZURE_BINDER_1, NPC_AZURE_BINDER_2); + DoSummon(entry, me, 2.0f, 20000, TEMPSUMMON_DEAD_DESPAWN); } } - break; - // spawn portal guardian or portal keeper with regular mobs - case 1: - if (uiSpawnTimer <= diff) - { - if (bPortalGuardianOrKeeperOrEliteSpawn) - { - uint8 k = instance->GetData(DATA_WAVE_COUNT) < 12 ? 3 : 4; - for (uint8 i = 0; i < k; ++i) - { - uint32 entry = RAND(NPC_AZURE_INVADER_1, NPC_AZURE_INVADER_2, NPC_AZURE_SPELLBREAKER_1, NPC_AZURE_SPELLBREAKER_2, NPC_AZURE_MAGE_SLAYER_1, NPC_AZURE_MAGE_SLAYER_2, NPC_AZURE_BINDER_1, NPC_AZURE_BINDER_2); - DoSummon(entry, me, 2.0f, 20000, TEMPSUMMON_DEAD_DESPAWN); - } - } - else - { - bPortalGuardianOrKeeperOrEliteSpawn = true; - uint32 entry = RAND(NPC_PORTAL_GUARDIAN, NPC_PORTAL_KEEPER); - if (Creature* pPortalKeeper = DoSummon(entry, me, 2.0f, 0, TEMPSUMMON_DEAD_DESPAWN)) - me->CastSpell(pPortalKeeper, SPELL_PORTAL_CHANNEL, false); - } - uiSpawnTimer = SPAWN_TIME; - } else uiSpawnTimer -= diff; + } + } - if (bPortalGuardianOrKeeperOrEliteSpawn && !me->IsNonMeleeSpellCast(false)) + void SummonedCreatureDies(Creature* summon, Unit* killer) override + { + npc_violet_hold_teleportation_portal_commonAI::SummonedCreatureDies(summon, killer); + + if (summon->GetEntry() == NPC_PORTAL_GUARDIAN || summon->GetEntry() == NPC_PORTAL_KEEPER) + { + _instance->SetData(DATA_WAVE_COUNT, _instance->GetData(DATA_WAVE_COUNT) + 1); + me->DespawnOrUnsummon(); + } + } + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetVioletHoldAI(creature); + } +}; + +class npc_violet_hold_teleportation_portal_elite : public CreatureScript +{ + public: + npc_violet_hold_teleportation_portal_elite() : CreatureScript("npc_violet_hold_teleportation_portal_elite") { } + + struct npc_violet_hold_teleportation_portal_eliteAI : public npc_violet_hold_teleportation_portal_commonAI + { + npc_violet_hold_teleportation_portal_eliteAI(Creature* creature) : npc_violet_hold_teleportation_portal_commonAI(creature) + { + } + + void ScheduleTasks() override + { + _scheduler.Schedule(Seconds(15), [this](TaskContext task) + { + uint8 k = _instance->GetData(DATA_WAVE_COUNT) < 12 ? 3 : 4; + while (k--) { - me->Kill(me, false); - me->RemoveCorpse(); - } - break; - case 2: // Pre-event - if (uiSpawnTimer <= diff) - { - uint32 entry = RAND(NPC_AZURE_INVADER_1, NPC_AZURE_MAGE_SLAYER_1, NPC_AZURE_BINDER_1); + uint32 entry = RAND(NPC_AZURE_CAPTAIN_1, NPC_AZURE_RAIDER_1, NPC_AZURE_STALKER_1, NPC_AZURE_SORCEROR_1); DoSummon(entry, me, 2.0f, 20000, TEMPSUMMON_DEAD_DESPAWN); - uiSpawnTimer = SPAWN_TIME; - } else uiSpawnTimer -= diff; - break; + } + + if (Creature* sinclariTrigger = _instance->GetCreature(DATA_SINCLARI_TRIGGER)) + sinclariTrigger->AI()->Talk(SAY_SINCLARI_ELITE_SQUAD); + + task.Schedule(Seconds(1), [this](TaskContext /*task*/) + { + me->SetVisible(false); + }); + }); } - } - void JustDied(Unit* /*killer*/) override - { - if (instance->GetData(DATA_MAIN_EVENT_PHASE) == IN_PROGRESS) - instance->SetData(DATA_WAVE_COUNT, instance->GetData(DATA_WAVE_COUNT) + 1); - } - - void JustSummoned(Creature* summoned) override - { - if (instance->GetData(DATA_MAIN_EVENT_PHASE) == IN_PROGRESS) + void SummonedCreatureDies(Creature* summon, Unit* killer) override { - listOfMobs.Summon(summoned); - instance->SetGuidData(DATA_ADD_TRASH_MOB, summoned->GetGUID()); - } - } + npc_violet_hold_teleportation_portal_commonAI::SummonedCreatureDies(summon, killer); - void SummonedCreatureDies(Creature* summoned, Unit* /*killer*/) override + if (_summons.empty()) + { + _instance->SetData(DATA_WAVE_COUNT, _instance->GetData(DATA_WAVE_COUNT) + 1); + me->DespawnOrUnsummon(); + } + } + }; + + CreatureAI* GetAI(Creature* creature) const override { - if (instance->GetData(DATA_MAIN_EVENT_PHASE) == IN_PROGRESS) - { - listOfMobs.Despawn(summoned); - instance->SetGuidData(DATA_DEL_TRASH_MOB, summoned->GetGUID()); - } + return GetVioletHoldAI(creature); } - }; +}; - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI(creature); - } +class npc_violet_hold_teleportation_portal_intro : public CreatureScript +{ + public: + npc_violet_hold_teleportation_portal_intro() : CreatureScript("npc_violet_hold_teleportation_portal_intro") { } + + struct npc_violet_hold_teleportation_portal_introAI : public npc_violet_hold_teleportation_portal_commonAI + { + npc_violet_hold_teleportation_portal_introAI(Creature* creature) : npc_violet_hold_teleportation_portal_commonAI(creature) + { + } + + void ScheduleTasks() override + { + if (_instance->GetData(DATA_MAIN_EVENT_STATE) != NOT_STARTED) + return; + + _scheduler.Schedule(Seconds(15), [this](TaskContext task) + { + uint32 entry = RAND(NPC_AZURE_INVADER_1, NPC_AZURE_MAGE_SLAYER_1, NPC_AZURE_BINDER_1); + DoSummon(entry, me, 2.0f, 20000, TEMPSUMMON_DEAD_DESPAWN); + + task.Repeat(); + }); + } + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetVioletHoldAI(creature); + } }; struct violet_hold_trashAI : public npc_escortAI { violet_hold_trashAI(Creature* creature) : npc_escortAI(creature) { - instance = creature->GetInstanceScript(); - bHasGotMovingPoints = false; + _instance = creature->GetInstanceScript(); + _lastWaypointId = 0; - if (instance->GetData(DATA_MAIN_EVENT_PHASE) == NOT_STARTED) + SetDespawnAtEnd(false); + + _scheduler.SetValidator([this] { - if (Creature* portal = me->FindNearestCreature(NPC_TELEPORTATION_PORTAL, 10.0f)) - { - ObjectGuid portalGUID = portal->GetGUID(); - for (uint8 i = 0; i < MAX_PRE_EVENT_PORTAL; i++) - if (portalGUID == preEventPortalGUID[i]) - portalLocationID = i * 2; - } - } - else - { - portalLocationID = instance->GetData(DATA_PORTAL_LOCATION); - Reset(); - } + return !me->HasUnitState(UNIT_STATE_CASTING); + }); } - public: - InstanceScript* instance; - bool bHasGotMovingPoints; - uint32 portalLocationID; - uint32 secondPortalRouteID; - - void WaypointReached(uint32 waypointId) override + void Reset() override { - switch (portalLocationID) - { - case 0: - if (waypointId == 5) - CreatureStartAttackDoor(); - break; - case 1: - if ((waypointId == 8 && secondPortalRouteID == 0) || (waypointId == 7 && secondPortalRouteID == 1)) - CreatureStartAttackDoor(); - break; - case 2: - if (waypointId == 7) - CreatureStartAttackDoor(); - break; - case 3: - if (waypointId == 8) - CreatureStartAttackDoor(); - break; - case 4: - if (waypointId == 5) - CreatureStartAttackDoor(); - break; - case 5: - if (waypointId == 3) - CreatureStartAttackDoor(); - break; - } + _scheduler.CancelAll(); } - void UpdateAI(uint32 diff) override + void SetData(uint32 type, uint32 data) override { - if (instance->GetData(DATA_MAIN_EVENT_PHASE) != IN_PROGRESS) - me->CastStop(); - - if (!bHasGotMovingPoints) + if (type == DATA_PORTAL_LOCATION) { - bHasGotMovingPoints = true; - switch (portalLocationID) + G3D::Vector3 const* path = nullptr; + + switch (data) { case 0: - for (int i=0;i<6;i++) - AddWaypoint(i, FirstPortalWPs[i][0]+irand(-1, 1), FirstPortalWPs[i][1]+irand(-1, 1), FirstPortalWPs[i][2]+irand(-1, 1), 0); - me->SetHomePosition(FirstPortalWPs[5][0], FirstPortalWPs[5][1], FirstPortalWPs[5][2], 3.149439f); + _lastWaypointId = 5; + path = FirstPortalWPs; break; - case 1: - secondPortalRouteID = urand(0, 1); - switch (secondPortalRouteID) + case 7: + switch (urand(0, 1)) { case 0: - for (int i=0;i<9;i++) - AddWaypoint(i, SecondPortalFirstWPs[i][0]+irand(-1, 1), SecondPortalFirstWPs[i][1]+irand(-1, 1), SecondPortalFirstWPs[i][2], 0); - me->SetHomePosition(SecondPortalFirstWPs[8][0]+irand(-1, 1), SecondPortalFirstWPs[8][1]+irand(-1, 1), SecondPortalFirstWPs[8][2]+irand(-1, 1), 3.149439f); + _lastWaypointId = 8; + path = SecondPortalFirstWPs; break; case 1: - for (int i=0;i<8;i++) - AddWaypoint(i, SecondPortalSecondWPs[i][0]+irand(-1, 1), SecondPortalSecondWPs[i][1]+irand(-1, 1), SecondPortalSecondWPs[i][2], 0); - me->SetHomePosition(SecondPortalSecondWPs[7][0], SecondPortalSecondWPs[7][1], SecondPortalSecondWPs[7][2], 3.149439f); + _lastWaypointId = 7; + path = SecondPortalSecondWPs; break; } break; case 2: - for (int i=0;i<8;i++) - AddWaypoint(i, ThirdPortalWPs[i][0]+irand(-1, 1), ThirdPortalWPs[i][1]+irand(-1, 1), ThirdPortalWPs[i][2], 0); - me->SetHomePosition(ThirdPortalWPs[7][0], ThirdPortalWPs[7][1], ThirdPortalWPs[7][2], 3.149439f); + _lastWaypointId = 7; + path = ThirdPortalWPs; break; - case 3: - for (int i=0;i<9;i++) - AddWaypoint(i, FourthPortalWPs[i][0]+irand(-1, 1), FourthPortalWPs[i][1]+irand(-1, 1), FourthPortalWPs[i][2], 0); - me->SetHomePosition(FourthPortalWPs[8][0], FourthPortalWPs[8][1], FourthPortalWPs[8][2], 3.149439f); + case 6: + _lastWaypointId = 8; + path = FourthPortalWPs; break; - case 4: - for (int i=0;i<6;i++) - AddWaypoint(i, FifthPortalWPs[i][0]+irand(-1, 1), FifthPortalWPs[i][1]+irand(-1, 1), FifthPortalWPs[i][2], 0); - me->SetHomePosition(FifthPortalWPs[5][0], FifthPortalWPs[5][1], FifthPortalWPs[5][2], 3.149439f); + case 1: + _lastWaypointId = 5; + path = FifthPortalWPs; break; case 5: - for (int i=0;i<4;i++) - AddWaypoint(i, SixthPoralWPs[i][0]+irand(-1, 1), SixthPoralWPs[i][1]+irand(-1, 1), SixthPoralWPs[i][2], 0); - me->SetHomePosition(SixthPoralWPs[3][0], SixthPoralWPs[3][1], SixthPoralWPs[3][2], 3.149439f); + _lastWaypointId = 3; + path = SixthPoralWPs; + break; + default: + _lastWaypointId = 0; + path = DefaultPortalWPs; break; } - SetDespawnAtEnd(false); + + if (path) + { + for (uint32 i = 0; i <= _lastWaypointId; i++) + AddWaypoint(i, path[i].x + irand(-1, 1), path[i].y + irand(-1, 1), path[i].z, 0); + me->SetHomePosition(path[_lastWaypointId].x, path[_lastWaypointId].y, path[_lastWaypointId].z, float(M_PI)); + } + Start(true, true); } - - npc_escortAI::UpdateAI(diff); } - void JustDied(Unit* /*killer*/) override + void WaypointReached(uint32 waypointId) override { - instance->SetData(DATA_NPC_PRESENCE_AT_DOOR_REMOVE, 1); + if (waypointId == _lastWaypointId) + CreatureStartAttackDoor(); } + void EnterCombat(Unit* who) override + { + npc_escortAI::EnterCombat(who); + ScheduledTasks(); + } + + void UpdateEscortAI(uint32 diff) override + { + if (_instance->GetData(DATA_MAIN_EVENT_STATE) != IN_PROGRESS) + me->CastStop(); + + if (!UpdateVictim()) + return; + + _scheduler.Update(diff, + std::bind(&npc_escortAI::DoMeleeAttackIfReady, this)); + } + + virtual void ScheduledTasks() { } + void CreatureStartAttackDoor() { - me->SetReactState(REACT_PASSIVE); - DoCast(SPELL_DESTROY_DOOR_SEAL); - instance->SetData(DATA_NPC_PRESENCE_AT_DOOR_ADD, 1); + me->SetReactState(REACT_DEFENSIVE); + DoCastAOE(SPELL_DESTROY_DOOR_SEAL); } + +protected: + InstanceScript* _instance; + TaskScheduler _scheduler; + + uint32 _lastWaypointId; }; class npc_azure_invader : public CreatureScript { -public: - npc_azure_invader() : CreatureScript("npc_azure_invader") { } + public: + npc_azure_invader() : CreatureScript("npc_azure_invader") { } - struct npc_azure_invaderAI : public violet_hold_trashAI - { - npc_azure_invaderAI(Creature* creature) : violet_hold_trashAI(creature) + struct npc_azure_invaderAI : public violet_hold_trashAI { - Initialize(); - instance = creature->GetInstanceScript(); - } + npc_azure_invaderAI(Creature* creature) : violet_hold_trashAI(creature) { } - void Initialize() - { - uiCleaveTimer = 5000; - uiImpaleTimer = 4000; - uiBrutalStrikeTimer = 5000; - uiSunderArmorTimer = 4000; - } - - uint32 uiCleaveTimer; - uint32 uiImpaleTimer; - uint32 uiBrutalStrikeTimer; - uint32 uiSunderArmorTimer; - - void Reset() override - { - Initialize(); - } - - void UpdateAI(uint32 diff) override - { - violet_hold_trashAI::UpdateAI(diff); - - if (!UpdateVictim()) - return; - - if (me->GetEntry() == NPC_AZURE_INVADER_1) + void ScheduledTasks() override { - if (uiCleaveTimer <= diff) + if (me->GetEntry() == NPC_AZURE_INVADER_1) { - DoCastVictim(SPELL_CLEAVE); - uiCleaveTimer = 5000; - } else uiCleaveTimer -= diff; + _scheduler.Schedule(Seconds(5), [this](TaskContext task) + { + DoCastVictim(SPELL_CLEAVE); + task.Repeat(); + }); - if (uiImpaleTimer <= diff) + _scheduler.Schedule(Seconds(4), [this](TaskContext task) + { + DoCastVictim(SPELL_IMPALE); + task.Repeat(); + }); + } + else if (me->GetEntry() == NPC_AZURE_INVADER_2) { - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(target, SPELL_IMPALE); - uiImpaleTimer = 4000; - } else uiImpaleTimer -= diff; + _scheduler.Schedule(Seconds(5), [this](TaskContext task) + { + DoCastVictim(SPELL_BRUTAL_STRIKE); + task.Repeat(); + }); + + _scheduler.Schedule(Seconds(4), [this](TaskContext task) + { + DoCastVictim(SPELL_SUNDER_ARMOR); + task.Repeat(Seconds(8), Seconds(10)); + }); + } } + }; - if (me->GetEntry() == NPC_AZURE_INVADER_2) - { - if (uiBrutalStrikeTimer <= diff) - { - DoCastVictim(SPELL_BRUTAL_STRIKE); - uiBrutalStrikeTimer = 5000; - } else uiBrutalStrikeTimer -= diff; - - if (uiSunderArmorTimer <= diff) - { - DoCastVictim(SPELL_SUNDER_ARMOR); - uiSunderArmorTimer = urand(8000, 10000); - } else uiSunderArmorTimer -= diff; - - DoMeleeAttackIfReady(); - } - - DoMeleeAttackIfReady(); + CreatureAI* GetAI(Creature* creature) const override + { + return GetVioletHoldAI(creature); } - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI(creature); - } }; class npc_azure_binder : public CreatureScript { -public: - npc_azure_binder() : CreatureScript("npc_azure_binder") { } + public: + npc_azure_binder() : CreatureScript("npc_azure_binder") { } - struct npc_azure_binderAI : public violet_hold_trashAI - { - npc_azure_binderAI(Creature* creature) : violet_hold_trashAI(creature) + struct npc_azure_binderAI : public violet_hold_trashAI { - Initialize(); - instance = creature->GetInstanceScript(); - } + npc_azure_binderAI(Creature* creature) : violet_hold_trashAI(creature) { } - void Initialize() - { - uiArcaneExplosionTimer = 5000; - uiArcainBarrageTimer = 4000; - uiFrostNovaTimer = 5000; - uiFrostboltTimer = 4000; - } - - uint32 uiArcaneExplosionTimer; - uint32 uiArcainBarrageTimer; - uint32 uiFrostNovaTimer; - uint32 uiFrostboltTimer; - - void Reset() override - { - Initialize(); - } - - void UpdateAI(uint32 diff) override - { - violet_hold_trashAI::UpdateAI(diff); - - if (!UpdateVictim()) - return; - - if (me->GetEntry() == NPC_AZURE_BINDER_1) + void ScheduledTasks() override { - if (uiArcaneExplosionTimer <= diff) + if (me->GetEntry() == NPC_AZURE_BINDER_1) { - DoCast(SPELL_ARCANE_EXPLOSION); - uiArcaneExplosionTimer = 5000; - } else uiArcaneExplosionTimer -= diff; + _scheduler.Schedule(Seconds(5), [this](TaskContext task) + { + DoCastAOE(SPELL_ARCANE_EXPLOSION); + task.Repeat(); + }); - if (uiArcainBarrageTimer <= diff) + _scheduler.Schedule(Seconds(4), [this](TaskContext task) + { + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 30.0f)) + DoCast(target, SPELL_ARCANE_BARRAGE); + task.Repeat(Seconds(6)); + }); + } + else if (me->GetEntry() == NPC_AZURE_BINDER_2) { - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(target, SPELL_ARCANE_BARRAGE); - uiArcainBarrageTimer = 6000; - } else uiArcainBarrageTimer -= diff; + _scheduler.Schedule(Seconds(5), [this](TaskContext task) + { + DoCastAOE(SPELL_FROST_NOVA); + task.Repeat(); + }); + + _scheduler.Schedule(Seconds(4), [this](TaskContext task) + { + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 40.0f)) + DoCast(target, SPELL_FROSTBOLT); + task.Repeat(Seconds(6)); + }); + } } + }; - if (me->GetEntry() == NPC_AZURE_BINDER_2) - { - if (uiFrostNovaTimer <= diff) - { - DoCast(SPELL_FROST_NOVA); - uiFrostNovaTimer = 5000; - } else uiFrostNovaTimer -= diff; - - if (uiFrostboltTimer <= diff) - { - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(target, SPELL_FROSTBOLT); - uiFrostboltTimer = 6000; - } else uiFrostboltTimer -= diff; - } - - DoMeleeAttackIfReady(); + CreatureAI* GetAI(Creature* creature) const override + { + return GetVioletHoldAI(creature); } - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI(creature); - } }; class npc_azure_mage_slayer : public CreatureScript { -public: - npc_azure_mage_slayer() : CreatureScript("npc_azure_mage_slayer") { } + public: + npc_azure_mage_slayer() : CreatureScript("npc_azure_mage_slayer") { } - struct npc_azure_mage_slayerAI : public violet_hold_trashAI - { - npc_azure_mage_slayerAI(Creature* creature) : violet_hold_trashAI(creature) + struct npc_azure_mage_slayerAI : public violet_hold_trashAI { - Initialize(); - instance = creature->GetInstanceScript(); - } + npc_azure_mage_slayerAI(Creature* creature) : violet_hold_trashAI(creature) { } - void Initialize() - { - uiArcaneEmpowermentTimer = 5000; - uiSpellLockTimer = 5000; - } - - uint32 uiArcaneEmpowermentTimer; - uint32 uiSpellLockTimer; - - void Reset() override - { - Initialize(); - } - - void UpdateAI(uint32 diff) override - { - violet_hold_trashAI::UpdateAI(diff); - - if (!UpdateVictim()) - return; - - if (me->GetEntry() == NPC_AZURE_MAGE_SLAYER_1) + void ScheduledTasks() override { - if (uiArcaneEmpowermentTimer <= diff) + if (me->GetEntry() == NPC_AZURE_MAGE_SLAYER_1) { - DoCast(me, SPELL_ARCANE_EMPOWERMENT); - uiArcaneEmpowermentTimer = 14000; - } else uiArcaneEmpowermentTimer -= diff; - } - - if (me->GetEntry() == NPC_AZURE_MAGE_SLAYER_2) - { - if (uiSpellLockTimer <= diff) + _scheduler.Schedule(Seconds(5), [this](TaskContext task) + { + DoCast(me, SPELL_ARCANE_EMPOWERMENT); + task.Repeat(Seconds(14)); + }); + } + else if (me->GetEntry() == NPC_AZURE_MAGE_SLAYER_2) { - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(target, SPELL_SPELL_LOCK); - uiSpellLockTimer = 9000; - } else uiSpellLockTimer -= diff; + _scheduler.Schedule(Seconds(5), [this](TaskContext task) + { + // wrong spellid? + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 30.0f)) + DoCast(target, SPELL_SPELL_LOCK); + task.Repeat(Seconds(9)); + }); + } } + }; - DoMeleeAttackIfReady(); + CreatureAI* GetAI(Creature* creature) const override + { + return GetVioletHoldAI(creature); } - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI(creature); - } }; class npc_azure_raider : public CreatureScript { -public: - npc_azure_raider() : CreatureScript("npc_azure_raider") { } + public: + npc_azure_raider() : CreatureScript("npc_azure_raider") { } - struct npc_azure_raiderAI : public violet_hold_trashAI - { - npc_azure_raiderAI(Creature* creature) : violet_hold_trashAI(creature) + struct npc_azure_raiderAI : public violet_hold_trashAI { - Initialize(); - instance = creature->GetInstanceScript(); - } + npc_azure_raiderAI(Creature* creature) : violet_hold_trashAI(creature) { } - void Initialize() - { - uiConcussionBlowTimer = 5000; - uiMagicReflectionTimer = 8000; - } - - uint32 uiConcussionBlowTimer; - uint32 uiMagicReflectionTimer; - - void Reset() override - { - Initialize(); - } - - void UpdateAI(uint32 diff) override - { - violet_hold_trashAI::UpdateAI(diff); - - if (!UpdateVictim()) - return; - - if (uiConcussionBlowTimer <= diff) + void ScheduledTasks() override { - DoCastVictim(SPELL_CONCUSSION_BLOW); - uiConcussionBlowTimer = 5000; - } else uiConcussionBlowTimer -= diff; + _scheduler.Schedule(Seconds(5), [this](TaskContext task) + { + DoCastVictim(SPELL_CONCUSSION_BLOW); + task.Repeat(); + }); - if (uiMagicReflectionTimer <= diff) - { - DoCast(SPELL_MAGIC_REFLECTION); - uiMagicReflectionTimer = urand(10000, 15000); - } else uiMagicReflectionTimer -= diff; + _scheduler.Schedule(Seconds(8), [this](TaskContext task) + { + DoCast(me, SPELL_MAGIC_REFLECTION); + task.Repeat(Seconds(10), Seconds(15)); + }); + } + }; - DoMeleeAttackIfReady(); + CreatureAI* GetAI(Creature* creature) const override + { + return GetVioletHoldAI(creature); } - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI(creature); - } }; class npc_azure_stalker : public CreatureScript { -public: - npc_azure_stalker() : CreatureScript("npc_azure_stalker") { } + public: + npc_azure_stalker() : CreatureScript("npc_azure_stalker") { } - struct npc_azure_stalkerAI : public violet_hold_trashAI - { - npc_azure_stalkerAI(Creature* creature) : violet_hold_trashAI(creature) + struct npc_azure_stalkerAI : public violet_hold_trashAI { - Initialize(); - instance = creature->GetInstanceScript(); - } + npc_azure_stalkerAI(Creature* creature) : violet_hold_trashAI(creature) { } - void Initialize() - { - _backstabTimer = 1300; - _tacticalBlinkTimer = 8000; - _tacticalBlinkCast = false; - } - - void Reset() override - { - Initialize(); - } - - void UpdateAI(uint32 diff) override - { - violet_hold_trashAI::UpdateAI(diff); - - if (!UpdateVictim()) - return; - - if (!_tacticalBlinkCast) + void ScheduledTasks() override { - if (_tacticalBlinkTimer <= diff) + _scheduler.Schedule(Seconds(8), [this](TaskContext task) { - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 40, true)) + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 40.0f)) DoCast(target, SPELL_TACTICAL_BLINK); - _tacticalBlinkTimer = 6000; - _tacticalBlinkCast = true; - } else _tacticalBlinkTimer -= diff; - } - else - { - if (_backstabTimer <= diff) - { - if (Unit* target = SelectTarget(SELECT_TARGET_NEAREST, 0, 10, true)) - DoCast(target, SPELL_BACKSTAB); - _tacticalBlinkCast = false; - _backstabTimer =1300; - } else _backstabTimer -= diff; - } + task.Schedule(Milliseconds(1300), [this](TaskContext /*task*/) + { + if (Unit* target = SelectTarget(SELECT_TARGET_NEAREST, 0, 5.0f)) + DoCast(target, SPELL_BACKSTAB); + }); - DoMeleeAttackIfReady(); + task.Repeat(); + }); + } + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetVioletHoldAI(creature); } - - private: - uint32 _backstabTimer; - uint32 _tacticalBlinkTimer; - bool _tacticalBlinkCast; - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI(creature); - } }; class npc_azure_spellbreaker : public CreatureScript { -public: - npc_azure_spellbreaker() : CreatureScript("npc_azure_spellbreaker") { } + public: + npc_azure_spellbreaker() : CreatureScript("npc_azure_spellbreaker") { } - struct npc_azure_spellbreakerAI : public violet_hold_trashAI - { - npc_azure_spellbreakerAI(Creature* creature) : violet_hold_trashAI(creature) + struct npc_azure_spellbreakerAI : public violet_hold_trashAI { - Initialize(); - instance = creature->GetInstanceScript(); - } + npc_azure_spellbreakerAI(Creature* creature) : violet_hold_trashAI(creature) { } - void Initialize() - { - uiArcaneBlastTimer = 5000; - uiSlowTimer = 4000; - uiChainsOfIceTimer = 5000; - uiConeOfColdTimer = 4000; - } - - uint32 uiArcaneBlastTimer; - uint32 uiSlowTimer; - uint32 uiChainsOfIceTimer; - uint32 uiConeOfColdTimer; - - void Reset() override - { - Initialize(); - } - - void UpdateAI(uint32 diff) override - { - violet_hold_trashAI::UpdateAI(diff); - - if (!UpdateVictim()) - return; - - if (me->GetEntry() == NPC_AZURE_SPELLBREAKER_1) + void ScheduledTasks() override { - if (uiArcaneBlastTimer <= diff) + if (me->GetEntry() == NPC_AZURE_SPELLBREAKER_1) { - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(target, SPELL_ARCANE_BLAST); - uiArcaneBlastTimer = 6000; - } else uiArcaneBlastTimer -= diff; + _scheduler.Schedule(Seconds(5), [this](TaskContext task) + { + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 30.0f)) + DoCast(target, SPELL_ARCANE_BLAST); + task.Repeat(Seconds(6)); + }); - if (uiSlowTimer <= diff) + _scheduler.Schedule(Seconds(4), [this](TaskContext task) + { + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 30.0f)) + DoCast(target, SPELL_SLOW); + task.Repeat(Seconds(5)); + }); + } + else if (me->GetEntry() == NPC_AZURE_SPELLBREAKER_2) { - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(target, SPELL_SLOW); - uiSlowTimer = 5000; - } else uiSlowTimer -= diff; + _scheduler.Schedule(Seconds(5), [this](TaskContext task) + { + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 30.0f)) + DoCast(target, SPELL_CHAINS_OF_ICE); + task.Repeat(Seconds(7)); + }); + + _scheduler.Schedule(Seconds(4), [this](TaskContext task) + { + DoCast(me, SPELL_CONE_OF_COLD); + task.Repeat(Seconds(5)); + }); + } } + }; - if (me->GetEntry() == NPC_AZURE_SPELLBREAKER_2) - { - if (uiChainsOfIceTimer <= diff) - { - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(target, SPELL_CHAINS_OF_ICE); - uiChainsOfIceTimer = 7000; - } else uiChainsOfIceTimer -= diff; - - if (uiConeOfColdTimer <= diff) - { - DoCast(SPELL_CONE_OF_COLD); - uiConeOfColdTimer = 5000; - } else uiConeOfColdTimer -= diff; - } - - DoMeleeAttackIfReady(); + CreatureAI* GetAI(Creature* creature) const override + { + return GetVioletHoldAI(creature); } - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI(creature); - } }; class npc_azure_captain : public CreatureScript { -public: - npc_azure_captain() : CreatureScript("npc_azure_captain") { } + public: + npc_azure_captain() : CreatureScript("npc_azure_captain") { } - struct npc_azure_captainAI : public violet_hold_trashAI - { - npc_azure_captainAI(Creature* creature) : violet_hold_trashAI(creature) + struct npc_azure_captainAI : public violet_hold_trashAI { - Initialize(); - instance = creature->GetInstanceScript(); - } + npc_azure_captainAI(Creature* creature) : violet_hold_trashAI(creature) { } - void Initialize() - { - uiMortalStrikeTimer = 5000; - uiWhirlwindTimer = 8000; - } - - uint32 uiMortalStrikeTimer; - uint32 uiWhirlwindTimer; - - void Reset() override - { - Initialize(); - } - - void UpdateAI(uint32 diff) override - { - violet_hold_trashAI::UpdateAI(diff); - - if (!UpdateVictim()) - return; - - if (uiMortalStrikeTimer <= diff) + void ScheduledTasks() override { - DoCastVictim(SPELL_MORTAL_STRIKE); - uiMortalStrikeTimer = 5000; - } else uiMortalStrikeTimer -= diff; + _scheduler.Schedule(Seconds(5), [this](TaskContext task) + { + DoCastVictim(SPELL_MORTAL_STRIKE); + task.Repeat(); + }); - if (uiWhirlwindTimer <= diff) - { - DoCast(me, SPELL_WHIRLWIND_OF_STEEL); - uiWhirlwindTimer = 8000; - } else uiWhirlwindTimer -= diff; + _scheduler.Schedule(Seconds(8), [this](TaskContext task) + { + DoCast(me, SPELL_WHIRLWIND_OF_STEEL); + task.Repeat(); + }); + } + }; - DoMeleeAttackIfReady(); + CreatureAI* GetAI(Creature* creature) const override + { + return GetVioletHoldAI(creature); } - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI(creature); - } }; class npc_azure_sorceror : public CreatureScript { -public: - npc_azure_sorceror() : CreatureScript("npc_azure_sorceror") { } + public: + npc_azure_sorceror() : CreatureScript("npc_azure_sorceror") { } - struct npc_azure_sorcerorAI : public violet_hold_trashAI - { - npc_azure_sorcerorAI(Creature* creature) : violet_hold_trashAI(creature) + struct npc_azure_sorcerorAI : public violet_hold_trashAI { - Initialize(); - instance = creature->GetInstanceScript(); - } + npc_azure_sorcerorAI(Creature* creature) : violet_hold_trashAI(creature) { } - void Initialize() - { - uiArcaneStreamTimer = 4000; - uiArcaneStreamTimerStartingValueHolder = uiArcaneStreamTimer; - uiManaDetonationTimer = 5000; - } - - uint32 uiArcaneStreamTimer; - uint32 uiArcaneStreamTimerStartingValueHolder; - uint32 uiManaDetonationTimer; - - void Reset() override - { - Initialize(); - } - - void UpdateAI(uint32 diff) override - { - violet_hold_trashAI::UpdateAI(diff); - - if (!UpdateVictim()) - return; - - if (uiArcaneStreamTimer <= diff) + void ScheduledTasks() override { - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(target, SPELL_ARCANE_STREAM); - uiArcaneStreamTimer = urand(0, 5000)+5000; - uiArcaneStreamTimerStartingValueHolder = uiArcaneStreamTimer; - } else uiArcaneStreamTimer -= diff; + _scheduler.Schedule(Seconds(4), [this](TaskContext task) + { + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 35.0f)) + DoCast(target, SPELL_ARCANE_STREAM); + task.Repeat(Seconds(5), Seconds(10)); + }); - if (uiManaDetonationTimer <= diff && uiArcaneStreamTimer >=1500 && uiArcaneStreamTimer <= uiArcaneStreamTimerStartingValueHolder/2) - { - DoCast(SPELL_MANA_DETONATION); - uiManaDetonationTimer = urand(2000, 6000); - } else uiManaDetonationTimer -= diff; + _scheduler.Schedule(Seconds(), Seconds(), [this](TaskContext task) + { + DoCastAOE(SPELL_MANA_DETONATION); + task.Repeat(Seconds(2), Seconds(6)); + }); + } + }; - DoMeleeAttackIfReady(); + CreatureAI* GetAI(Creature* creature) const override + { + return GetVioletHoldAI(creature); } - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI(creature); - } }; -class npc_violet_hold_arcane_sphere : public CreatureScript +class npc_violet_hold_defense_system : public CreatureScript { -public: - npc_violet_hold_arcane_sphere() : CreatureScript("npc_violet_hold_arcane_sphere") { } + public: + npc_violet_hold_defense_system() : CreatureScript("npc_violet_hold_defense_system") { } - struct npc_violet_hold_arcane_sphereAI : public ScriptedAI - { - npc_violet_hold_arcane_sphereAI(Creature* creature) : ScriptedAI(creature) + struct npc_violet_hold_defense_systemAI : public ScriptedAI { - Initialize(); - } + npc_violet_hold_defense_systemAI(Creature* creature) : ScriptedAI(creature) { } - void Initialize() + void Reset() override + { + ScheduledTasks(); + me->DespawnOrUnsummon(7000); + } + + void ScheduledTasks() + { + _scheduler.Schedule(Seconds(4), [this](TaskContext task) + { + DoCastAOE(SPELL_ARCANE_LIGHTNING_DAMAGE); + DoCastAOE(SPELL_ARCANE_LIGHTNING_DUMMY); + if (task.GetRepeatCounter() == 2) + DoCastAOE(SPELL_ARCANE_LIGHTNING_INSTAKILL); + else + task.Repeat(Seconds(1)); + }); + } + + void UpdateAI(uint32 diff) override + { + _scheduler.Update(diff); + } + + private: + TaskScheduler _scheduler; + }; + + CreatureAI* GetAI(Creature* creature) const override { - DespawnTimer = 3000; + return new npc_violet_hold_defense_systemAI(creature); } - - uint32 DespawnTimer; - - void Reset() override - { - Initialize(); - - me->SetDisableGravity(true); - DoCast(me, SPELL_ARCANE_SPHERE_PASSIVE, true); - } - - void EnterCombat(Unit * /*who*/) override { } - - void UpdateAI(uint32 diff) override - { - if (DespawnTimer <= diff) - me->Kill(me); - else - DespawnTimer -= diff; - } - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return new npc_violet_hold_arcane_sphereAI(creature); - } }; class go_activation_crystal : public GameObjectScript { -public: - go_activation_crystal() : GameObjectScript("go_activation_crystal") { } + public: + go_activation_crystal() : GameObjectScript("go_activation_crystal") { } - bool OnGossipHello(Player * /*player*/, GameObject* go) override - { - go->EventInform(EVENT_ACTIVATE_CRYSTAL); - return false; - } + bool OnGossipHello(Player* player, GameObject* /*go*/) override + { + player->CastSpell(player, SPELL_CRYSTAL_ACTIVATION, true); + return false; + } }; -class spell_crystal_activation : public SpellScriptLoader +// 58040 - Destroy Door Seal +class spell_violet_hold_destroy_door_seal : public SpellScriptLoader { -public: - spell_crystal_activation() : SpellScriptLoader("spell_crystal_activation") { } + public: + spell_violet_hold_destroy_door_seal() : SpellScriptLoader("spell_violet_hold_destroy_door_seal") { } - class spell_crystal_activation_SpellScript : public SpellScript - { - PrepareSpellScript(spell_crystal_activation_SpellScript); - - void HandleSendEvent(SpellEffIndex effIndex) + class spell_violet_hold_destroy_door_seal_AuraScript : public AuraScript { - if (GetHitUnit()->GetEntry() == NPC_VIOLET_HOLD_GUARD) - PreventHitDefaultEffect(effIndex); - } + PrepareAuraScript(spell_violet_hold_destroy_door_seal_AuraScript); - void Register() override + bool Load() override + { + _instance = GetUnitOwner()->GetInstanceScript(); + return _instance != nullptr; + } + + void PeriodicTick(AuraEffect const* /*aurEff*/) + { + PreventDefaultAction(); + if (uint32 integrity = _instance->GetData(DATA_DOOR_INTEGRITY)) + _instance->SetData(DATA_DOOR_INTEGRITY, integrity - 1); + } + + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_violet_hold_destroy_door_seal_AuraScript::PeriodicTick, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); + } + + private: + InstanceScript* _instance = nullptr; + }; + + AuraScript* GetAuraScript() const override { - OnEffectHitTarget += SpellEffectFn(spell_crystal_activation_SpellScript::HandleSendEvent, EFFECT_0, SPELL_EFFECT_SEND_EVENT); + return new spell_violet_hold_destroy_door_seal_AuraScript(); } - }; +}; - SpellScript* GetSpellScript() const override - { - return new spell_crystal_activation_SpellScript(); - } +// 58008 - Portal Periodic +class spell_violet_hold_portal_periodic : public SpellScriptLoader +{ + public: + spell_violet_hold_portal_periodic() : SpellScriptLoader("spell_violet_hold_portal_periodic") { } + + class spell_violet_hold_portal_periodic_AuraScript : public AuraScript + { + PrepareAuraScript(spell_violet_hold_portal_periodic_AuraScript); + + void PeriodicTick(AuraEffect const* aurEff) + { + PreventDefaultAction(); + if (GetTarget()->IsAIEnabled) + GetTarget()->GetAI()->SetData(DATA_PORTAL_PERIODIC_TICK, aurEff->GetTickNumber()); + } + + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_violet_hold_portal_periodic_AuraScript::PeriodicTick, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_violet_hold_portal_periodic_AuraScript(); + } +}; + +// 62138 - Teleport to Inside Violet Hold +class spell_violet_hold_teleport_player : public SpellScriptLoader +{ + public: + spell_violet_hold_teleport_player() : SpellScriptLoader("spell_violet_hold_teleport_player") { } + + class spell_violet_hold_teleport_player_SpellScript : public SpellScript + { + PrepareSpellScript(spell_violet_hold_teleport_player_SpellScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_TELEPORT_PLAYER_EFFECT)) + return false; + return true; + } + + void HandleScript(SpellEffIndex /*effIndex*/) + { + if (Unit* target = GetHitUnit()) + target->CastSpell(target, SPELL_TELEPORT_PLAYER_EFFECT, true); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_violet_hold_teleport_player_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_violet_hold_teleport_player_SpellScript(); + } }; void AddSC_violet_hold() { new npc_sinclari_vh(); - new npc_teleportation_portal_vh(); + new npc_violet_hold_teleportation_portal(); + new npc_violet_hold_teleportation_portal_elite(); + new npc_violet_hold_teleportation_portal_intro(); new npc_azure_invader(); new npc_azure_spellbreaker(); new npc_azure_binder(); @@ -1520,7 +1431,9 @@ void AddSC_violet_hold() new npc_azure_raider(); new npc_azure_stalker(); new npc_azure_saboteur(); - new npc_violet_hold_arcane_sphere(); + new npc_violet_hold_defense_system(); new go_activation_crystal(); - new spell_crystal_activation(); + new spell_violet_hold_destroy_door_seal(); + new spell_violet_hold_portal_periodic(); + new spell_violet_hold_teleport_player(); } diff --git a/src/server/scripts/Northrend/VioletHold/violet_hold.h b/src/server/scripts/Northrend/VioletHold/violet_hold.h index 2bd90672024..113a3c46ea0 100644 --- a/src/server/scripts/Northrend/VioletHold/violet_hold.h +++ b/src/server/scripts/Northrend/VioletHold/violet_hold.h @@ -15,44 +15,56 @@ * with this program. If not, see . */ -#ifndef DEF_VIOLET_HOLD_H -#define DEF_VIOLET_HOLD_H +#ifndef VIOLET_HOLD_H_ +#define VIOLET_HOLD_H_ +#define VioletHoldScriptName "instance_violet_hold" #define DataHeader "VH" -uint32 const EncounterCount = 3; +uint32 const EncounterCount = 3 + 6; + +// Defined in instance_violet_hold.cpp +extern Position const DefenseSystemLocation; +uint8 const PortalIntroCount = 3; +extern Position const PortalIntroPositions[]; + +/* + * Violet hold bosses: + * + * 1 - Moragg + * 2 - Erekem + * 3 - Ichoron + * 4 - Lavanthor + * 5 - Xevozz + * 6 - Zuramat + * 7 - Cyanigosa + */ enum Data { // Main encounters - DATA_1ST_BOSS_EVENT, - DATA_2ND_BOSS_EVENT, - DATA_CYANIGOSA, + DATA_1ST_BOSS = 0, + DATA_2ND_BOSS = 1, + DATA_CYANIGOSA = 2, + // Bosses + DATA_MORAGG = 3, + DATA_EREKEM = 4, + DATA_ICHORON = 5, + DATA_LAVANTHOR = 6, + DATA_XEVOZZ = 7, + DATA_ZURAMAT = 8, // Misc + DATA_MAIN_EVENT_STATE, DATA_WAVE_COUNT, - DATA_REMOVE_NPC, - DATA_PORTAL_LOCATION, DATA_DOOR_INTEGRITY, - DATA_NPC_PRESENCE_AT_DOOR, - DATA_NPC_PRESENCE_AT_DOOR_ADD, - DATA_NPC_PRESENCE_AT_DOOR_REMOVE, + DATA_PORTAL_LOCATION, DATA_START_BOSS_ENCOUNTER, - DATA_FIRST_BOSS, - DATA_SECOND_BOSS, - DATA_ACTIVATE_CRYSTAL, - DATA_MAIN_EVENT_PHASE, DATA_DEFENSELESS, // Bosses - DATA_MORAGG, - DATA_EREKEM, DATA_EREKEM_GUARD_1, DATA_EREKEM_GUARD_2, - DATA_ICHORON, - DATA_LAVANTHOR, - DATA_XEVOZZ, - DATA_ZURAMAT, // Cells DATA_MORAGG_CELL, @@ -67,43 +79,43 @@ enum Data // Misc DATA_MAIN_DOOR, DATA_SINCLARI, - DATA_TELEPORTATION_PORTAL, - DATA_SABOTEUR_PORTAL, - DATA_ADD_TRASH_MOB, - DATA_DEL_TRASH_MOB -}; - -enum Bosses -{ - BOSS_NONE, // 0 used as marker for not yet randomized - BOSS_MORAGG, - BOSS_EREKEM, - BOSS_ICHORON, - BOSS_LAVANTHOR, - BOSS_XEVOZZ, - BOSS_ZURAMAT, - BOSS_CYANIGOSA + DATA_SINCLARI_TRIGGER, + DATA_HANDLE_CELLS }; enum CreaturesIds { - NPC_TELEPORTATION_PORTAL = 31011, + NPC_TELEPORTATION_PORTAL = 30679, + NPC_TELEPORTATION_PORTAL_ELITE = 32174, + NPC_TELEPORTATION_PORTAL_INTRO = 31011, NPC_PORTAL_GUARDIAN = 30660, NPC_PORTAL_KEEPER = 30695, NPC_XEVOZZ = 29266, NPC_LAVANTHOR = 29312, NPC_ICHORON = 29313, + NPC_ICHOR_GLOBULE = 29321, + NPC_ICHORON_SUMMON_TARGET = 29326, NPC_ZURAMAT = 29314, + NPC_VOID_SENTRY = 29364, + NPC_VOID_SENTRY_BALL = 29365, NPC_EREKEM = 29315, NPC_EREKEM_GUARD = 29395, NPC_MORAGG = 29316, + + NPC_DUMMY_XEVOZZ = 32231, + NPC_DUMMY_LAVANTHOR = 32237, + NPC_DUMMY_ICHORON = 32234, + NPC_DUMMY_ZURAMAT = 32230, + NPC_DUMMY_EREKEM = 32226, + NPC_DUMMY_EREKEM_GUARD = 32228, + NPC_DUMMY_MORAGG = 32235, + NPC_CYANIGOSA = 31134, NPC_SINCLARI = 30658, + NPC_SINCLARI_TRIGGER = 32204, NPC_SABOTEOUR = 31079, NPC_VIOLET_HOLD_GUARD = 30659, - NPC_DEFENSE_SYSTEM = 30837, - NPC_VOID_SENTRY = 29364, - NPC_VOID_SENTRY_BALL = 29365 + NPC_DEFENSE_SYSTEM = 30837 }; enum GameObjectIds @@ -117,13 +129,13 @@ enum GameObjectIds GO_EREKEM_GUARD_1_DOOR = 191563, GO_EREKEM_GUARD_2_DOOR = 191562, GO_MORAGG_DOOR = 191606, - GO_INTRO_ACTIVATION_CRYSTAL = 193615, - GO_ACTIVATION_CRYSTAL = 193611 + GO_ACTIVATION_CRYSTAL = 193611, + GO_INTRO_ACTIVATION_CRYSTAL = 193615 }; enum WorldStateIds { - WORLD_STATE_VH = 3816, + WORLD_STATE_VH_SHOW = 3816, WORLD_STATE_VH_PRISON_STATE = 3815, WORLD_STATE_VH_WAVE_COUNT = 3810, }; @@ -133,4 +145,16 @@ enum Events EVENT_ACTIVATE_CRYSTAL = 20001 }; -#endif +enum InstanceMisc +{ + ACTION_SINCLARI_OUTRO = 1, + POINT_INTRO = 1 +}; + +template +inline AI* GetVioletHoldAI(Creature* creature) +{ + return GetInstanceAI(creature, VioletHoldScriptName); +} + +#endif // VIOLET_HOLD_H_ diff --git a/src/server/scripts/Northrend/zone_borean_tundra.cpp b/src/server/scripts/Northrend/zone_borean_tundra.cpp index 1741a6d928e..2df7940afaf 100644 --- a/src/server/scripts/Northrend/zone_borean_tundra.cpp +++ b/src/server/scripts/Northrend/zone_borean_tundra.cpp @@ -596,12 +596,13 @@ public: switch (IntroPhase) { case 1: - Talk(SAY_START_1); + if (Player* player = GetPlayerForEscort()) + Talk(SAY_START_1, player); IntroPhase = 2; IntroTimer = 7500; break; case 2: - Talk(SAY_END_1); + Talk(SAY_START_2); IntroPhase = 3; IntroTimer = 7500; break; @@ -611,12 +612,13 @@ public: IntroTimer = 0; break; case 4: - Talk(SAY_START_2); + Talk(SAY_END_1); IntroPhase = 5; IntroTimer = 8000; break; case 5: - Talk(SAY_END_2); + if (Player* player = GetPlayerForEscort()) + Talk(SAY_END_2, player); IntroPhase = 6; IntroTimer = 2500; break; @@ -1819,7 +1821,7 @@ public: player->FailQuest(QUEST_GET_ME_OUTA_HERE); } - void UpdateEscortAI(const uint32 /*diff*/) override + void UpdateEscortAI(uint32 /*diff*/) override { if (GetAttack() && UpdateVictim()) { diff --git a/src/server/scripts/Northrend/zone_howling_fjord.cpp b/src/server/scripts/Northrend/zone_howling_fjord.cpp index fe72a2cedf7..ba69a1385d5 100644 --- a/src/server/scripts/Northrend/zone_howling_fjord.cpp +++ b/src/server/scripts/Northrend/zone_howling_fjord.cpp @@ -98,7 +98,7 @@ public: player->FailQuest(QUEST_TRAIL_OF_FIRE); } - void UpdateEscortAI(const uint32 diff) override + void UpdateEscortAI(uint32 diff) override { if (HealthBelowPct(75)) { diff --git a/src/server/scripts/Northrend/zone_storm_peaks.cpp b/src/server/scripts/Northrend/zone_storm_peaks.cpp index d5d9f8ae77e..25bf4826000 100644 --- a/src/server/scripts/Northrend/zone_storm_peaks.cpp +++ b/src/server/scripts/Northrend/zone_storm_peaks.cpp @@ -381,7 +381,7 @@ class npc_hyldsmeet_protodrake : public CreatureScript class npc_hyldsmeet_protodrakeAI : public CreatureAI { public: - npc_hyldsmeet_protodrakeAI(Creature* creature) : CreatureAI(creature), _accessoryRespawnTimer(0), _vehicleKit(creature->GetVehicleKit()) { } + npc_hyldsmeet_protodrakeAI(Creature* creature) : CreatureAI(creature), _accessoryRespawnTimer(0) { } void PassengerBoarded(Unit* who, int8 /*seat*/, bool apply) override { @@ -396,6 +396,7 @@ class npc_hyldsmeet_protodrake : public CreatureScript { //! We need to manually reinstall accessories because the vehicle itself is friendly to players, //! so EnterEvadeMode is never triggered. The accessory on the other hand is hostile and killable. + Vehicle* _vehicleKit = me->GetVehicleKit(); if (_accessoryRespawnTimer && _accessoryRespawnTimer <= diff && _vehicleKit) { _vehicleKit->InstallAllAccessories(true); @@ -407,7 +408,6 @@ class npc_hyldsmeet_protodrake : public CreatureScript private: uint32 _accessoryRespawnTimer; - Vehicle* _vehicleKit; }; CreatureAI* GetAI(Creature* creature) const override diff --git a/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_ambassador_hellmaw.cpp b/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_ambassador_hellmaw.cpp index 9667b4e3bb0..80cc2028cb3 100644 --- a/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_ambassador_hellmaw.cpp +++ b/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_ambassador_hellmaw.cpp @@ -136,7 +136,7 @@ class boss_ambassador_hellmaw : public CreatureScript Talk(SAY_DEATH); } - void UpdateEscortAI(uint32 const diff) override + void UpdateEscortAI(uint32 diff) override { if (!UpdateVictim()) return; diff --git a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_morogrim_tidewalker.cpp b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_morogrim_tidewalker.cpp index b76712fc541..a8d65cc096d 100644 --- a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_morogrim_tidewalker.cpp +++ b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_morogrim_tidewalker.cpp @@ -219,12 +219,12 @@ public: if (WateryGrave_Timer <= diff) { //Teleport 4 players under the waterfalls - Unit* target; GuidSet targets; GuidSet::const_iterator itr; for (uint8 i = 0; i < 4; ++i) { counter = 0; + Unit* target; do { target = SelectTarget(SELECT_TARGET_RANDOM, 1, 50, true); //target players only @@ -257,12 +257,12 @@ public: //WateryGlobules_Timer if (WateryGlobules_Timer <= diff) { - Unit* pGlobuleTarget; GuidSet globules; GuidSet::const_iterator itr; for (uint8 g = 0; g < 4; g++) //one unit can't cast more than one spell per update, so some players have to cast for us XD { counter = 0; + Unit* pGlobuleTarget; do { pGlobuleTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 50, true); diff --git a/src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp b/src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp index f5583c0bc53..0dc75ff8efa 100644 --- a/src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp +++ b/src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp @@ -25,115 +25,236 @@ EndScriptData */ #include "ScriptMgr.h" #include "ScriptedCreature.h" +#include "Spell.h" +#include "SpellScript.h" #include "the_eye.h" -#include "WorldPacket.h" -#include "Opcodes.h" enum Yells { // Kael'thas Speech - SAY_INTRO = 0, - SAY_INTRO_CAPERNIAN = 1, - SAY_INTRO_TELONICUS = 2, - SAY_INTRO_THALADRED = 3, - SAY_INTRO_SANGUINAR = 4, - SAY_PHASE2_WEAPON = 5, - SAY_PHASE3_ADVANCE = 6, - SAY_PHASE4_INTRO2 = 7, - SAY_PHASE5_NUTS = 8, - SAY_SLAY = 9, - SAY_MINDCONTROL = 10, - SAY_GRAVITYLAPSE = 11, - SAY_SUMMON_PHOENIX = 12, - SAY_DEATH = 13, + SAY_INTRO = 0, + SAY_INTRO_CAPERNIAN = 1, + SAY_INTRO_TELONICUS = 2, + SAY_INTRO_THALADRED = 3, + SAY_INTRO_SANGUINAR = 4, + SAY_PHASE2_WEAPON = 5, + SAY_PHASE3_ADVANCE = 6, + SAY_PHASE4_INTRO2 = 7, + SAY_PHASE5_NUTS = 8, + SAY_SLAY = 9, + SAY_MIND_CONTROL = 10, + SAY_GRAVITY_LAPSE = 11, + SAY_SUMMON_PHOENIX = 12, + SAY_DEATH = 13, + EMOTE_PYROBLAST = 14, // Thaladred the Darkener speech - SAY_THALADRED_AGGRO = 0, - SAY_THALADRED_DEATH = 1, - EMOTE_THALADRED_GAZE = 2, + SAY_THALADRED_AGGRO = 0, + SAY_THALADRED_DEATH = 1, + EMOTE_THALADRED_GAZE = 2, //Lord Sanguinar speech - SAY_SANGUINAR_AGGRO = 0, - SAY_SANGUINAR_DEATH = 1, + SAY_SANGUINAR_AGGRO = 0, + SAY_SANGUINAR_DEATH = 1, // Grand Astromancer Capernian speech - SAY_CAPERNIAN_AGGRO = 0, - SAY_CAPERNIAN_DEATH = 1, + SAY_CAPERNIAN_AGGRO = 0, + SAY_CAPERNIAN_DEATH = 1, // Master Engineer Telonicus speech - SAY_TELONICUS_AGGRO = 0, - SAY_TELONICUS_DEATH = 1 + SAY_TELONICUS_AGGRO = 0, + SAY_TELONICUS_DEATH = 1 }; enum Spells { // Phase 2 spells - SPELL_SUMMON_WEAPONS = 36976, - SPELL_SUMMON_WEAPONA = 36958, - SPELL_SUMMON_WEAPONB = 36959, - SPELL_SUMMON_WEAPONC = 36960, - SPELL_SUMMON_WEAPOND = 36961, - SPELL_SUMMON_WEAPONE = 36962, - SPELL_SUMMON_WEAPONF = 36963, - SPELL_SUMMON_WEAPONG = 36964, - SPELL_RES_VISUAL = 24171, + SPELL_SUMMON_WEAPONS = 36976, + SPELL_SUMMON_WEAPONA = 36958, + SPELL_SUMMON_WEAPONB = 36959, + SPELL_SUMMON_WEAPONC = 36960, + SPELL_SUMMON_WEAPOND = 36961, + SPELL_SUMMON_WEAPONE = 36962, + SPELL_SUMMON_WEAPONF = 36963, + SPELL_SUMMON_WEAPONG = 36964, + SPELL_RESSURECTION = 36450, // Phase 4 spells - SPELL_FIREBALL = 22088, //wrong but works with CastCustomSpell - SPELL_PYROBLAST = 36819, - SPELL_FLAME_STRIKE = 36735, - SPELL_FLAME_STRIKE_VIS = 36730, - SPELL_FLAME_STRIKE_DMG = 36731, - SPELL_ARCANE_DISRUPTION = 36834, - SPELL_SHOCK_BARRIER = 36815, - SPELL_PHOENIX_ANIMATION = 36723, - SPELL_MIND_CONTROL = 32830, + SPELL_FIREBALL = 36805, + SPELL_PYROBLAST = 36819, + SPELL_FLAME_STRIKE = 36735, + SPELL_FLAME_STRIKE_VIS = 36730, + SPELL_FLAME_STRIKE_DMG = 36731, + SPELL_ARCANE_DISRUPTION = 36834, + SPELL_SHOCK_BARRIER = 36815, + SPELL_PHOENIX_ANIMATION = 36723, + //SPELL_MIND_CONTROL = 32830, + SPELL_MIND_CONTROL = 36797, + SPELL_BANISH = 40370, // Cast on Phoenix // Phase 5 spells - SPELL_EXPLODE = 36092, - SPELL_FULLPOWER = 36187, - SPELL_KNOCKBACK = 11027, - SPELL_GRAVITY_LAPSE = 34480, - SPELL_GRAVITY_LAPSE_AURA = 39432, - SPELL_NETHER_BEAM = 35873, + SPELL_KAEL_GAINING_POWER = 36091, + SPELL_KAEL_EXPLODES = 36373, + SPELL_KAEL_EXPLODES2 = 36375, + SPELL_KAEL_EXPLODES3 = 36092, + SPELL_KAEL_EXPLODES4 = 36354, + SPELL_KAEL_STUNNED = 36185, + SPELL_FULLPOWER = 36187, + SPELL_NETHER_BEAM = 35873, + SPELL_PURE_NETHER_BEAM = 36196, + SPELL_SUMMON_NETHER_VAPOR = 35865, + + // Visual, phase transition spells + SPELL_NETHER_BEAM_VISUAL = 36089, // Channeled by trigger on Kael'thas. + SPELL_NETHER_BEAM_VISUAL2 = 36090, // Channeled by trigger on Kael'thas. + SPELL_NETHER_BEAM_VISUAL3 = 36364, // Cast by Kael'thas on himself, purple glowing effect. + + // Gravity Lapse spells + SPELL_GRAVITY_LAPSE = 35941, + SPELL_GRAVITY_LAPSE_PERIODIC = 34480, + SPELL_GRAVITY_LAPSE_FLIGHT_AURA = 39432, // Cast by players on themselves, allows flight + + // 25 teleport spells, one for each raid member... + SPELL_GRAVITY_LAPSE_TELE_FRONT = 35966, + SPELL_GRAVITY_LAPSE_TELE_FRONT_RIGHT = 35967, + SPELL_GRAVITY_LAPSE_TELE_FRONT_LEFT = 35968, + SPELL_GRAVITY_LAPSE_TELE_CASTER_BACK_RIGHT = 35969, + SPELL_GRAVITY_LAPSE_TELE_BACK = 35970, + SPELL_GRAVITY_LAPSE_TELE_TO_CASTER = 35971, + SPELL_GRAVITY_LAPSE_TELE_BACK_LEFT = 35972, + SPELL_GRAVITY_LAPSE_TELE_FRONT_LEFT2 = 35973, + SPELL_GRAVITY_LAPSE_TELE_CASTER_LEFT = 35974, + SPELL_GRAVITY_LAPSE_TELE_CASTER_LEFT2 = 35975, + SPELL_GRAVITY_LAPSE_TELE_FRONT_LEFT3 = 35976, + SPELL_GRAVITY_LAPSE_TELE_CASTER_BACK_LEFT = 35977, + SPELL_GRAVITY_LAPSE_TELE_CASTER_FRONT = 35978, + SPELL_GRAVITY_LAPSE_TELE_CASTER_BACK = 35979, + SPELL_GRAVITY_LAPSE_TELE_FRONT_RIGHT2 = 35980, + SPELL_GRAVITY_LAPSE_TELE_CASTER_RIGHT = 35981, + SPELL_GRAVITY_LAPSE_TELE_CASTER_FRONT_RIGHT = 35982, + SPELL_GRAVITY_LAPSE_TELE_CASTER_FRONT2 = 35983, + SPELL_GRAVITY_LAPSE_TELE_CASTER_FRONT_LEFT = 35984, + SPELL_GRAVITY_LAPSE_TELE_CASTER_LEFT3 = 35985, + SPELL_GRAVITY_LAPSE_TELE_CASTER_BACK_LEFT2 = 35986, + SPELL_GRAVITY_LAPSE_TELE_CASTER_BACK2 = 35987, + SPELL_GRAVITY_LAPSE_TELE_CASTER_BACK_RIGHT2 = 35988, + SPELL_GRAVITY_LAPSE_TELE_CASTER_RIGHT2 = 35989, + SPELL_GRAVITY_LAPSE_TELE_CASTER_BACK_RIGHT3 = 35990, // Thaladred the Darkener spells - SPELL_PSYCHIC_BLOW = 10689, - SPELL_SILENCE = 30225, + SPELL_PSYCHIC_BLOW = 10689, + SPELL_SILENCE = 30225, // Lord Sanguinar spells - SPELL_BELLOWING_ROAR = 40636, + SPELL_BELLOWING_ROAR = 40636, // Grand Astromancer Capernian spells - SPELL_CAPERNIAN_FIREBALL = 36971, - SPELL_CONFLAGRATION = 37018, - SPELL_ARCANE_EXPLOSION = 36970, + SPELL_CAPERNIAN_FIREBALL = 36971, + SPELL_CONFLAGRATION = 37018, + SPELL_ARCANE_EXPLOSION = 36970, //Master Engineer Telonicus spells - SPELL_BOMB = 37036, - SPELL_REMOTE_TOY = 37027, + SPELL_BOMB = 37036, + SPELL_REMOTE_TOY = 37027, //Nether Vapor spell - SPELL_NETHER_VAPOR = 35859, + SPELL_NETHER_VAPOR = 35859, //Phoenix spell - SPELL_BURN = 36720, - SPELL_EMBER_BLAST = 34341, - SPELL_REBIRTH = 41587 + SPELL_BURN = 36720, + SPELL_EMBER_BLAST = 34341, + SPELL_REBIRTH = 41587 }; enum Creatures { - NPC_PHOENIX = 21362, - NPC_PHOENIX_EGG = 21364 + NPC_PHOENIX = 21362, + NPC_PHOENIX_EGG = 21364 }; enum Models { //Phoenix egg and phoenix model - MODEL_ID_PHOENIX = 19682, - MODEL_ID_PHOENIX_EGG = 20245 + MODEL_ID_PHOENIX = 19682, + MODEL_ID_PHOENIX_EGG = 20245 }; -enum Misc +enum Actions { - MAX_ADVISORS = 4 + ACTION_START_ENCOUNTER, + ACTION_REVIVE_ADVISORS, + ACTION_PREPARE_ADVISORS, + ACTION_ACTIVE_ADVISOR, + ACTION_SCHEDULE_COMBAT_EVENTS +}; + +enum Advisors +{ + ADVISOR_THALADRED, + ADVISOR_SANGUINAR, + ADVISOR_CAPERNIAN, + ADVISOR_TELONICUS, + MAX_ADVISORS = 4, + + MAX_DEFEATED_ADVISORS = 4, + MAX_KILLED_ADVISORS = 8 +}; + +enum Events +{ + EVENT_START_ENCOUNTER = 1, + EVENT_ACTIVE_ADVISOR, + EVENT_SUMMON_WEAPONS, + EVENT_REVIVE_ADVISORS, + EVENT_ENGAGE_COMBAT, + EVENT_FULL_POWER, + EVENT_FIREBALL, + EVENT_ARCANE_DISRUPTION, + EVENT_FLAMESTRIKE, + EVENT_MIND_CONTROL, + EVENT_SUMMON_PHOENIX, + EVENT_SHOCK_BARRIER, + EVENT_PYROBLAST, + EVENT_PYROBLAST_CAST, + EVENT_GAINING_POWER, + EVENT_END_TRANSITION, + EVENT_GRAVITY_LAPSE, + EVENT_NETHER_BEAM, + + // Movement updates + EVENT_TRANSITION_1, + EVENT_TRANSITION_2, + EVENT_TRANSITION_3, + EVENT_TRANSITION_4, + EVENT_TRANSITION_5, + EVENT_TRANSITION_6, + + // Phase transition + EVENT_SIZE_INCREASE, + EVENT_EXPLODE, + EVENT_RESUME_COMBAT, + + // Advisors + EVENT_DELAYED_RESSURECTION, + + // Event groups + EVENT_GROUP_COMBAT = 1, // Default abilities + EVENT_GROUP_SPECIAL = 2 // Special abilities (Pyroblast, Nether Beam, Shock Barrier) +}; + +enum Phases +{ + PHASE_NONE, + PHASE_INTRO, + PHASE_REVIVED_ADVISORS, + PHASE_COMBAT, + PHASE_TRANSITION +}; + +enum MovementPoints +{ + POINT_START_TRANSITION = 1, + POINT_TRANSITION_CENTER_ASCENDING = 2, + POINT_TRANSITION_HALFWAY_ASCENDING = 3, + POINT_TRANSITION_TOP = 4, + POINT_TRANSITION_HALFWAY_DESCENDING = 5, + POINT_END_TRANSITION = 6 }; uint32 m_auiSpellSummonWeapon[]= @@ -142,61 +263,83 @@ uint32 m_auiSpellSummonWeapon[]= SPELL_SUMMON_WEAPONE, SPELL_SUMMON_WEAPONF, SPELL_SUMMON_WEAPONG }; +uint32 GravityLapseSpells[] = +{ + SPELL_GRAVITY_LAPSE_TELE_FRONT, + SPELL_GRAVITY_LAPSE_TELE_FRONT_RIGHT, + SPELL_GRAVITY_LAPSE_TELE_FRONT_LEFT, + SPELL_GRAVITY_LAPSE_TELE_CASTER_BACK_RIGHT, + SPELL_GRAVITY_LAPSE_TELE_BACK, + SPELL_GRAVITY_LAPSE_TELE_TO_CASTER, + SPELL_GRAVITY_LAPSE_TELE_BACK_LEFT, + SPELL_GRAVITY_LAPSE_TELE_FRONT_LEFT2, + SPELL_GRAVITY_LAPSE_TELE_CASTER_LEFT, + SPELL_GRAVITY_LAPSE_TELE_CASTER_LEFT2, + SPELL_GRAVITY_LAPSE_TELE_FRONT_LEFT3, + SPELL_GRAVITY_LAPSE_TELE_CASTER_BACK_LEFT, + SPELL_GRAVITY_LAPSE_TELE_CASTER_FRONT, + SPELL_GRAVITY_LAPSE_TELE_CASTER_BACK, + SPELL_GRAVITY_LAPSE_TELE_FRONT_RIGHT2, + SPELL_GRAVITY_LAPSE_TELE_CASTER_RIGHT, + SPELL_GRAVITY_LAPSE_TELE_CASTER_FRONT_RIGHT, + SPELL_GRAVITY_LAPSE_TELE_CASTER_FRONT2, + SPELL_GRAVITY_LAPSE_TELE_CASTER_FRONT_LEFT, + SPELL_GRAVITY_LAPSE_TELE_CASTER_LEFT3, + SPELL_GRAVITY_LAPSE_TELE_CASTER_BACK_LEFT2, + SPELL_GRAVITY_LAPSE_TELE_CASTER_BACK2, + SPELL_GRAVITY_LAPSE_TELE_CASTER_BACK_RIGHT2, + SPELL_GRAVITY_LAPSE_TELE_CASTER_RIGHT2, + SPELL_GRAVITY_LAPSE_TELE_CASTER_BACK_RIGHT3 +}; + const float CAPERNIAN_DISTANCE = 20.0f; //she casts away from the target //const float KAEL_VISIBLE_RANGE = 50.0f; -const float afGravityPos[3] = {795.0f, 0.0f, 70.0f}; +Position const afGravityPos = {795.0f, 0.0f, 70.0f}; -#define TIME_PHASE_2_3 120000 -#define TIME_PHASE_3_4 180000 +Position const TransitionPos[6] = +{ + // First two values are not static, they seem to differ on each sniff. + { 794.0522f, -0.96732f, 48.97848f, 0.0f }, + { 796.641f, -0.5888171f, 48.72847f, 3.176499f }, + { 795.007f, -0.471827f, 75.0f, 0.0f }, + { 795.007f, -0.471827f, 75.0f, 3.133458f }, + { 792.419f, -0.504778f, 50.0505f, 0.0f }, + { 792.419f, -0.504778f, 50.0505f, 3.130386f } +}; -//Base AI for Advisors struct advisorbase_ai : public ScriptedAI { advisorbase_ai(Creature* creature) : ScriptedAI(creature) { Initialize(); instance = creature->GetInstanceScript(); - m_bDoubled_Health = false; } void Initialize() { - FakeDeath = false; - DelayRes_Timer = 0; + _hasRessurrected = false; + _inFakeDeath = false; DelayRes_Target.Clear(); } - InstanceScript* instance; - bool FakeDeath; - bool m_bDoubled_Health; - uint32 DelayRes_Timer; - ObjectGuid DelayRes_Target; - void Reset() override { - if (m_bDoubled_Health) - { - me->SetMaxHealth(me->GetMaxHealth() / 2); - m_bDoubled_Health = false; - } - Initialize(); me->SetStandState(UNIT_STAND_STATE_STAND); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_STUNNED); //reset encounter - if (instance->GetData(DATA_KAELTHASEVENT) == 1 || instance->GetData(DATA_KAELTHASEVENT) == 3) + if (instance->GetBossState(DATA_KAELTHAS) == IN_PROGRESS) if (Creature* Kaelthas = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_KAELTHAS))) Kaelthas->AI()->EnterEvadeMode(); } void MoveInLineOfSight(Unit* who) override - { - if (!who || FakeDeath || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + if (!who || _inFakeDeath || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) return; ScriptedAI::MoveInLineOfSight(who); @@ -204,69 +347,61 @@ struct advisorbase_ai : public ScriptedAI void AttackStart(Unit* who) override { - if (!who || FakeDeath || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + if (!who || _inFakeDeath || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) return; ScriptedAI::AttackStart(who); } - void Revive(Unit* /*Target*/) + void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - // double health for phase 3 - me->SetMaxHealth(me->GetMaxHealth() * 2); - m_bDoubled_Health = true; - me->SetFullHealth(); - me->SetStandState(UNIT_STAND_STATE_STAND); - - DoCast(me, SPELL_RES_VISUAL, false); - DelayRes_Timer = 2000; + if (spell->Id == SPELL_RESSURECTION) + { + _hasRessurrected = true; + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_STUNNED); + me->SetStandState(UNIT_STAND_STATE_STAND); + events.ScheduleEvent(EVENT_DELAYED_RESSURECTION, 2000); + } } void DamageTaken(Unit* killer, uint32 &damage) override { - if (damage < me->GetHealth()) - return; - - //Prevent glitch if in fake death - if (FakeDeath && instance->GetData(DATA_KAELTHASEVENT) != 0) - { - damage = 0; - return; - } - - //Don't really die in phase 1 & 3, only die after that - if (instance->GetData(DATA_KAELTHASEVENT) != 0) + if (damage >= me->GetHealth() && !_inFakeDeath && !_hasRessurrected) { //prevent death damage = 0; - FakeDeath = true; + _inFakeDeath = true; me->InterruptNonMeleeSpells(false); me->SetHealth(0); - me->StopMoving(); me->ClearComboPointHolders(); me->RemoveAllAurasOnDeath(); me->ModifyAuraState(AURA_STATE_HEALTHLESS_20_PERCENT, false); me->ModifyAuraState(AURA_STATE_HEALTHLESS_35_PERCENT, false); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->ClearAllReactives(); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_STUNNED); me->SetTarget(ObjectGuid::Empty); - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MoveIdle(); me->SetStandState(UNIT_STAND_STATE_DEAD); + me->GetMotionMaster()->Clear(); JustDied(killer); } } + void JustDied(Unit* /*killer*/) override + { + if (Creature* kael = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_KAELTHAS))) + kael->AI()->DoAction(ACTION_ACTIVE_ADVISOR); + } + void UpdateAI(uint32 diff) override { - if (DelayRes_Timer) + if (_hasRessurrected) + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) { - if (DelayRes_Timer <= diff) + if (eventId == EVENT_DELAYED_RESSURECTION) { - DelayRes_Timer = 0; - FakeDeath = false; + _inFakeDeath = false; Unit* Target = ObjectAccessor::GetUnit(*me, DelayRes_Target); if (!Target) @@ -277,9 +412,15 @@ struct advisorbase_ai : public ScriptedAI me->GetMotionMaster()->Clear(); me->GetMotionMaster()->MoveChase(Target); me->AddThreat(Target, 0.0f); - } else DelayRes_Timer -= diff; + } } } + public: + EventMap events; + InstanceScript* instance; + bool _hasRessurrected; + bool _inFakeDeath; + ObjectGuid DelayRes_Target; }; class boss_kaelthas : public CreatureScript @@ -293,150 +434,199 @@ class boss_kaelthas : public CreatureScript boss_kaelthasAI(Creature* creature) : BossAI(creature, DATA_KAELTHAS) { Initialize(); - PhaseSubphase = 0; - Phase_Timer = 0; } void Initialize() { - Fireball_Timer = 5000 + rand32() % 10000; - ArcaneDisruption_Timer = 45000; - MindControl_Timer = 40000; - Phoenix_Timer = 50000; - ShockBarrier_Timer = 60000; - FlameStrike_Timer = 30000; - GravityLapse_Timer = 20000; - GravityLapse_Phase = 0; - NetherBeam_Timer = 8000; - NetherVapor_Timer = 10000; - PyrosCast = 0; - Phase = 0; - InGravityLapse = false; - IsCastingFireball = false; - ChainPyros = false; + _advisorCounter = 0; + _pyrosCast = 0; + _netherbeamsCast = 0; + _phase = PHASE_NONE; + _scaleStage = 0; + _hasFullPower = false; } - uint32 Fireball_Timer; - uint32 ArcaneDisruption_Timer; - uint32 Phoenix_Timer; - uint32 ShockBarrier_Timer; - uint32 GravityLapse_Timer; - uint32 GravityLapse_Phase; - uint32 NetherBeam_Timer; - uint32 NetherVapor_Timer; - uint32 FlameStrike_Timer; - uint32 MindControl_Timer; - uint32 Phase; - uint32 PhaseSubphase; //generic - uint32 Phase_Timer; //generic timer - uint32 PyrosCast; - - bool InGravityLapse; - bool IsCastingFireball; - bool ChainPyros; - - ObjectGuid m_auiAdvisorGuid[MAX_ADVISORS]; - void Reset() override { Initialize(); - - if (me->IsInCombat()) - PrepareAdvisors(); - - _Reset(); - + DoAction(ACTION_PREPARE_ADVISORS); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - - instance->SetData(DATA_KAELTHASEVENT, 0); + me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE); + me->SetDisableGravity(false); + me->SetTarget(ObjectGuid::Empty); + me->SetObjectScale(1.0f); + BossAI::Reset(); } - void PrepareAdvisors() + void JustReachedHome() override { - for (uint8 i = 0; i < MAX_ADVISORS; ++i) - { - if (Creature* creature = ObjectAccessor::GetCreature(*me, m_auiAdvisorGuid[i])) - { - creature->Respawn(); - creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - creature->setFaction(me->getFaction()); - creature->AI()->EnterEvadeMode(); - } - } + BossAI::JustReachedHome(); + + // Rebuild the surrounding environment. + if (GameObject* statue = instance->GetGameObject(DATA_KAEL_STATUE_LEFT)) + statue->ResetDoorOrButton(); + + if (GameObject* statue = instance->GetGameObject(DATA_KAEL_STATUE_RIGHT)) + statue->ResetDoorOrButton(); + + if (GameObject* window = instance->GetGameObject(DATA_TEMPEST_BRIDGE_WINDOW)) + window->ResetDoorOrButton(); } - void StartEvent() + void DoAction(int32 action) override { - m_auiAdvisorGuid[0] = instance->GetGuidData(DATA_THALADREDTHEDARKENER); - m_auiAdvisorGuid[1] = instance->GetGuidData(DATA_LORDSANGUINAR); - m_auiAdvisorGuid[2] = instance->GetGuidData(DATA_GRANDASTROMANCERCAPERNIAN); - m_auiAdvisorGuid[3] = instance->GetGuidData(DATA_MASTERENGINEERTELONICUS); - - if (!m_auiAdvisorGuid[0] || !m_auiAdvisorGuid[1] || !m_auiAdvisorGuid[2] || !m_auiAdvisorGuid[3]) + switch (action) { - TC_LOG_ERROR("scripts", "Kael'Thas One or more advisors missing, Skipping Phases 1-3"); + case ACTION_START_ENCOUNTER: + Talk(SAY_INTRO); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - Talk(SAY_PHASE4_INTRO2); + _advisorGuid[ADVISOR_THALADRED] = instance->GetGuidData(DATA_THALADREDTHEDARKENER); + _advisorGuid[ADVISOR_SANGUINAR] = instance->GetGuidData(DATA_LORDSANGUINAR); + _advisorGuid[ADVISOR_CAPERNIAN] = instance->GetGuidData(DATA_GRANDASTROMANCERCAPERNIAN); + _advisorGuid[ADVISOR_TELONICUS] = instance->GetGuidData(DATA_MASTERENGINEERTELONICUS); - Phase = 4; + _phase = PHASE_INTRO; + instance->SetBossState(DATA_KAELTHAS, IN_PROGRESS); + events.ScheduleEvent(EVENT_START_ENCOUNTER, 23000); + break; + case ACTION_PREPARE_ADVISORS: + for (uint8 i = 0; i < MAX_ADVISORS; ++i) + { + if (Creature* creature = ObjectAccessor::GetCreature(*me, _advisorGuid[i])) + { + creature->Respawn(true); + creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + creature->AI()->EnterEvadeMode(); + } + } + break; + case ACTION_ACTIVE_ADVISOR: + // They have already been active, so we are not handling new ones, just counting their death. + if (_phase == PHASE_REVIVED_ADVISORS) + ++_advisorCounter; - instance->SetData(DATA_KAELTHASEVENT, 4); - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) - AttackStart(target); - } - else - { - PrepareAdvisors(); - - Talk(SAY_INTRO); - - instance->SetData(DATA_KAELTHASEVENT, 1); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - - PhaseSubphase = 0; - Phase_Timer = 23000; - Phase = 1; + switch (_advisorCounter) + { + case ADVISOR_THALADRED: + Talk(SAY_INTRO_THALADRED); + events.ScheduleEvent(EVENT_ACTIVE_ADVISOR, 7000); + break; + case ADVISOR_SANGUINAR: + Talk(SAY_INTRO_SANGUINAR); + events.ScheduleEvent(EVENT_ACTIVE_ADVISOR, 12500); + break; + case ADVISOR_CAPERNIAN: + Talk(SAY_INTRO_CAPERNIAN); + events.ScheduleEvent(EVENT_ACTIVE_ADVISOR, 7000); + break; + case ADVISOR_TELONICUS: + Talk(SAY_INTRO_TELONICUS); + events.ScheduleEvent(EVENT_ACTIVE_ADVISOR, 8400); + break; + case MAX_DEFEATED_ADVISORS: + // Every advisor defeated - Phase 2 starts. + Talk(SAY_PHASE2_WEAPON); + events.ScheduleEvent(EVENT_SUMMON_WEAPONS, 3500); + break; + case MAX_KILLED_ADVISORS: + // Every advisor killed - Phase 3 starts. + events.ScheduleEvent(EVENT_ENGAGE_COMBAT, 5000); + break; + default: + break; + } + break; + case ACTION_SCHEDULE_COMBAT_EVENTS: + _phase = PHASE_COMBAT; + events.SetPhase(PHASE_COMBAT); + events.ScheduleEvent(EVENT_FIREBALL, 1000, EVENT_GROUP_COMBAT, PHASE_COMBAT); + events.ScheduleEvent(EVENT_ARCANE_DISRUPTION, 45000, EVENT_GROUP_COMBAT, PHASE_COMBAT); + events.ScheduleEvent(EVENT_FLAMESTRIKE, 30000, EVENT_GROUP_COMBAT, PHASE_COMBAT); + events.ScheduleEvent(EVENT_MIND_CONTROL, 40000, EVENT_GROUP_COMBAT, PHASE_COMBAT); + events.ScheduleEvent(EVENT_SUMMON_PHOENIX, 50000, EVENT_GROUP_COMBAT, PHASE_COMBAT); + break; + default: + break; } } void MoveInLineOfSight(Unit* who) override { - if (!me->HasUnitState(UNIT_STATE_STUNNED) && me->CanCreatureAttack(who)) + if (_phase == PHASE_NONE && me->IsValidAttackTarget(who) && me->IsWithinDistInMap(who, 30.0f)) { - if (!me->CanFly() && me->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE) - return; - - float attackRadius = me->GetAttackDistance(who); - if (me->IsWithinDistInMap(who, attackRadius) && me->IsWithinLOSInMap(who)) - { - if (!me->GetVictim() && Phase >= 4) - { - who->RemoveAurasByType(SPELL_AURA_MOD_STEALTH); - AttackStart(who); - } - else if (me->GetMap()->IsDungeon()) - { - if (!instance->GetData(DATA_KAELTHASEVENT) && !Phase) - StartEvent(); - - who->SetInCombatWith(me); - me->AddThreat(who, 0.0f); - } - } + DoAction(ACTION_START_ENCOUNTER); + who->SetInCombatWith(me); + me->AddThreat(who, 0.0f); + me->SetTarget(who->GetGUID()); } } - void EnterCombat(Unit* /*who*/) override + void DamageTaken(Unit* attacker, uint32& damage) override { - if (!instance->GetData(DATA_KAELTHASEVENT) && !Phase) - StartEvent(); + if (_phase == PHASE_NONE) + { + DoAction(ACTION_START_ENCOUNTER); + me->SetTarget(attacker->GetGUID()); + } - instance->SetBossState(DATA_KAELTHAS, IN_PROGRESS); + if (!_hasFullPower && me->HealthBelowPctDamaged(50, damage)) + { + _hasFullPower = true; + me->AttackStop(); + me->InterruptNonMeleeSpells(false); + events.CancelEventGroup(EVENT_GROUP_COMBAT); + events.CancelEventGroup(EVENT_GROUP_SPECIAL); + events.SetPhase(PHASE_TRANSITION); + me->SetReactState(REACT_PASSIVE); + me->GetMotionMaster()->MovePoint(POINT_START_TRANSITION, TransitionPos[0]); + } + } + + void MovementInform(uint32 type, uint32 point) override + { + if (type != POINT_MOTION_TYPE) + return; + + switch (point) + { + case POINT_START_TRANSITION: + events.ScheduleEvent(EVENT_TRANSITION_1, 1000); + break; + case POINT_TRANSITION_CENTER_ASCENDING: + me->SetFacingTo(float(M_PI)); + Talk(SAY_PHASE5_NUTS); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetDisableGravity(true); + //me->SetHover(true); -- Set in sniffs, but breaks his visual. + events.ScheduleEvent(EVENT_TRANSITION_2, 2000); + events.ScheduleEvent(EVENT_SIZE_INCREASE, 5000); + break; + case POINT_TRANSITION_HALFWAY_ASCENDING: + DoCast(me, SPELL_NETHER_BEAM_VISUAL3, true); + events.ScheduleEvent(EVENT_TRANSITION_3, 1000); + break; + case POINT_TRANSITION_TOP: + events.ScheduleEvent(EVENT_EXPLODE, 10000); + break; + case POINT_TRANSITION_HALFWAY_DESCENDING: + events.ScheduleEvent(EVENT_TRANSITION_5, 2000); + break; + case POINT_END_TRANSITION: + me->SetReactState(REACT_AGGRESSIVE); + me->InterruptNonMeleeSpells(false); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->RemoveAurasDueToSpell(SPELL_FULLPOWER); + + if (Unit* target = SelectTarget(SELECT_TARGET_TOPAGGRO, 0)) + AttackStart(target); + + DoAction(ACTION_SCHEDULE_COMBAT_EVENTS); + events.ScheduleEvent(EVENT_GRAVITY_LAPSE, 10000, EVENT_GROUP_COMBAT, PHASE_COMBAT); + break; + default: + break; + } } void KilledUnit(Unit* /*victim*/) override @@ -456,557 +646,224 @@ class boss_kaelthas : public CreatureScript } } - void JustDied(Unit* /*killer*/) override + void JustDied(Unit* killer) override { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - Talk(SAY_DEATH); - - instance->SetData(DATA_KAELTHASEVENT, 0); - - for (uint8 i = 0; i < MAX_ADVISORS; ++i) - { - if (Unit* pAdvisor = ObjectAccessor::GetUnit(*me, m_auiAdvisorGuid[i])) - pAdvisor->Kill(pAdvisor); - } - _JustDied(); + BossAI::JustDied(killer); } void UpdateAI(uint32 diff) override { - //Phase 1 - switch (Phase) + if (_phase == PHASE_COMBAT) + if (!UpdateVictim()) + return; + + events.Update(diff); + + // SPELL_KAEL_GAINING_POWER and SPELL_KAEL_STUNNED are channeling spells that need to be interrupted during his transition. + if (me->HasUnitState(UNIT_STATE_CASTING) && !me->FindCurrentSpellBySpellId(SPELL_KAEL_GAINING_POWER) && !me->FindCurrentSpellBySpellId(SPELL_KAEL_STUNNED)) + return; + + while (uint32 eventId = events.ExecuteEvent()) { - case 1: + switch (eventId) { - Unit* target = NULL; - Creature* Advisor = NULL; - - //Subphase switch - switch (PhaseSubphase) - { - //Subphase 1 - Start - case 0: - if (Phase_Timer <= diff) - { - Talk(SAY_INTRO_THALADRED); - - //start advisor within 7 seconds - Phase_Timer = 7000; - ++PhaseSubphase; - } else Phase_Timer -= diff; - break; - - //Subphase 1 - Unlock advisor - case 1: - if (Phase_Timer <= diff) - { - Advisor = (ObjectAccessor::GetCreature(*me, m_auiAdvisorGuid[0])); - - if (Advisor) - { - Advisor->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - Advisor->setFaction(me->getFaction()); - - target = SelectTarget(SELECT_TARGET_RANDOM, 0); - if (target) - Advisor->AI()->AttackStart(target); - } - - ++PhaseSubphase; - } else Phase_Timer -= diff; - break; - - //Subphase 2 - Start - case 2: - Advisor = (ObjectAccessor::GetCreature(*me, m_auiAdvisorGuid[0])); - - if (Advisor && (Advisor->getStandState() == UNIT_STAND_STATE_DEAD)) - { - Talk(SAY_INTRO_SANGUINAR); - - //start advisor within 12.5 seconds - Phase_Timer = 12500; - ++PhaseSubphase; - } - break; - - //Subphase 2 - Unlock advisor - case 3: - if (Phase_Timer <= diff) - { - Advisor = (ObjectAccessor::GetCreature(*me, m_auiAdvisorGuid[1])); - - if (Advisor) - { - Advisor->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - Advisor->setFaction(me->getFaction()); - - target = SelectTarget(SELECT_TARGET_RANDOM, 0); - if (target) - Advisor->AI()->AttackStart(target); - } - - ++PhaseSubphase; - } else Phase_Timer -= diff; - break; - - //Subphase 3 - Start - case 4: - Advisor = (ObjectAccessor::GetCreature(*me, m_auiAdvisorGuid[1])); - - if (Advisor && (Advisor->getStandState() == UNIT_STAND_STATE_DEAD)) - { - Talk(SAY_INTRO_CAPERNIAN); - - //start advisor within 7 seconds - Phase_Timer = 7000; - ++PhaseSubphase; - } - break; - - //Subphase 3 - Unlock advisor - case 5: - if (Phase_Timer <= diff) - { - Advisor = (ObjectAccessor::GetCreature(*me, m_auiAdvisorGuid[2])); - - if (Advisor) - { - Advisor->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - Advisor->setFaction(me->getFaction()); - - target = SelectTarget(SELECT_TARGET_RANDOM, 0); - if (target) - Advisor->AI()->AttackStart(target); - } - - ++PhaseSubphase; - } else Phase_Timer -= diff; - break; - - //Subphase 4 - Start - case 6: - Advisor = (ObjectAccessor::GetCreature(*me, m_auiAdvisorGuid[2])); - - if (Advisor && (Advisor->getStandState() == UNIT_STAND_STATE_DEAD)) - { - Talk(SAY_INTRO_TELONICUS); - - //start advisor within 8.4 seconds - Phase_Timer = 8400; - ++PhaseSubphase; - } - break; - - //Subphase 4 - Unlock advisor - case 7: - if (Phase_Timer <= diff) - { - Advisor = (ObjectAccessor::GetCreature(*me, m_auiAdvisorGuid[3])); - - if (Advisor) - { - Advisor->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - Advisor->setFaction(me->getFaction()); - - target = SelectTarget(SELECT_TARGET_RANDOM, 0); - if (target) - Advisor->AI()->AttackStart(target); - } - - Phase_Timer = 3000; - ++PhaseSubphase; - } else Phase_Timer -= diff; - break; - - //End of phase 1 - case 8: - Advisor = (ObjectAccessor::GetCreature(*me, m_auiAdvisorGuid[3])); - - if (Advisor && (Advisor->getStandState() == UNIT_STAND_STATE_DEAD)) - { - Phase = 2; - instance->SetData(DATA_KAELTHASEVENT, 2); - - Talk(SAY_PHASE2_WEAPON); - - PhaseSubphase = 0; - Phase_Timer = 3500; - DoCast(me, SPELL_SUMMON_WEAPONS); - } - break; - } - } - break; - - case 2: - { - if (PhaseSubphase == 0) - { - if (Phase_Timer <= diff) + case EVENT_START_ENCOUNTER: + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED); + DoAction(ACTION_ACTIVE_ADVISOR); + break; + case EVENT_ACTIVE_ADVISOR: + if (Creature* advisor = ObjectAccessor::GetCreature(*me, _advisorGuid[_advisorCounter])) { - PhaseSubphase = 1; - } - else - Phase_Timer -= diff; - } + advisor->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - //Spawn weapons - if (PhaseSubphase == 1) + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) + advisor->AI()->AttackStart(target); + } + ++_advisorCounter; + break; + case EVENT_SUMMON_WEAPONS: { DoCast(me, SPELL_SUMMON_WEAPONS, false); - uint8 uiMaxWeapon = sizeof(m_auiSpellSummonWeapon)/sizeof(uint32); + uint8 uiMaxWeapon = sizeof(m_auiSpellSummonWeapon) / sizeof(uint32); for (uint32 i = 0; i < uiMaxWeapon; ++i) DoCast(me, m_auiSpellSummonWeapon[i], true); - PhaseSubphase = 2; - Phase_Timer = TIME_PHASE_2_3; + events.ScheduleEvent(EVENT_REVIVE_ADVISORS, 120000); + break; } - - if (PhaseSubphase == 2) - { - if (Phase_Timer <= diff) - { - Talk(SAY_PHASE3_ADVANCE); - instance->SetData(DATA_KAELTHASEVENT, 3); - Phase = 3; - PhaseSubphase = 0; - } - else - Phase_Timer -= diff; - } - } - break; - - case 3: - { - if (PhaseSubphase == 0) - { - //Respawn advisors - Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0); - - Creature* Advisor; - for (uint8 i = 0; i < MAX_ADVISORS; ++i) - { - Advisor = ObjectAccessor::GetCreature(*me, m_auiAdvisorGuid[i]); - - if (!Advisor) - TC_LOG_ERROR("scripts", "SD2: Kael'Thas Advisor %u does not exist. Possibly despawned? Incorrectly Killed?", i); - else - ENSURE_AI(advisorbase_ai, Advisor->AI())->Revive(target); - } - - PhaseSubphase = 1; - Phase_Timer = TIME_PHASE_3_4; - } - - if (Phase_Timer <= diff) - { + case EVENT_REVIVE_ADVISORS: + _phase = PHASE_REVIVED_ADVISORS; + Talk(SAY_PHASE3_ADVANCE); + DoCast(me, SPELL_RESSURECTION); + break; + case EVENT_ENGAGE_COMBAT: Talk(SAY_PHASE4_INTRO2); - Phase = 4; - - instance->SetData(DATA_KAELTHASEVENT, 4); // Sometimes people can collect Aggro in Phase 1-3. Reset threat before releasing Kael. DoResetThreat(); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_PACIFIED); if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) AttackStart(target); - Phase_Timer = 30000; - } - else - Phase_Timer -= diff; - } - break; + DoAction(ACTION_SCHEDULE_COMBAT_EVENTS); + events.ScheduleEvent(EVENT_PYROBLAST, 60000, EVENT_GROUP_COMBAT, PHASE_COMBAT); + break; + case EVENT_FIREBALL: + DoCastVictim(SPELL_FIREBALL); + events.ScheduleEvent(EVENT_FIREBALL, 2500, EVENT_GROUP_COMBAT, PHASE_COMBAT); + break; + case EVENT_ARCANE_DISRUPTION: + DoCastVictim(SPELL_ARCANE_DISRUPTION, true); + events.ScheduleEvent(EVENT_ARCANE_DISRUPTION, 60000, EVENT_GROUP_COMBAT, PHASE_COMBAT); + break; + case EVENT_FLAMESTRIKE: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) + DoCast(target, SPELL_FLAME_STRIKE); - case 4: - case 5: - case 6: - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //Fireball_Timer - if (!InGravityLapse && !ChainPyros && Phase != 5) - { - if (Fireball_Timer <= diff) - { - if (!IsCastingFireball) - { - if (!me->IsNonMeleeSpellCast(false)) - { - //interruptable - me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_INTERRUPT_CAST, false); - int32 dmg = 20000 + rand32() % 5000; - me->CastCustomSpell(me->GetVictim(), SPELL_FIREBALL, &dmg, 0, 0, false); - IsCastingFireball = true; - Fireball_Timer = 2500; - } - } - else - { - //apply resistance - me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_INTERRUPT_CAST, true); - IsCastingFireball = false; - Fireball_Timer = 5000 + rand32() % 10000; - } - } - else - Fireball_Timer -= diff; - - //ArcaneDisruption_Timer - if (ArcaneDisruption_Timer <= diff) - { - DoCastVictim(SPELL_ARCANE_DISRUPTION, true); - ArcaneDisruption_Timer = 60000; - } - else - ArcaneDisruption_Timer -= diff; - - if (FlameStrike_Timer <= diff) - { - if (Unit* unit = SelectTarget(SELECT_TARGET_RANDOM, 0)) - DoCast(unit, SPELL_FLAME_STRIKE); - - FlameStrike_Timer = 30000; - } - else - FlameStrike_Timer -= diff; - - if (MindControl_Timer <= diff) - { - if (me->getThreatManager().getThreatList().size() >= 2) - for (uint32 i = 0; i < 3; ++i) - { - TC_LOG_DEBUG("scripts", "Kael'Thas mind control not supported."); - //DoCast(unit, SPELL_MIND_CONTROL); - } - - MindControl_Timer = 60000; - } - else - MindControl_Timer -= diff; - } - - //Phoenix_Timer - if (Phoenix_Timer <= diff) - { + events.ScheduleEvent(EVENT_FLAMESTRIKE, 30000, EVENT_GROUP_COMBAT, PHASE_COMBAT); + break; + case EVENT_MIND_CONTROL: + Talk(SAY_MIND_CONTROL); + DoCastAOE(SPELL_MIND_CONTROL, true); + events.ScheduleEvent(EVENT_MIND_CONTROL, 60000, EVENT_GROUP_COMBAT, PHASE_COMBAT); + break; + case EVENT_SUMMON_PHOENIX: DoCast(me, SPELL_PHOENIX_ANIMATION); Talk(SAY_SUMMON_PHOENIX); - - Phoenix_Timer = 60000; - } - else - Phoenix_Timer -= diff; - - //Phase 4 specific spells - if (Phase == 4) - { - if (HealthBelowPct(50)) + events.ScheduleEvent(EVENT_SUMMON_PHOENIX, urand(45000, 60000), EVENT_GROUP_COMBAT, PHASE_COMBAT); + break; + case EVENT_END_TRANSITION: + me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE); + DoCast(SPELL_FULLPOWER); + events.ScheduleEvent(EVENT_TRANSITION_4, 2000); + break; + case EVENT_PYROBLAST: + _pyrosCast = 0; + Talk(EMOTE_PYROBLAST); + DoCast(me, SPELL_SHOCK_BARRIER); + events.DelayEvents(10000, EVENT_GROUP_COMBAT); + events.ScheduleEvent(EVENT_PYROBLAST_CAST, 1000, EVENT_GROUP_SPECIAL, PHASE_COMBAT); + break; + case EVENT_PYROBLAST_CAST: + if (_pyrosCast < 3) { - instance->SetData(DATA_KAELTHASEVENT, 4); - Phase = 5; - Phase_Timer = 10000; - - Talk(SAY_PHASE5_NUTS); - - me->StopMoving(); - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MoveIdle(); - me->SetPosition(afGravityPos[0], afGravityPos[1], afGravityPos[2], 0); - me->MonsterMoveWithSpeed(afGravityPos[0], afGravityPos[1], afGravityPos[2], 1); - - me->InterruptNonMeleeSpells(false); - DoCast(me, SPELL_FULLPOWER); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - - //ShockBarrier_Timer - if (ShockBarrier_Timer <= diff) - { - DoCast(me, SPELL_SHOCK_BARRIER); - ChainPyros = true; - PyrosCast = 0; - ShockBarrier_Timer = 60000; + DoCastVictim(SPELL_PYROBLAST); + events.ScheduleEvent(EVENT_PYROBLAST_CAST, 3000); + _pyrosCast++; } else - ShockBarrier_Timer -= diff; - - //Chain Pyros (3 of them max) - if (ChainPyros && !me->IsNonMeleeSpellCast(false)) + events.ScheduleEvent(EVENT_PYROBLAST, 60000, EVENT_GROUP_COMBAT, PHASE_COMBAT); + break; + case EVENT_GRAVITY_LAPSE: + Talk(SAY_GRAVITY_LAPSE); + DoCastAOE(SPELL_GRAVITY_LAPSE); + DoCast(me, SPELL_NETHER_VAPOR); + events.DelayEvents(24000, EVENT_GROUP_COMBAT); + events.ScheduleEvent(EVENT_NETHER_BEAM, 3000, EVENT_GROUP_SPECIAL, PHASE_COMBAT); + events.ScheduleEvent(EVENT_SHOCK_BARRIER, 1000, EVENT_GROUP_SPECIAL, PHASE_COMBAT); + events.ScheduleEvent(EVENT_GRAVITY_LAPSE, 30000, EVENT_GROUP_SPECIAL, PHASE_COMBAT); + break; + case EVENT_NETHER_BEAM: + if (_netherbeamsCast <= 8) { - if (PyrosCast < 3) - { - DoCastVictim(SPELL_PYROBLAST); - ++PyrosCast; - } - else - { - ChainPyros = false; - Fireball_Timer = 2500; - ArcaneDisruption_Timer = 60000; - } - } - } + if (Unit* unit = SelectTarget(SELECT_TARGET_RANDOM, 0)) + DoCast(unit, SPELL_NETHER_BEAM); - if (Phase == 5) - { - if (Phase_Timer <= diff) - { - me->InterruptNonMeleeSpells(false); - me->RemoveAurasDueToSpell(SPELL_FULLPOWER); - - DoCast(me, SPELL_EXPLODE); - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - Phase = 6; - AttackStart(me->GetVictim()); + _netherbeamsCast++; + events.ScheduleEvent(EVENT_NETHER_BEAM, 3000); } else - Phase_Timer -= diff; - } + _netherbeamsCast = 0; + break; + case EVENT_TRANSITION_1: + me->GetMotionMaster()->MovePoint(POINT_TRANSITION_CENTER_ASCENDING, TransitionPos[1]); + break; + case EVENT_TRANSITION_2: + DoCast(me, SPELL_KAEL_GAINING_POWER); + me->GetMotionMaster()->Clear(); + me->RemoveUnitMovementFlag(MOVEMENTFLAG_ROOT); + me->GetMotionMaster()->MovePoint(POINT_TRANSITION_HALFWAY_ASCENDING, TransitionPos[2], false); + break; + case EVENT_TRANSITION_3: + me->GetMotionMaster()->MovePoint(POINT_TRANSITION_TOP, TransitionPos[3], false); + break; + case EVENT_TRANSITION_4: + me->GetMotionMaster()->MovePoint(POINT_TRANSITION_HALFWAY_DESCENDING, TransitionPos[4], false); + break; + case EVENT_TRANSITION_5: + me->GetMotionMaster()->MovePoint(POINT_END_TRANSITION, TransitionPos[5], false); + break; + case EVENT_EXPLODE: + me->InterruptNonMeleeSpells(false); + me->RemoveAurasDueToSpell(SPELL_NETHER_BEAM_VISUAL3); + DoCast(me, SPELL_KAEL_EXPLODES3, true); + DoCast(me, SPELL_KAEL_STUNNED); // Core doesn't handle the emote properly while flying. + me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_DROWNED); - //Phase 5 - if (Phase == 6) - { - //GravityLapse_Timer - if (GravityLapse_Timer <= diff) + // Destroy the surrounding environment. + if (GameObject* statue = instance->GetGameObject(DATA_KAEL_STATUE_LEFT)) + statue->UseDoorOrButton(); + + if (GameObject* statue = instance->GetGameObject(DATA_KAEL_STATUE_RIGHT)) + statue->UseDoorOrButton(); + + if (GameObject* window = instance->GetGameObject(DATA_TEMPEST_BRIDGE_WINDOW)) + window->UseDoorOrButton(); + + events.ScheduleEvent(EVENT_END_TRANSITION, 10000); + break; + case EVENT_SIZE_INCREASE: + switch (_scaleStage) { - ThreatContainer::StorageType threatlist = me->getThreatManager().getThreatList(); - ThreatContainer::StorageType::const_iterator i = threatlist.begin(); - - switch (GravityLapse_Phase) - { - case 0: - me->StopMoving(); - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MoveIdle(); - me->SetPosition(afGravityPos[0], afGravityPos[1], afGravityPos[2], 0); - me->MonsterMoveWithSpeed(afGravityPos[0], afGravityPos[1], afGravityPos[2], 0); - - // 1) Kael'thas will portal the whole raid right into his body - for (i = threatlist.begin(); i != threatlist.end(); ++i) - { - Unit* unit = ObjectAccessor::GetUnit(*me, (*i)->getUnitGuid()); - if (unit && (unit->GetTypeId() == TYPEID_PLAYER)) - { - //Use work around packet to prevent player from being dropped from combat - DoTeleportPlayer(unit, afGravityPos[0], afGravityPos[1], afGravityPos[2], unit->GetOrientation()); - } - } - - GravityLapse_Timer = 500; - ++GravityLapse_Phase; - InGravityLapse = true; - ShockBarrier_Timer = 1000; - NetherBeam_Timer = 5000; - break; - - case 1: - Talk(SAY_GRAVITYLAPSE); - - // 2) At that point he will put a Gravity Lapse debuff on everyone - for (i = threatlist.begin(); i != threatlist.end(); ++i) - { - if (Unit* unit = ObjectAccessor::GetUnit(*me, (*i)->getUnitGuid())) - { - DoCast(unit, SPELL_KNOCKBACK, true); - //Gravity lapse - needs an exception in Spell system to work - - unit->CastSpell(unit, SPELL_GRAVITY_LAPSE, true, 0, 0, me->GetGUID()); - unit->CastSpell(unit, SPELL_GRAVITY_LAPSE_AURA, true, 0, 0, me->GetGUID()); - - //Using packet workaround - WorldPacket data(SMSG_MOVE_SET_CAN_FLY, 12); - data << unit->GetPackGUID(); - data << uint32(0); - unit->SendMessageToSet(&data, true); - } - } - GravityLapse_Timer = 10000; - ++GravityLapse_Phase; - break; - - case 2: - //Cast nether vapor aura on self - me->InterruptNonMeleeSpells(false); - DoCast(me, SPELL_NETHER_VAPOR); - - GravityLapse_Timer = 20000; - ++GravityLapse_Phase; - break; - - case 3: - //Remove flight - for (i = threatlist.begin(); i != threatlist.end(); ++i) - { - if (Unit* unit = ObjectAccessor::GetUnit(*me, (*i)->getUnitGuid())) - { - //Using packet workaround - WorldPacket data(SMSG_MOVE_UNSET_CAN_FLY, 12); - data << unit->GetPackGUID(); - data << uint32(0); - unit->SendMessageToSet(&data, true); - } - } - - me->RemoveAurasDueToSpell(SPELL_NETHER_VAPOR); - InGravityLapse = false; - GravityLapse_Timer = 60000; - GravityLapse_Phase = 0; - AttackStart(me->GetVictim()); - break; - } + case 0: + me->SetObjectScale(1.4f); + events.ScheduleEvent(EVENT_SIZE_INCREASE, 5000); + break; + case 1: + me->SetObjectScale(1.8f); + events.ScheduleEvent(EVENT_SIZE_INCREASE, 3000); + break; + case 2: + me->SetObjectScale(2.0f); + events.ScheduleEvent(EVENT_SIZE_INCREASE, 1000); + break; + case 3: + me->SetObjectScale(2.2f); + break; + default: + break; } - else - GravityLapse_Timer -= diff; - - if (InGravityLapse) - { - //ShockBarrier_Timer - if (ShockBarrier_Timer <= diff) - { - DoCast(me, SPELL_SHOCK_BARRIER); - ShockBarrier_Timer = 20000; - } - else - ShockBarrier_Timer -= diff; - - //NetherBeam_Timer - if (NetherBeam_Timer <= diff) - { - if (Unit* unit = SelectTarget(SELECT_TARGET_RANDOM, 0)) - DoCast(unit, SPELL_NETHER_BEAM); - - NetherBeam_Timer = 4000; - } - else - NetherBeam_Timer -= diff; - } - } - - if (!InGravityLapse) - DoMeleeAttackIfReady(); + ++_scaleStage; + break; + default: + break; } } + + if (events.IsInPhase(PHASE_COMBAT)) + DoMeleeAttackIfReady(); } + private: + uint8 _advisorCounter; + uint8 _phase; + uint8 _pyrosCast; + uint8 _scaleStage; + uint8 _netherbeamsCast; + bool _hasFullPower; + ObjectGuid _advisorGuid[MAX_ADVISORS]; }; + CreatureAI* GetAI(Creature* creature) const override { return GetInstanceAI(creature); } }; -//Thaladred the Darkener AI class boss_thaladred_the_darkener : public CreatureScript { public: @@ -1040,32 +897,23 @@ class boss_thaladred_the_darkener : public CreatureScript void EnterCombat(Unit* who) override { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - if (!who || FakeDeath) - return; - Talk(SAY_THALADRED_AGGRO); me->AddThreat(who, 5000000.0f); } - void JustDied(Unit* /*killer*/) override + void JustDied(Unit* killer) override { - if (instance->GetData(DATA_KAELTHASEVENT) == 3) + if (_hasRessurrected) Talk(SAY_THALADRED_DEATH); + + advisorbase_ai::JustDied(killer); } void UpdateAI(uint32 diff) override { advisorbase_ai::UpdateAI(diff); - //Faking death, don't do anything - if (FakeDeath) - return; - - //Return since we have no target - if (!UpdateVictim()) + if (!UpdateVictim() || _inFakeDeath) return; //Gaze_Timer @@ -1110,7 +958,6 @@ class boss_thaladred_the_darkener : public CreatureScript } }; -//Lord Sanguinar AI class boss_lord_sanguinar : public CreatureScript { public: @@ -1137,33 +984,24 @@ class boss_lord_sanguinar : public CreatureScript advisorbase_ai::Reset(); } - void EnterCombat(Unit* who) override + void EnterCombat(Unit* /*who*/) override { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - if (!who || FakeDeath) - return; - Talk(SAY_SANGUINAR_AGGRO); } - void JustDied(Unit* /*killer*/) override + void JustDied(Unit* killer) override { - if (instance->GetData(DATA_KAELTHASEVENT) == 3) + if (_hasRessurrected) Talk(SAY_SANGUINAR_DEATH); + + advisorbase_ai::JustDied(killer); } void UpdateAI(uint32 diff) override { advisorbase_ai::UpdateAI(diff); - //Faking death, don't do anything - if (FakeDeath) - return; - - //Return since we have no target - if (!UpdateVictim()) + if (!UpdateVictim() || _inFakeDeath) return; //Fear_Timer @@ -1183,7 +1021,7 @@ class boss_lord_sanguinar : public CreatureScript return GetInstanceAI(creature); } }; -//Grand Astromancer Capernian AI + class boss_grand_astromancer_capernian : public CreatureScript { public: @@ -1219,15 +1057,17 @@ class boss_grand_astromancer_capernian : public CreatureScript advisorbase_ai::Reset(); } - void JustDied(Unit* /*killer*/) override + void JustDied(Unit* killer) override { - if (instance->GetData(DATA_KAELTHASEVENT) == 3) + if (_hasRessurrected) Talk(SAY_CAPERNIAN_DEATH); + + advisorbase_ai::JustDied(killer); } void AttackStart(Unit* who) override { - if (!who || FakeDeath || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + if (!who || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) return; if (me->Attack(who, true)) @@ -1240,39 +1080,18 @@ class boss_grand_astromancer_capernian : public CreatureScript } } - void EnterCombat(Unit* who) override + void EnterCombat(Unit* /*who*/) override { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - if (!who || FakeDeath) - return; + Talk(SAY_CAPERNIAN_AGGRO); } void UpdateAI(uint32 diff) override { advisorbase_ai::UpdateAI(diff); - //Faking Death, don't do anything - if (FakeDeath) + if (!UpdateVictim() || _inFakeDeath) return; - //Return since we have no target - if (!UpdateVictim()) - return; - - //Yell_Timer - if (!Yell) - { - if (Yell_Timer <= diff) - { - Talk(SAY_CAPERNIAN_AGGRO); - Yell = true; - } - else - Yell_Timer -= diff; - } - //Fireball_Timer if (Fireball_Timer <= diff) { @@ -1334,7 +1153,6 @@ class boss_grand_astromancer_capernian : public CreatureScript } }; -//Master Engineer Telonicus AI class boss_master_engineer_telonicus : public CreatureScript { public: @@ -1364,20 +1182,16 @@ class boss_master_engineer_telonicus : public CreatureScript advisorbase_ai::Reset(); } - void JustDied(Unit* /*killer*/) override + void JustDied(Unit* killer) override { - if (instance->GetData(DATA_KAELTHASEVENT) == 3) + if (_hasRessurrected) Talk(SAY_TELONICUS_DEATH); + + advisorbase_ai::JustDied(killer); } - void EnterCombat(Unit* who) override + void EnterCombat(Unit* /*who*/) override { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - if (!who || FakeDeath) - return; - Talk(SAY_TELONICUS_AGGRO); } @@ -1385,12 +1199,7 @@ class boss_master_engineer_telonicus : public CreatureScript { advisorbase_ai::UpdateAI(diff); - //Faking Death, do nothing - if (FakeDeath) - return; - - //Return since we have no target - if (!UpdateVictim()) + if (!UpdateVictim() || _inFakeDeath) return; //Bomb_Timer @@ -1423,7 +1232,6 @@ class boss_master_engineer_telonicus : public CreatureScript } }; -//Flame Strike AI class npc_kael_flamestrike : public CreatureScript { public: @@ -1494,7 +1302,6 @@ class npc_kael_flamestrike : public CreatureScript } }; -//Phoenix AI class npc_phoenix_tk : public CreatureScript { public: @@ -1554,7 +1361,6 @@ class npc_phoenix_tk : public CreatureScript } }; -//Phoenix Egg AI class npc_phoenix_egg_tk : public CreatureScript { public: @@ -1621,6 +1427,54 @@ class npc_phoenix_egg_tk : public CreatureScript } }; +// 35941 - Gravity Lapse +class spell_kael_gravity_lapse : public SpellScriptLoader +{ + public: + spell_kael_gravity_lapse() : SpellScriptLoader("spell_kael_gravity_lapse") { } + + class spell_kael_gravity_lapse_SpellScript : public SpellScript + { + PrepareSpellScript(spell_kael_gravity_lapse_SpellScript); + + public: + spell_kael_gravity_lapse_SpellScript() + { + _targetCount = 0; + } + + bool Validate(SpellInfo const* /*spell*/) override + { + for (uint8 i = 0; i < 25; ++i) + if (!sSpellMgr->GetSpellInfo(GravityLapseSpells[i])) + return false; + + return true; + } + + void HandleScript(SpellEffIndex /*effIndex*/) + { + GetCaster()->CastSpell(GetHitUnit(), GravityLapseSpells[_targetCount], true); + GetHitUnit()->CastSpell(GetHitUnit(), SPELL_GRAVITY_LAPSE_PERIODIC, true); + GetHitUnit()->CastSpell(GetHitUnit(), SPELL_GRAVITY_LAPSE_FLIGHT_AURA, true); + _targetCount++; + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_kael_gravity_lapse_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + + private: + uint8 _targetCount; + }; + + SpellScript* GetSpellScript() const override + { + return new spell_kael_gravity_lapse_SpellScript(); + } +}; + void AddSC_boss_kaelthas() { new boss_kaelthas(); @@ -1631,4 +1485,5 @@ void AddSC_boss_kaelthas() new npc_kael_flamestrike(); new npc_phoenix_tk(); new npc_phoenix_egg_tk(); + new spell_kael_gravity_lapse(); } diff --git a/src/server/scripts/Outland/TempestKeep/Eye/instance_the_eye.cpp b/src/server/scripts/Outland/TempestKeep/Eye/instance_the_eye.cpp index c421b9974ce..173e0596bea 100644 --- a/src/server/scripts/Outland/TempestKeep/Eye/instance_the_eye.cpp +++ b/src/server/scripts/Outland/TempestKeep/Eye/instance_the_eye.cpp @@ -34,6 +34,21 @@ EndScriptData */ 3 - Void Reaver event */ +DoorData const doorData[] = +{ + { GO_ARCANE_DOOR_LEFT, DATA_KAELTHAS, DOOR_TYPE_ROOM, BOUNDARY_SW }, + { GO_ARCANE_DOOR_RIGHT, DATA_KAELTHAS, DOOR_TYPE_ROOM, BOUNDARY_SE }, + { 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE } // END +}; + +ObjectData const gameObjectData[] = +{ + { GO_KAEL_STATUE_RIGHT, DATA_KAEL_STATUE_RIGHT }, + { GO_KAEL_STATUE_LEFT, DATA_KAEL_STATUE_LEFT }, + { GO_TEMPEST_BRIDDGE_WINDOW, DATA_TEMPEST_BRIDGE_WINDOW }, + { 0, 0 } // END +}; + class instance_the_eye : public InstanceMapScript { public: @@ -45,8 +60,8 @@ class instance_the_eye : public InstanceMapScript { SetHeaders(DataHeader); SetBossNumber(EncounterCount); - - KaelthasEventPhase = 0; + LoadDoorData(doorData); + LoadObjectData(nullptr, gameObjectData); } ObjectGuid ThaladredTheDarkener; @@ -56,7 +71,6 @@ class instance_the_eye : public InstanceMapScript ObjectGuid Kaelthas; ObjectGuid Astromancer; ObjectGuid Alar; - uint8 KaelthasEventPhase; void OnCreatureCreate(Creature* creature) override { @@ -102,28 +116,6 @@ class instance_the_eye : public InstanceMapScript } return ObjectGuid::Empty; } - - void SetData(uint32 type, uint32 data) override - { - switch (type) - { - case DATA_KAELTHASEVENT: - KaelthasEventPhase = data; - break; - default: - break; - } - } - - uint32 GetData(uint32 type) const override - { - switch (type) - { - case DATA_KAELTHASEVENT: - return KaelthasEventPhase; - } - return 0; - } }; InstanceScript* GetInstanceScript(InstanceMap* map) const override diff --git a/src/server/scripts/Outland/TempestKeep/Eye/the_eye.h b/src/server/scripts/Outland/TempestKeep/Eye/the_eye.h index c46fe408274..ca60e14e923 100644 --- a/src/server/scripts/Outland/TempestKeep/Eye/the_eye.h +++ b/src/server/scripts/Outland/TempestKeep/Eye/the_eye.h @@ -33,10 +33,14 @@ enum DataTypes DATA_ASTROMANCER = 4, DATA_GRANDASTROMANCERCAPERNIAN = 5, - DATA_KAELTHASEVENT = 6, - DATA_LORDSANGUINAR = 7, - DATA_MASTERENGINEERTELONICUS = 8, - DATA_THALADREDTHEDARKENER = 9 + DATA_LORDSANGUINAR = 6, + DATA_MASTERENGINEERTELONICUS = 7, + DATA_THALADREDTHEDARKENER = 8, + + // Additional Data + DATA_KAEL_STATUE_LEFT = 9, + DATA_KAEL_STATUE_RIGHT = 10, + DATA_TEMPEST_BRIDGE_WINDOW = 11 }; enum CreatureIds @@ -50,4 +54,13 @@ enum CreatureIds NPC_ALAR = 19514 }; +enum GameObjectIds +{ + GO_TEMPEST_BRIDDGE_WINDOW = 184069, + GO_KAEL_STATUE_RIGHT = 184596, + GO_KAEL_STATUE_LEFT = 184597, + GO_ARCANE_DOOR_LEFT = 184324, + GO_ARCANE_DOOR_RIGHT = 184325 +}; + #endif diff --git a/src/server/scripts/Spells/spell_mage.cpp b/src/server/scripts/Spells/spell_mage.cpp index 6dd9222afc9..11ff77a81d9 100644 --- a/src/server/scripts/Spells/spell_mage.cpp +++ b/src/server/scripts/Spells/spell_mage.cpp @@ -58,6 +58,7 @@ enum MageSpells SPELL_MAGE_WORGEN_FORM = 32819, SPELL_MAGE_SHEEP_FORM = 32820, SPELL_MAGE_GLYPH_OF_ETERNAL_WATER = 70937, + SPELL_MAGE_SHATTERED_BARRIER = 55080, SPELL_MAGE_SUMMON_WATER_ELEMENTAL_PERMANENT = 70908, SPELL_MAGE_SUMMON_WATER_ELEMENTAL_TEMPORARY = 70907, SPELL_MAGE_GLYPH_OF_BLAST_WAVE = 62126, @@ -152,6 +153,11 @@ class spell_mage_arcane_potency : public SpellScriptLoader } }; +enum MageSpellIcons +{ + SPELL_ICON_MAGE_SHATTERED_BARRIER = 2945 +}; + // Incanter's Absorbtion class spell_mage_incanters_absorbtion_base_AuraScript : public AuraScript { @@ -789,6 +795,7 @@ class spell_mage_ice_barrier : public SpellScriptLoader { DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_mage_ice_barrier_AuraScript::CalculateAmount, EFFECT_0, SPELL_AURA_SCHOOL_ABSORB); AfterEffectRemove += AuraEffectRemoveFn(spell_mage_ice_barrier_AuraScript::AfterRemove, EFFECT_0, SPELL_AURA_SCHOOL_ABSORB, AURA_EFFECT_HANDLE_REAL); + AfterEffectRemove += AuraEffectRemoveFn(spell_mage_ice_barrier_AuraScript::AfterRemove, EFFECT_0, SPELL_AURA_SCHOOL_ABSORB, AURA_EFFECT_HANDLE_REAL); } }; diff --git a/src/server/scripts/World/npcs_special.cpp b/src/server/scripts/World/npcs_special.cpp index 04c9cd0ec09..5bb8788c50d 100644 --- a/src/server/scripts/World/npcs_special.cpp +++ b/src/server/scripts/World/npcs_special.cpp @@ -936,6 +936,28 @@ public: { npc_garments_of_questsAI(Creature* creature) : npc_escortAI(creature) { + switch (me->GetEntry()) + { + case ENTRY_SHAYA: + quest = QUEST_MOON; + break; + case ENTRY_ROBERTS: + quest = QUEST_LIGHT_1; + break; + case ENTRY_DOLF: + quest = QUEST_LIGHT_2; + break; + case ENTRY_KORJA: + quest = QUEST_SPIRIT; + break; + case ENTRY_DG_KEL: + quest = QUEST_DARKNESS; + break; + default: + quest = 0; + break; + } + Reset(); } @@ -945,6 +967,7 @@ public: bool CanRun; uint32 RunAwayTimer; + uint32 quest; void Reset() override { @@ -976,93 +999,20 @@ public: if (Player* player = caster->ToPlayer()) { - switch (me->GetEntry()) + if (quest && player->GetQuestStatus(quest) == QUEST_STATUS_INCOMPLETE) { - case ENTRY_SHAYA: - if (player->GetQuestStatus(QUEST_MOON) == QUEST_STATUS_INCOMPLETE) - { - if (IsHealed && !CanRun && spell->Id == SPELL_FORTITUDE_R1) - { - Talk(SAY_THANKS, caster); - CanRun = true; - } - else if (!IsHealed && spell->Id == SPELL_LESSER_HEAL_R2) - { - CasterGUID = caster->GetGUID(); - me->SetStandState(UNIT_STAND_STATE_STAND); - Talk(SAY_HEALED, caster); - IsHealed = true; - } - } - break; - case ENTRY_ROBERTS: - if (player->GetQuestStatus(QUEST_LIGHT_1) == QUEST_STATUS_INCOMPLETE) - { - if (IsHealed && !CanRun && spell->Id == SPELL_FORTITUDE_R1) - { - Talk(SAY_THANKS, caster); - CanRun = true; - } - else if (!IsHealed && spell->Id == SPELL_LESSER_HEAL_R2) - { - CasterGUID = caster->GetGUID(); - me->SetStandState(UNIT_STAND_STATE_STAND); - Talk(SAY_HEALED, caster); - IsHealed = true; - } - } - break; - case ENTRY_DOLF: - if (player->GetQuestStatus(QUEST_LIGHT_2) == QUEST_STATUS_INCOMPLETE) - { - if (IsHealed && !CanRun && spell->Id == SPELL_FORTITUDE_R1) - { - Talk(SAY_THANKS, caster); - CanRun = true; - } - else if (!IsHealed && spell->Id == SPELL_LESSER_HEAL_R2) - { - CasterGUID = caster->GetGUID(); - me->SetStandState(UNIT_STAND_STATE_STAND); - Talk(SAY_HEALED, caster); - IsHealed = true; - } - } - break; - case ENTRY_KORJA: - if (player->GetQuestStatus(QUEST_SPIRIT) == QUEST_STATUS_INCOMPLETE) - { - if (IsHealed && !CanRun && spell->Id == SPELL_FORTITUDE_R1) - { - Talk(SAY_THANKS, caster); - CanRun = true; - } - else if (!IsHealed && spell->Id == SPELL_LESSER_HEAL_R2) - { - CasterGUID = caster->GetGUID(); - me->SetStandState(UNIT_STAND_STATE_STAND); - Talk(SAY_HEALED, caster); - IsHealed = true; - } - } - break; - case ENTRY_DG_KEL: - if (player->GetQuestStatus(QUEST_DARKNESS) == QUEST_STATUS_INCOMPLETE) - { - if (IsHealed && !CanRun && spell->Id == SPELL_FORTITUDE_R1) - { - Talk(SAY_THANKS, caster); - CanRun = true; - } - else if (!IsHealed && spell->Id == SPELL_LESSER_HEAL_R2) - { - CasterGUID = caster->GetGUID(); - me->SetStandState(UNIT_STAND_STATE_STAND); - Talk(SAY_HEALED, caster); - IsHealed = true; - } - } - break; + if (IsHealed && !CanRun && spell->Id == SPELL_FORTITUDE_R1) + { + Talk(SAY_THANKS, caster); + CanRun = true; + } + else if (!IsHealed && spell->Id == SPELL_LESSER_HEAL_R2) + { + CasterGUID = caster->GetGUID(); + me->SetStandState(UNIT_STAND_STATE_STAND); + Talk(SAY_HEALED, caster); + IsHealed = true; + } } // give quest credit, not expect any special quest objectives diff --git a/src/server/shared/CMakeLists.txt b/src/server/shared/CMakeLists.txt index abc019863b1..dbfd4966603 100644 --- a/src/server/shared/CMakeLists.txt +++ b/src/server/shared/CMakeLists.txt @@ -12,25 +12,16 @@ if( USE_COREPCH ) include_directories(${CMAKE_CURRENT_BINARY_DIR}) endif() -file(GLOB_RECURSE sources_Configuration Configuration/*.cpp Configuration/*.h) file(GLOB_RECURSE sources_Cryptography Cryptography/*.cpp Cryptography/*.h) -file(GLOB_RECURSE sources_Database Database/*.cpp Database/*.h) file(GLOB_RECURSE sources_DataStores DataStores/*.cpp DataStores/*.h) 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_Threading Threading/*.cpp Threading/*.h) -file(GLOB_RECURSE sources_Updater Updater/*.cpp Updater/*.h) -file(GLOB_RECURSE sources_Utilities Utilities/*.cpp Utilities/*.h) - +if( WIN32 ) + file(GLOB_RECURSE sources_Service Service/*.cpp Service/*.h) +endif( WIN32 ) file(GLOB sources_localdir *.cpp *.h) -# Manually set sources for Debugging directory as we don't want to include WheatyExceptionReport in shared project -# It needs to be included both in authserver and worldserver for the static global variable to be properly initialized -# and to handle crash logs on windows -set(sources_Debugging Debugging/Errors.cpp Debugging/Errors.h) - # # Build shared sourcelist # @@ -42,43 +33,23 @@ endif() set(shared_STAT_SRCS ${shared_STAT_SRCS} - ${sources_Configuration} ${sources_Cryptography} - ${sources_Database} ${sources_DataStores} - ${sources_Debugging} ${sources_Dynamic} - ${sources_Logging} ${sources_Networking} ${sources_Packets} - ${sources_Threading} - ${sources_Updater} - ${sources_Utilities} + ${sources_Service} ${sources_localdir} ) include_directories( - ${CMAKE_BINARY_DIR} - ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour - ${CMAKE_SOURCE_DIR}/dep/SFMT - ${CMAKE_SOURCE_DIR}/dep/cppformat - ${CMAKE_SOURCE_DIR}/dep/utf8cpp - ${CMAKE_SOURCE_DIR}/dep/process - ${CMAKE_SOURCE_DIR}/src/server - ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/Configuration - ${CMAKE_CURRENT_SOURCE_DIR}/Cryptography - ${CMAKE_CURRENT_SOURCE_DIR}/Database - ${CMAKE_CURRENT_SOURCE_DIR}/DataStores - ${CMAKE_CURRENT_SOURCE_DIR}/Debugging ${CMAKE_CURRENT_SOURCE_DIR}/Dynamic - ${CMAKE_CURRENT_SOURCE_DIR}/Logging ${CMAKE_CURRENT_SOURCE_DIR}/Networking - ${CMAKE_CURRENT_SOURCE_DIR}/Packets - ${CMAKE_CURRENT_SOURCE_DIR}/Threading - ${CMAKE_CURRENT_SOURCE_DIR}/Utilities - ${CMAKE_CURRENT_SOURCE_DIR}/Updater - ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Object + ${CMAKE_SOURCE_DIR}/dep/cppformat + ${CMAKE_SOURCE_DIR}/src/common/ + ${CMAKE_SOURCE_DIR}/src/common/Debugging + ${CMAKE_SOURCE_DIR}/src/common/Logging + ${CMAKE_SOURCE_DIR}/src/common/Utilities ${MYSQL_INCLUDE_DIR} ${OPENSSL_INCLUDE_DIR} ${VALGRIND_INCLUDE_DIR} @@ -91,6 +62,8 @@ add_library(shared STATIC ${shared_STAT_PCH_SRC} ) +add_dependencies(shared revision_data.h) + # Generate precompiled header if (USE_COREPCH) add_cxx_pch(shared ${shared_STAT_PCH_HDR} ${shared_STAT_PCH_SRC}) diff --git a/src/server/shared/DataStores/DBCStore.h b/src/server/shared/DataStores/DBCStore.h index 589d53c1552..7fa69e8e77f 100644 --- a/src/server/shared/DataStores/DBCStore.h +++ b/src/server/shared/DataStores/DBCStore.h @@ -20,6 +20,7 @@ #define DBCSTORE_H #include "DBCFileLoader.h" +#include "DBStorageIterator.h" #include "Log.h" #include "Field.h" #include "DatabaseWorkerPool.h" @@ -72,8 +73,11 @@ private: template class DBCStorage { - typedef std::list StringPoolList; + typedef std::list StringPoolList; + public: + typedef DBStorageIterator iterator; + explicit DBCStorage(char const* f) : fmt(f), nCount(0), fieldCount(0), dataTable(NULL) { @@ -296,6 +300,9 @@ class DBCStorage nCount = 0; } + iterator begin() { return iterator(indexTable.asT, nCount); } + iterator end() { return iterator(indexTable.asT, nCount, nCount); } + private: char const* fmt; uint32 nCount; diff --git a/src/server/shared/DataStores/DBStorageIterator.h b/src/server/shared/DataStores/DBStorageIterator.h new file mode 100644 index 00000000000..767900a123e --- /dev/null +++ b/src/server/shared/DataStores/DBStorageIterator.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2008-2015 TrinityCore + * + * 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 . + */ + +#ifndef DBStorageIterator_h__ +#define DBStorageIterator_h__ + +#include "Define.h" +#include + +template +class DBStorageIterator : public std::iterator +{ +public: + DBStorageIterator() : _index(nullptr), _pos(0), _end(0) { } + DBStorageIterator(T** index, uint32 size, uint32 pos = 0) : _index(index), _pos(pos), _end(size) + { + if (_pos < _end) + { + while (_pos < _end && !_index[_pos]) + ++_pos; + } + } + + T* operator->() { return _index[_pos]; } + T* operator*() { return _index[_pos]; } + + bool operator==(DBStorageIterator const& right) const { /*ASSERT(_index == right._index, "Iterator belongs to a different container")*/ return _pos == right._pos; } + bool operator!=(DBStorageIterator const& right) const { return !(*this == right); } + + DBStorageIterator& operator++() + { + if (_pos < _end) + { + do + ++_pos; + while (_pos < _end && !_index[_pos]); + } + + return *this; + } + + DBStorageIterator operator++(int) + { + DBStorageIterator tmp = *this; + ++*this; + return tmp; + } + +private: + T** _index; + uint32 _pos; + uint32 _end; +}; + +#endif // DBStorageIterator_h__ diff --git a/src/server/shared/PrecompiledHeaders/sharedPCH.h b/src/server/shared/PrecompiledHeaders/sharedPCH.h index d99476bc7a8..f864674d5ad 100644 --- a/src/server/shared/PrecompiledHeaders/sharedPCH.h +++ b/src/server/shared/PrecompiledHeaders/sharedPCH.h @@ -1,10 +1,4 @@ //add here most rarely modified headers to speed up debug build compilation -#include "Common.h" -#include "Log.h" -#include "DatabaseWorker.h" -#include "SQLOperation.h" -#include "Errors.h" #include "TypeList.h" -#include "TaskScheduler.h" -#include "EventMap.h" +#include "GitRevision.h" diff --git a/src/server/shared/Utilities/ServiceWin32.cpp b/src/server/shared/Service/ServiceWin32.cpp similarity index 100% rename from src/server/shared/Utilities/ServiceWin32.cpp rename to src/server/shared/Service/ServiceWin32.cpp diff --git a/src/server/shared/Utilities/ServiceWin32.h b/src/server/shared/Service/ServiceWin32.h similarity index 100% rename from src/server/shared/Utilities/ServiceWin32.h rename to src/server/shared/Service/ServiceWin32.h diff --git a/src/server/worldserver/CMakeLists.txt b/src/server/worldserver/CMakeLists.txt index 93f35c798fd..b76a3f0a976 100644 --- a/src/server/worldserver/CMakeLists.txt +++ b/src/server/worldserver/CMakeLists.txt @@ -41,57 +41,41 @@ endif() include_directories( ${CMAKE_BINARY_DIR} - ${CMAKE_SOURCE_DIR}/dep/g3dlite/include - ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour - ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour/Include - ${CMAKE_SOURCE_DIR}/dep/gsoap - ${CMAKE_SOURCE_DIR}/dep/sockets/include - ${CMAKE_SOURCE_DIR}/dep/SFMT - ${CMAKE_SOURCE_DIR}/dep/zmqpp + ${CMAKE_CURRENT_SOURCE_DIR}/CommandLine + ${CMAKE_CURRENT_SOURCE_DIR}/RemoteAccess + ${CMAKE_CURRENT_SOURCE_DIR}/TCSoap ${CMAKE_SOURCE_DIR}/dep/cppformat - ${CMAKE_SOURCE_DIR}/dep/process - ${CMAKE_SOURCE_DIR}/src/server/collision - ${CMAKE_SOURCE_DIR}/src/server/collision/Management - ${CMAKE_SOURCE_DIR}/src/server/collision/Models - ${CMAKE_SOURCE_DIR}/src/server/shared - ${CMAKE_SOURCE_DIR}/src/server/shared/Configuration - ${CMAKE_SOURCE_DIR}/src/server/shared/Cryptography - ${CMAKE_SOURCE_DIR}/src/server/shared/Cryptography/Authentication - ${CMAKE_SOURCE_DIR}/src/server/shared/Database - ${CMAKE_SOURCE_DIR}/src/server/shared/DataStores - ${CMAKE_SOURCE_DIR}/src/server/shared/Debugging - ${CMAKE_SOURCE_DIR}/src/server/shared/Dynamic/LinkedReference - ${CMAKE_SOURCE_DIR}/src/server/shared/Dynamic - ${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/Threading - ${CMAKE_SOURCE_DIR}/src/server/shared/Updater - ${CMAKE_SOURCE_DIR}/src/server/shared/Utilities + ${CMAKE_SOURCE_DIR}/dep/g3dlite/include + ${CMAKE_SOURCE_DIR}/dep/gsoap + ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour/Include + ${CMAKE_SOURCE_DIR}/dep/zmqpp + ${CMAKE_SOURCE_DIR}/src/common/ + ${CMAKE_SOURCE_DIR}/src/common/Collision + ${CMAKE_SOURCE_DIR}/src/common/Collision/Maps + ${CMAKE_SOURCE_DIR}/src/common/Collision/Models + ${CMAKE_SOURCE_DIR}/src/common/Configuration + ${CMAKE_SOURCE_DIR}/src/common/Cryptography + ${CMAKE_SOURCE_DIR}/src/common/Cryptography/Authentication + ${CMAKE_SOURCE_DIR}/src/common/Debugging + ${CMAKE_SOURCE_DIR}/src/common/Logging + ${CMAKE_SOURCE_DIR}/src/common/Threading + ${CMAKE_SOURCE_DIR}/src/common/Utilities + ${CMAKE_SOURCE_DIR}/src/server/authserver/Realms + ${CMAKE_SOURCE_DIR}/src/server/database/ + ${CMAKE_SOURCE_DIR}/src/server/database/Database + ${CMAKE_SOURCE_DIR}/src/server/database/Logging ${CMAKE_SOURCE_DIR}/src/server/ipc ${CMAKE_SOURCE_DIR}/src/server/game ${CMAKE_SOURCE_DIR}/src/server/game/Accounts - ${CMAKE_SOURCE_DIR}/src/server/game/Achievements ${CMAKE_SOURCE_DIR}/src/server/game/Addons - ${CMAKE_SOURCE_DIR}/src/server/game/AI - ${CMAKE_SOURCE_DIR}/src/server/game/AI/CoreAI - ${CMAKE_SOURCE_DIR}/src/server/game/AI/ScriptedAI - ${CMAKE_SOURCE_DIR}/src/server/game/AI/SmartScripts - ${CMAKE_SOURCE_DIR}/src/server/game/AuctionHouse - ${CMAKE_SOURCE_DIR}/src/server/game/AuctionHouse/AuctionHouseBot ${CMAKE_SOURCE_DIR}/src/server/game/Battlegrounds - ${CMAKE_SOURCE_DIR}/src/server/game/Battlegrounds/Zones - ${CMAKE_SOURCE_DIR}/src/server/game/Calendar ${CMAKE_SOURCE_DIR}/src/server/game/Chat - ${CMAKE_SOURCE_DIR}/src/server/game/Chat/Channels ${CMAKE_SOURCE_DIR}/src/server/game/Combat ${CMAKE_SOURCE_DIR}/src/server/game/Conditions ${CMAKE_SOURCE_DIR}/src/server/game/DataStores - ${CMAKE_SOURCE_DIR}/src/server/game/DungeonFinding - ${CMAKE_SOURCE_DIR}/src/server/game/Entities ${CMAKE_SOURCE_DIR}/src/server/game/Entities/AreaTrigger - ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Creature ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Corpse + ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Creature ${CMAKE_SOURCE_DIR}/src/server/game/Entities/DynamicObject ${CMAKE_SOURCE_DIR}/src/server/game/Entities/GameObject ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Item @@ -100,17 +84,12 @@ include_directories( ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Object/Updates ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Pet ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Player - ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Totem ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Unit ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Vehicle - ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Transport - ${CMAKE_SOURCE_DIR}/src/server/game/Events ${CMAKE_SOURCE_DIR}/src/server/game/Globals - ${CMAKE_SOURCE_DIR}/src/server/game/Grids/Cells - ${CMAKE_SOURCE_DIR}/src/server/game/Grids/Notifiers ${CMAKE_SOURCE_DIR}/src/server/game/Grids + ${CMAKE_SOURCE_DIR}/src/server/game/Grids/Cells ${CMAKE_SOURCE_DIR}/src/server/game/Groups - ${CMAKE_SOURCE_DIR}/src/server/game/Guilds ${CMAKE_SOURCE_DIR}/src/server/game/Handlers ${CMAKE_SOURCE_DIR}/src/server/game/Instances ${CMAKE_SOURCE_DIR}/src/server/game/Loot @@ -118,31 +97,23 @@ include_directories( ${CMAKE_SOURCE_DIR}/src/server/game/Maps ${CMAKE_SOURCE_DIR}/src/server/game/Miscellaneous ${CMAKE_SOURCE_DIR}/src/server/game/Movement - ${CMAKE_SOURCE_DIR}/src/server/game/Movement/MovementGenerators ${CMAKE_SOURCE_DIR}/src/server/game/Movement/Spline ${CMAKE_SOURCE_DIR}/src/server/game/Movement/Waypoints - ${CMAKE_SOURCE_DIR}/src/server/game/OutdoorPvP - ${CMAKE_SOURCE_DIR}/src/server/game/Pools - ${CMAKE_SOURCE_DIR}/src/server/game/PrecompiledHeaders ${CMAKE_SOURCE_DIR}/src/server/game/Quests - ${CMAKE_SOURCE_DIR}/src/server/game/Reputation ${CMAKE_SOURCE_DIR}/src/server/game/Scripting - ${CMAKE_SOURCE_DIR}/src/server/game/Server/Protocol ${CMAKE_SOURCE_DIR}/src/server/game/Server - ${CMAKE_SOURCE_DIR}/src/server/game/Skills + ${CMAKE_SOURCE_DIR}/src/server/game/Server/Protocol ${CMAKE_SOURCE_DIR}/src/server/game/Spells ${CMAKE_SOURCE_DIR}/src/server/game/Spells/Auras - ${CMAKE_SOURCE_DIR}/src/server/game/Tools - ${CMAKE_SOURCE_DIR}/src/server/game/Warden - ${CMAKE_SOURCE_DIR}/src/server/game/Warden/Modules ${CMAKE_SOURCE_DIR}/src/server/game/Weather ${CMAKE_SOURCE_DIR}/src/server/game/World - ${CMAKE_SOURCE_DIR}/src/server/authserver/Server - ${CMAKE_SOURCE_DIR}/src/server/authserver/Realms - ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/CommandLine - ${CMAKE_CURRENT_SOURCE_DIR}/RemoteAccess - ${CMAKE_CURRENT_SOURCE_DIR}/TCSoap + ${CMAKE_SOURCE_DIR}/src/server/shared + ${CMAKE_SOURCE_DIR}/src/server/shared/DataStores + ${CMAKE_SOURCE_DIR}/src/server/shared/Dynamic + ${CMAKE_SOURCE_DIR}/src/server/shared/Dynamic/LinkedReference + ${CMAKE_SOURCE_DIR}/src/server/shared/Networking + ${CMAKE_SOURCE_DIR}/src/server/shared/Packets + ${CMAKE_SOURCE_DIR}/src/server/shared/Service ${MYSQL_INCLUDE_DIR} ${OPENSSL_INCLUDE_DIR} ${VALGRIND_INCLUDE_DIR} @@ -162,8 +133,6 @@ if( NOT WIN32 ) ) endif() -add_dependencies(worldserver revision.h) - if( UNIX AND NOT NOJEM AND NOT APPLE ) set(worldserver_LINK_FLAGS "-pthread -lncurses ${worldserver_LINK_FLAGS}") endif() @@ -172,10 +141,11 @@ set_target_properties(worldserver PROPERTIES LINK_FLAGS "${worldserver_LINK_FLAG target_link_libraries(worldserver game + common ipc shared + database scripts - collision g3dlib gsoap Detour diff --git a/src/server/worldserver/Main.cpp b/src/server/worldserver/Main.cpp index 4055cb51b25..0c334ce1422 100644 --- a/src/server/worldserver/Main.cpp +++ b/src/server/worldserver/Main.cpp @@ -40,11 +40,12 @@ #include "BattlegroundMgr.h" #include "TCSoap.h" #include "CliRunnable.h" -#include "SystemConfig.h" +#include "GitRevision.h" #include "WorldSocket.h" #include "WorldSocketMgr.h" #include "BattlenetServerManager.h" #include "DatabaseLoader.h" +#include "AppenderDB.h" #include #include #include @@ -122,13 +123,11 @@ extern int main(int argc, char** argv) return 1; } - if (sConfigMgr->GetBoolDefault("Log.Async.Enable", false)) - { - // If logs are supposed to be handled async then we need to pass the io_service into the Log singleton - Log::instance(&_ioService); - } + sLog->RegisterAppender(); + // If logs are supposed to be handled async then we need to pass the io_service into the Log singleton + sLog->Initialize(sConfigMgr->GetBoolDefault("Log.Async.Enable", false) ? &_ioService : nullptr); - TC_LOG_INFO("server.worldserver", "%s (worldserver-daemon)", _FULLVERSION); + TC_LOG_INFO("server.worldserver", "%s (worldserver-daemon)", GitRevision::GetFullVersion()); TC_LOG_INFO("server.worldserver", " to stop.\n"); TC_LOG_INFO("server.worldserver", " ______ __"); TC_LOG_INFO("server.worldserver", "/\\__ _\\ __ __/\\ \\__"); @@ -238,10 +237,10 @@ extern int main(int argc, char** argv) } sIpcContext->Initialize(); + TC_LOG_INFO("server.worldserver", "%s (worldserver-daemon) ready...", GitRevision::GetFullVersion()); sBattlenetServer.InitializeConnection(); - TC_LOG_INFO("server.worldserver", "%s (worldserver-daemon) ready...", _FULLVERSION); sScriptMgr->OnStartup(); @@ -492,7 +491,7 @@ bool StartDB() ClearOnlineAccounts(); ///- Insert version info into DB - WorldDatabase.PExecute("UPDATE version SET core_version = '%s', core_revision = '%s'", _FULLVERSION, _HASH); // One-time query + WorldDatabase.PExecute("UPDATE version SET core_version = '%s', core_revision = '%s'", GitRevision::GetFullVersion(), GitRevision::GetHash()); // One-time query sWorld->LoadDBVersion(); @@ -558,7 +557,7 @@ variables_map GetConsoleArguments(int argc, char** argv, std::string& configFile } else if (vm.count("version")) { - std::cout << _FULLVERSION << "\n"; + std::cout << GitRevision::GetFullVersion() << "\n"; } return vm; diff --git a/src/server/worldserver/worldserver.rc b/src/server/worldserver/worldserver.rc index cc5545741d3..9af2db46ce0 100644 --- a/src/server/worldserver/worldserver.rc +++ b/src/server/worldserver/worldserver.rc @@ -17,7 +17,7 @@ */ #include "resource.h" -#include "revision.h" +#include "revision_data.h" #define APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// diff --git a/src/tools/mmaps_generator/CMakeLists.txt b/src/tools/mmaps_generator/CMakeLists.txt index 48e30b1c3cf..52a7f5504d6 100644 --- a/src/tools/mmaps_generator/CMakeLists.txt +++ b/src/tools/mmaps_generator/CMakeLists.txt @@ -21,13 +21,15 @@ set(mmap_gen_Includes ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour/Include ${CMAKE_SOURCE_DIR}/src/server/shared - ${CMAKE_SOURCE_DIR}/src/server/shared/Utilities - ${CMAKE_SOURCE_DIR}/src/server/shared/Threading ${CMAKE_SOURCE_DIR}/src/server/game/Conditions - ${CMAKE_SOURCE_DIR}/src/server/collision - ${CMAKE_SOURCE_DIR}/src/server/collision/Management - ${CMAKE_SOURCE_DIR}/src/server/collision/Maps - ${CMAKE_SOURCE_DIR}/src/server/collision/Models + ${CMAKE_SOURCE_DIR}/src/common + ${CMAKE_SOURCE_DIR}/src/common/Collision + ${CMAKE_SOURCE_DIR}/src/common/Collision/Management + ${CMAKE_SOURCE_DIR}/src/common/Collision/Maps + ${CMAKE_SOURCE_DIR}/src/common/Collision/Models + ${CMAKE_SOURCE_DIR}/src/common/Debugging + ${CMAKE_SOURCE_DIR}/src/common/Threading + ${CMAKE_SOURCE_DIR}/src/common/Utilities ) if( WIN32 ) @@ -42,7 +44,7 @@ include_directories(${mmap_gen_Includes}) add_executable(mmaps_generator ${mmap_gen_sources}) target_link_libraries(mmaps_generator - collision + common g3dlib Recast Detour diff --git a/src/tools/vmap4_assembler/CMakeLists.txt b/src/tools/vmap4_assembler/CMakeLists.txt index bb1971b3ed9..3a4d032a3b9 100644 --- a/src/tools/vmap4_assembler/CMakeLists.txt +++ b/src/tools/vmap4_assembler/CMakeLists.txt @@ -13,9 +13,10 @@ include_directories( ${CMAKE_SOURCE_DIR}/dep/g3dlite/include ${CMAKE_SOURCE_DIR}/src/server/shared ${CMAKE_SOURCE_DIR}/src/server/shared/Debugging - ${CMAKE_SOURCE_DIR}/src/server/collision - ${CMAKE_SOURCE_DIR}/src/server/collision/Maps - ${CMAKE_SOURCE_DIR}/src/server/collision/Models + ${CMAKE_SOURCE_DIR}/src/common + ${CMAKE_SOURCE_DIR}/src/common/Collision + ${CMAKE_SOURCE_DIR}/src/common/Collision/Maps + ${CMAKE_SOURCE_DIR}/src/common/Collision/Models ${ZLIB_INCLUDE_DIR} ) @@ -23,7 +24,7 @@ add_executable(vmap4assembler VMapAssembler.cpp) add_dependencies(vmap4assembler storm) target_link_libraries(vmap4assembler - collision + common g3dlib ${ZLIB_LIBRARIES} )