diff options
260 files changed, 8652 insertions, 2902 deletions
diff --git a/.travis.yml b/.travis.yml index cddb98492a2..583318ef1fa 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,3 +1,6 @@ +sudo: required +dist: trusty + language: cpp compiler: - clang @@ -6,16 +9,10 @@ git: depth: 1 before_install: - - echo "yes" | sudo add-apt-repository ppa:george-edison55/precise-backports - - echo "yes" | sudo add-apt-repository ppa:boost-latest/ppa - - echo "yes" | sudo add-apt-repository ppa:ubuntu-toolchain-r/test - - echo "yes" | sudo add-apt-repository 'deb http://llvm.org/apt/precise/ llvm-toolchain-precise-3.5 main' - - wget -O - http://llvm.org/apt/llvm-snapshot.gpg.key | sudo apt-key add - - - sudo apt-get -qq update - - sudo apt-get -qq install build-essential libtool gcc-4.8 g++-4.8 make cmake cmake-data openssl clang-3.5 + - sudo apt-get -qq install build-essential libtool make cmake cmake-data openssl - sudo apt-get -qq install libssl-dev libmysqlclient-dev libmysql++-dev libreadline6-dev zlib1g-dev libbz2-dev - sudo apt-get -qq install libboost1.55-dev libboost-thread1.55-dev libboost-filesystem1.55-dev libboost-system1.55-dev libboost-program-options1.55-dev libboost-iostreams1.55-dev - - export CC=clang-3.5 CXX=clang++-3.5 + - sudo apt-get -qq install mysql-server - git config user.email "travis@build.bot" && git config user.name "Travis CI" - git tag -a -m "Travis build" init diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4baa1197965..e7bd9263a70 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,7 +8,7 @@ Issues ====== Read [this](http://www.trinitycore.org/f/topic/37-the-trinitycore-issuetracker-and-you/) before creating a ticket. -If you have problems with TrinityCore instalation, read [this](http://www.trinitycore.org/f/topic/1518-trouble-with-your-trinity-install-readme-1st-faqs/) +If you have problems with TrinityCore installation, read [this](http://www.trinitycore.org/f/topic/1518-trouble-with-your-trinity-install-readme-1st-faqs/). Mandatory things when creating a ticket: ======================================== diff --git a/cmake/compiler/gcc/settings.cmake b/cmake/compiler/gcc/settings.cmake index c4f97f4ffd4..a0c2b737475 100644 --- a/cmake/compiler/gcc/settings.cmake +++ b/cmake/compiler/gcc/settings.cmake @@ -1,7 +1,7 @@ # Set build-directive (used in core to tell which buildtype we used) add_definitions(-D_BUILD_DIRECTIVE='"${CMAKE_BUILD_TYPE}"') -set(GCC_EXPECTED_VERSION 4.7.2) +set(GCC_EXPECTED_VERSION 4.9.0) if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS GCC_EXPECTED_VERSION) message(FATAL_ERROR "GCC: TrinityCore requires version ${GCC_EXPECTED_VERSION} to build but found ${CMAKE_CXX_COMPILER_VERSION}") diff --git a/cmake/macros/FindBoost.cmake b/cmake/macros/FindBoost.cmake index 997336261d3..62da7fc4caf 100644 --- a/cmake/macros/FindBoost.cmake +++ b/cmake/macros/FindBoost.cmake @@ -478,6 +478,7 @@ else() # The user has not requested an exact version. Among known # versions, find those that are acceptable to the user request. set(_Boost_KNOWN_VERSIONS ${Boost_ADDITIONAL_VERSIONS} + "1.61.0" "1.61" "1.60.0" "1.60" "1.59.0" "1.59" "1.58.0" "1.58" "1.57.0" "1.57" "1.56.0" "1.56" "1.55.0" "1.55" "1.54.0" "1.54" "1.53.0" "1.53" "1.52.0" "1.52" "1.51.0" "1.51" "1.50.0" "1.50" "1.49.0" "1.49" "1.48.0" "1.48" "1.47.0" "1.47" "1.46.1" diff --git a/dep/boost/CMakeLists.txt b/dep/boost/CMakeLists.txt index 6cda5fbec4e..764953ab587 100644 --- a/dep/boost/CMakeLists.txt +++ b/dep/boost/CMakeLists.txt @@ -26,7 +26,7 @@ if(WIN32) set(Boost_USE_STATIC_RUNTIME OFF) endif() -find_package(Boost 1.51 REQUIRED system filesystem thread program_options iostreams regex) +find_package(Boost 1.55 REQUIRED system filesystem thread program_options iostreams regex) # Find if Boost was compiled in C++03 mode because it requires -DBOOST_NO_CXX11_SCOPED_ENUMS diff --git a/dep/recastnavigation/CMakeLists.txt b/dep/recastnavigation/CMakeLists.txt index 4a406f7833c..dd28884eb1f 100644 --- a/dep/recastnavigation/CMakeLists.txt +++ b/dep/recastnavigation/CMakeLists.txt @@ -1,4 +1,4 @@ -# +# Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> # Copyright (C) 2005-2011 MaNGOS project <http://getmangos.com/> # # This program is free software; you can redistribute it and/or modify diff --git a/issue_template.md b/issue_template.md index 8653726f830..1bcd91ae766 100644 --- a/issue_template.md +++ b/issue_template.md @@ -18,8 +18,6 @@ **Operating system**: -**Linking model**: static/dynamic - [//]: # (This template is for problem reports, for other type of reports edit it accordingly) [//]: # (If this is a crash report, include the crashlog with https://gist.github.com/) diff --git a/sql/base/auth_database.sql b/sql/base/auth_database.sql index fd47a349f01..b0a120bae63 100644 --- a/sql/base/auth_database.sql +++ b/sql/base/auth_database.sql @@ -375,7 +375,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),(192,795),(192,796),(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,51),(194,195),(194,198),(194,632),(194,798),(195,3),(195,4),(195,5),(195,6),(195,24),(195,49),(195,199),(196,200),(196,201),(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),(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),(196,836),(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,217),(199,221),(199,222),(199,223),(199,225),(199,263),(199,496),(199,501),(199,507),(199,525),(199,534),(199,797); +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,795),(192,796),(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,51),(194,195),(194,198),(194,632),(194,798),(195,3),(195,4),(195,5),(195,6),(195,24),(195,49),(195,199),(196,200),(196,201),(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),(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),(196,836),(196,837),(196,838),(196,839),(196,840),(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,217),(199,221),(199,222),(199,223),(199,225),(199,263),(199,496),(199,501),(199,507),(199,525),(199,534),(199,797); /*!40000 ALTER TABLE `rbac_linked_permissions` ENABLE KEYS */; UNLOCK TABLES; @@ -399,7 +399,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'),(51,'Allow trading between factions'),(192,'Role: Sec Level Administrator'),(193,'Role: Sec Level Gamemaster'),(194,'Role: Sec Level Moderator'),(195,'Role: Sec Level Player'),(196,'Role: Administrator Commands'),(197,'Role: Gamemaster Commands'),(198,'Role: Moderator Commands'),(199,'Role: Player Commands'),(200,'Command: rbac'),(201,'Command: rbac account'),(202,'Command: rbac account list'),(203,'Command: rbac account grant'),(204,'Command: rbac account deny'),(205,'Command: rbac account revoke'),(206,'Command: rbac list'),(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'),(795,'Command: .instance setbossstate'),(796,'Command: instance getbossstate'),(797,'Command: pvpstats'),(798,'Command: .mod xp'),(835,'Command: debug loadcells'),(836,'Command: .debug boundary'); +INSERT INTO `rbac_permissions` VALUES (1,'Instant logout'),(2,'Skip Queue'),(3,'Join Normal Battleground'),(4,'Join Random Battleground'),(5,'Join Arenas'),(6,'Join Dungeon Finder'),(11,'Log GM trades'),(13,'Skip Instance required bosses check'),(14,'Skip character creation team mask check'),(15,'Skip character creation class mask check'),(16,'Skip character creation race mask check'),(17,'Skip character creation reserved name check'),(18,'Skip character creation heroic min level check'),(19,'Skip needed requirements to use channel check'),(20,'Skip disable map check'),(21,'Skip reset talents when used more than allowed check'),(22,'Skip spam chat check'),(23,'Skip over-speed ping check'),(24,'Two side faction characters on the same account'),(25,'Allow say chat between factions'),(26,'Allow channel chat between factions'),(27,'Two side mail interaction'),(28,'See two side who list'),(29,'Add friends of other faction'),(30,'Save character without delay with .save command'),(31,'Use params with .unstuck command'),(32,'Can be assigned tickets with .assign ticket command'),(33,'Notify if a command was not found'),(34,'Check if should appear in list using .gm ingame command'),(35,'See all security levels with who command'),(36,'Filter whispers'),(37,'Use staff badge in chat'),(38,'Resurrect with full Health Points'),(39,'Restore saved gm setting states'),(40,'Allows to add a gm to friend list'),(41,'Use Config option START_GM_LEVEL to assign new character level'),(42,'Allows to use CMSG_WORLD_TELEPORT opcode'),(43,'Allows to use CMSG_WHOIS opcode'),(44,'Receive global GM messages/texts'),(45,'Join channels without announce'),(46,'Change channel settings without being channel moderator'),(47,'Enables lower security than target check'),(48,'Enable IP, Last Login and EMail output in pinfo'),(49,'Forces to enter the email for confirmation on password change'),(50,'Allow user to check his own email with .account'),(51,'Allow trading between factions'),(192,'Role: Sec Level Administrator'),(193,'Role: Sec Level Gamemaster'),(194,'Role: Sec Level Moderator'),(195,'Role: Sec Level Player'),(196,'Role: Administrator Commands'),(197,'Role: Gamemaster Commands'),(198,'Role: Moderator Commands'),(199,'Role: Player Commands'),(200,'Command: rbac'),(201,'Command: rbac account'),(202,'Command: rbac account list'),(203,'Command: rbac account grant'),(204,'Command: rbac account deny'),(205,'Command: rbac account revoke'),(206,'Command: rbac list'),(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'),(795,'Command: .instance setbossstate'),(796,'Command: instance getbossstate'),(797,'Command: pvpstats'),(798,'Command: .mod xp'),(835,'Command: debug loadcells'),(836,'Command: .debug boundary'),(837,'Command: .npc evade'),(838,'Command: .pet level'),(839,'Command: .server shutdown force'),(840,'Command: .server restart force'); /*!40000 ALTER TABLE `rbac_permissions` ENABLE KEYS */; UNLOCK TABLES; @@ -486,7 +486,7 @@ CREATE TABLE `updates` ( LOCK TABLES `updates` WRITE; /*!40000 ALTER TABLE `updates` DISABLE KEYS */; -INSERT INTO `updates` VALUES ('2014_11_10_00_auth.sql','0E3CB119442D09DD88E967015319BBC8DAFBBFE0','ARCHIVED','2015-03-21 21:44:12',0),('2014_11_10_01_auth.sql','327E77A1DA3546D5275AB249915DD57EDD6FDD3D','ARCHIVED','2015-03-21 21:44:12',0),('2014_12_10_00_auth.sql','821703A96D80F9080074852B5A46E2909C9562EA','ARCHIVED','2015-03-21 21:44:12',0),('2014_12_21_00_auth.sql','CE2E5D2CD82E79C25294539ADED27A1429105B43','ARCHIVED','2015-03-21 21:44:12',0),('2015_03_20_00_auth.sql','E8C5B74BB45F0F35DEC182C72BACF435C7066FB0','ARCHIVED','2015-03-21 21:44:12',0),('2015_03_20_01_auth.sql','862961815354DA2746F5F71FBC8155F57CBE75AB','ARCHIVED','2015-03-21 21:44:12',0),('2015_03_20_02_auth.sql','33E4F94086590768EF5D4855DD43D7DE7C06ADA4','ARCHIVED','2015-03-21 21:44:51',0),('2015_08_21_00_auth.sql','C31A9E1D28E11B60BE8F8198637DD51F6D75123F','ARCHIVED','2015-10-05 23:16:19',0),('2015_11_07_00_auth.sql','0ACDD35EC9745231BCFA701B78056DEF94D0CC53','ARCHIVED','2016-04-11 00:42:36',92),('2016_01_13_00_auth.sql','24615CC69B3CD7BB4699874647C35BA86E8A93FD','ARCHIVED','2016-01-13 00:00:00',0),('2016_04_11_00_auth.sql','0ACDD35EC9745231BCFA701B78056DEF94D0CC53','RELEASED','2016-04-11 03:18:17',0); +INSERT INTO `updates` VALUES ('2014_11_10_00_auth.sql','0E3CB119442D09DD88E967015319BBC8DAFBBFE0','ARCHIVED','2015-03-21 21:44:12',0),('2014_11_10_01_auth.sql','327E77A1DA3546D5275AB249915DD57EDD6FDD3D','ARCHIVED','2015-03-21 21:44:12',0),('2014_12_10_00_auth.sql','821703A96D80F9080074852B5A46E2909C9562EA','ARCHIVED','2015-03-21 21:44:12',0),('2014_12_21_00_auth.sql','CE2E5D2CD82E79C25294539ADED27A1429105B43','ARCHIVED','2015-03-21 21:44:12',0),('2015_03_20_00_auth.sql','E8C5B74BB45F0F35DEC182C72BACF435C7066FB0','ARCHIVED','2015-03-21 21:44:12',0),('2015_03_20_01_auth.sql','862961815354DA2746F5F71FBC8155F57CBE75AB','ARCHIVED','2015-03-21 21:44:12',0),('2015_03_20_02_auth.sql','33E4F94086590768EF5D4855DD43D7DE7C06ADA4','ARCHIVED','2015-03-21 21:44:51',0),('2015_08_21_00_auth.sql','C31A9E1D28E11B60BE8F8198637DD51F6D75123F','ARCHIVED','2015-10-05 23:16:19',0),('2015_11_07_00_auth.sql','0ACDD35EC9745231BCFA701B78056DEF94D0CC53','ARCHIVED','2016-04-11 00:42:36',92),('2016_01_13_00_auth.sql','24615CC69B3CD7BB4699874647C35BA86E8A93FD','ARCHIVED','2016-01-13 00:00:00',0),('2016_04_11_00_auth.sql','0ACDD35EC9745231BCFA701B78056DEF94D0CC53','RELEASED','2016-04-11 03:18:17',0),('2016_05_11_00_auth.sql','95B66235B8D67BF1CA216EB09F313C1F8F393B47','RELEASED','2016-04-16 13:17:11',0); /*!40000 ALTER TABLE `updates` ENABLE KEYS */; UNLOCK TABLES; diff --git a/sql/updates/auth/3.3.5/2016_05_11_00_auth.sql b/sql/updates/auth/3.3.5/2016_05_11_00_auth.sql new file mode 100644 index 00000000000..254f3d801d6 --- /dev/null +++ b/sql/updates/auth/3.3.5/2016_05_11_00_auth.sql @@ -0,0 +1,6 @@ +-- +DELETE FROM `rbac_permissions` WHERE `id` IN (837,838,839,840); +INSERT INTO `rbac_permissions` (`id`,`name`) VALUES (837,"Command: .npc evade"), (838,"Command: .pet level"), (839,"Command: .server shutdown force"), (840,"Command: .server restart force"); + +DELETE FROM `rbac_linked_permissions` WHERE `linkedId` IN (837,838,839,840); +INSERT INTO `rbac_linked_permissions` (`id`,`linkedId`) VALUES (196,837),(196,838),(196,839),(196,840); diff --git a/sql/updates/world/3.3.5/2016_04_20_00_world.sql b/sql/updates/world/3.3.5/2016_04_20_00_world.sql new file mode 100644 index 00000000000..776254b8fb9 --- /dev/null +++ b/sql/updates/world/3.3.5/2016_04_20_00_world.sql @@ -0,0 +1,7 @@ +-- +-- Add missing Gnomeregan Conjuror/Silvermoon Magister SAI (Cosmetic) +UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry` IN (19006, 19007); +DELETE FROM `smart_scripts` WHERE `entryorguid` IN (19006, 19007) AND `source_type`=0; +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(19006, 0, 0, 0, 25, 0, 100, 0, 0, 0, 0, 0, 11, 32783, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Silvermoon Magister - On Reset - Cast \'Arcane Channeling\''), +(19007, 0, 0, 0, 25, 0, 100, 0, 0, 0, 0, 0, 11, 32783, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Gnomeregan Conjuror - On Reset - Cast \'Arcane Channeling\''); diff --git a/sql/updates/world/3.3.5/2016_04_20_01_world.sql b/sql/updates/world/3.3.5/2016_04_20_01_world.sql new file mode 100644 index 00000000000..19bd02a91f5 --- /dev/null +++ b/sql/updates/world/3.3.5/2016_04_20_01_world.sql @@ -0,0 +1,5 @@ +-- +-- Hairy Herring Heads, Withered Batwings, Wasp's Wings, Muddy Mire Maggots, Knotroot, Spekled Guano, Seasoned Slider Cider, Pickled Eagle Egg, Prismatic Mojo, Raptor Claw +-- Pulverized Gargoyle Teeth, Icerown Bottled Water, Putrid Pirate Perspiration, Spiky Spider Eggs, Abomination Guts, Amberseed, Shrunken Dragom's Claw, Crystallized Hogsnot +-- Ancient Ectoplasm, Chrushed Basilisk Crystals, Blight Crystal, Frozen Spider Ichor, Trollbane, Ghoul Drool, +UPDATE `gameobject` SET `spawntimesecs` = 0 WHERE `id` IN (190459,190461,190462,190463,190464,190465,190466,190467,190468,190469,190470,190471,190472,190473,190474,190476,190477,190478,190479,190480,190481,190482,191180,191181,191182); diff --git a/sql/updates/world/3.3.5/2016_04_20_02_world.sql b/sql/updates/world/3.3.5/2016_04_20_02_world.sql new file mode 100644 index 00000000000..743f1fdab50 --- /dev/null +++ b/sql/updates/world/3.3.5/2016_04_20_02_world.sql @@ -0,0 +1,89 @@ +-- +DELETE FROM `creature_addon` WHERE `guid` IN (202936, 202878, 202950, 202931, 202875, 202884, 202914, 202925, 202934, 202944, 202879, 202945, 202898, 202910, 202912, 202909, 202870, 202949, 202903, 202920, 202922, 202924, 202926, 202939, 202888, 202940, 202882, 202947, 202897, 202937, 202915, 202929, 202935, 202872, 202887, 202942, 202948, 202896, 202900, 202916, 202886, 202923, 202894, 202927, 202913, 202906, 202876, 202941, 202881, 202890, 202907, 202904, 202874, 202880, 202877, 202905, 202873, 202908, 202946, 202917, 202928, 202932, 202943, 202883, 202895, 202951, 202901, 202911, 202885, 202899, 202933, 202868, 202938, 202919, 202921, 202918, 202893, 202891, 202889, 202866, 202871, 202892, 202930, 202902, 202869, 202867); +INSERT INTO `creature_addon` (`guid`, `path_id`, `mount`, `bytes1`, `bytes2`, `emote`, `auras`) VALUES +(202936, 0, 0, 0, 1, 0, '66321 55944'), -- Argent Crusade Spectator +(202878, 0, 0, 0, 1, 0, '66321 55944 66370'), -- Tauren Coliseum Spectator +(202950, 0, 0, 0, 1, 0, '66321 55944 66361'), -- Argent Crusade Spectator, 66361 - Argent Crusade Pennant +(202931, 0, 0, 0, 1, 0, '66321 55944'), -- [ph] Argent Raid Spectator - FX - Draenei +(202875, 0, 0, 0, 1, 0, '66321 55944'), -- Troll Coliseum Spectator +(202884, 0, 0, 0, 1, 0, '66321 55944 66369'), -- Orcish Coliseum Spectator +(202914, 0, 0, 0, 1, 0, '66321 55944'), -- Human Coliseum Spectator +(202925, 0, 0, 0, 1, 0, '66321 55944'), -- [ph] Argent Raid Spectator - FX - Orc +(202934, 0, 0, 0, 1, 0, '66321 55944 66361'), -- Argent Crusade Spectator +(202944, 0, 0, 0, 1, 0, '66321 55944 66361'), -- Argent Crusade Spectator +(202879, 0, 0, 0, 1, 0, '66321 55944 66370'), -- Tauren Coliseum Spectator +(202945, 0, 0, 0, 1, 0, '66321 55944'), -- Argent Crusade Spectator +(202898, 0, 0, 0, 1, 0, '66321 55944'), -- Blood Elf Coliseum Spectator +(202910, 0, 0, 0, 1, 0, '66321 55944 66366'), -- Gnomish Coliseum Spectator +(202912, 0, 0, 0, 1, 0, '66321 55944'), -- Human Coliseum Spectator +(202909, 0, 0, 0, 1, 0, '66321 55944'), -- Gnomish Coliseum Spectator +(202870, 0, 0, 0, 1, 0, '66321 55944'), -- Dwarven Coliseum Spectator +(202949, 0, 0, 0, 1, 0, '66321 55944'), -- Argent Crusade Spectator +(202903, 0, 0, 0, 1, 0, '66321 55944 66362'), -- Draenei Coliseum Spectator +(202920, 0, 0, 0, 1, 0, '66321 55944'), -- Night Elf Coliseum Spectator +(202922, 0, 0, 0, 1, 0, '66321 55944'), -- [ph] Argent Raid Spectator - FX - Horde +(202924, 0, 0, 0, 1, 0, '66321 55944'), -- [ph] Argent Raid Spectator - FX - Human +(202926, 0, 0, 0, 1, 0, '66321 55944'), -- [ph] Argent Raid Spectator - FX - Troll +(202939, 0, 0, 0, 1, 0, '66321 55944'), -- Argent Crusade Spectator +(202888, 0, 0, 0, 1, 0, '66321 55944'), -- Orcish Coliseum Spectator +(202940, 0, 0, 0, 1, 0, '66321 55944'), -- Argent Crusade Spectator +(202882, 0, 0, 0, 1, 0, '66321 55944'), -- Tauren Coliseum Spectator +(202947, 0, 0, 0, 1, 0, '66321 55944'), -- Argent Crusade Spectator +(202897, 0, 0, 0, 1, 0, '66321 55944 66360'), -- Blood Elf Coliseum Spectator, 66360 - Silvermoon Pennant +(202937, 0, 0, 0, 1, 0, '66321 55944 66361'), -- Argent Crusade Spectator +(202915, 0, 0, 0, 1, 0, '66321 55944 66367'), -- Human Coliseum Spectator +(202929, 0, 0, 0, 1, 0, '66321 55944'), -- [ph] Argent Raid Spectator - FX - Undead +(202935, 0, 0, 0, 1, 0, '66321 55944'), -- Argent Crusade Spectator +(202872, 0, 0, 0, 1, 0, '66321 55944 66371'), -- Troll Coliseum Spectator +(202887, 0, 0, 0, 1, 0, '66321 55944'), -- Orcish Coliseum Spectator +(202942, 0, 0, 0, 1, 0, '66321 55944'), -- Argent Crusade Spectator +(202948, 0, 0, 0, 1, 0, '66321 55944'), -- Argent Crusade Spectator +(202896, 0, 0, 0, 1, 0, '66321 55944'), -- Blood Elf Coliseum Spectator +(202900, 0, 0, 0, 1, 0, '66321 55944'), -- Draenei Coliseum Spectator +(202916, 0, 0, 0, 1, 0, '66321 55944 66367'), -- Human Coliseum Spectator +(202886, 0, 0, 0, 1, 0, '66321 55944'), -- Orcish Coliseum Spectator +(202923, 0, 0, 0, 1, 0, '66321 55944'), -- [ph] Argent Raid Spectator - FX - Alliance +(202894, 0, 0, 0, 1, 0, '66321 55944 66360'), -- Blood Elf Coliseum Spectator +(202927, 0, 0, 0, 1, 0, '66321 55944'), -- [ph] Argent Raid Spectator - FX - Tauren +(202913, 0, 0, 0, 1, 0, '66321 55944'), -- Human Coliseum Spectator +(202906, 0, 0, 0, 1, 0, '66321 55944'), -- Gnomish Coliseum Spectator +(202876, 0, 0, 0, 1, 0, '66321 55944'), -- Troll Coliseum Spectator +(202941, 0, 0, 0, 1, 0, '66321 55944'), -- Argent Crusade Spectator +(202881, 0, 0, 0, 1, 0, '66321 55944'), -- Tauren Coliseum Spectator +(202890, 0, 0, 0, 1, 0, '66321 55944 66365'), -- Forsaken Coliseum Spectator +(202907, 0, 0, 0, 1, 0, '66321 55944 66366'), -- Gnomish Coliseum Spectator +(202904, 0, 0, 0, 1, 0, '66321 55944 66362'), -- Draenei Coliseum Spectator +(202874, 0, 0, 0, 1, 0, '66321 55944'), -- Troll Coliseum Spectator +(202880, 0, 0, 0, 1, 0, '66321 55944'), -- Tauren Coliseum Spectator +(202877, 0, 0, 0, 1, 0, '66321 55944 66371'), -- Troll Coliseum Spectator, 66371 - Sen'jin Pennant +(202905, 0, 0, 0, 1, 0, '66321 55944'), -- Gnomish Coliseum Spectator +(202873, 0, 0, 0, 1, 0, '66321 55944 66371'), -- Troll Coliseum Spectator +(202908, 0, 0, 0, 1, 0, '66321 55944 66366'), -- Gnomish Coliseum Spectator +(202946, 0, 0, 0, 1, 0, '66321 55944'), -- Argent Crusade Spectator +(202917, 0, 0, 0, 1, 0, '66321 55944'), -- Night Elf Coliseum Spectator +(202928, 0, 0, 0, 1, 0, '66321 55944'), -- [ph] Argent Raid Spectator - FX - Blood Elf +(202932, 0, 0, 0, 1, 0, '66321 55944'), -- [ph] Argent Raid Spectator - FX - Night Elf +(202943, 0, 0, 0, 1, 0, '66321 55944'), -- Argent Crusade Spectator +(202883, 0, 0, 0, 1, 0, '66321 55944 66369'), -- Orcish Coliseum Spectator +(202895, 0, 0, 0, 1, 0, '66321 55944 66360'), -- Blood Elf Coliseum Spectator +(202951, 0, 0, 0, 1, 0, '66321 55944'), -- Argent Crusade Spectator +(202901, 0, 0, 0, 1, 0, '66321 55944 66362'), -- Draenei Coliseum Spectator +(202911, 0, 0, 0, 1, 0, '66321 55944'), -- Human Coliseum Spectator +(202885, 0, 0, 0, 1, 0, '66321 55944'), -- Orcish Coliseum Spectator +(202899, 0, 0, 0, 1, 0, '66321 55944'), -- Blood Elf Coliseum Spectator +(202933, 0, 0, 0, 1, 0, '66321 55944'), -- [ph] Argent Raid Spectator - FX - Gnome +(202868, 0, 0, 0, 1, 0, '66321 55944 66363'), -- Dwarven Coliseum Spectator, 66363 - Ironforge Pennant +(202938, 0, 0, 0, 1, 0, '66321 55944'), -- Argent Crusade Spectator +(202919, 0, 0, 0, 1, 0, '66321 55944 66368'), -- Night Elf Coliseum Spectator, 66368 - Darnassus Pennant +(202921, 0, 0, 0, 1, 0, '66321 55944 66368'), -- Night Elf Coliseum Spectator +(202918, 0, 0, 0, 1, 0, '66321 55944'), -- Night Elf Coliseum Spectator +(202893, 0, 0, 0, 1, 0, '66321 55944'), -- Forsaken Coliseum Spectator +(202891, 0, 0, 0, 1, 0, '66321 55944'), -- Forsaken Coliseum Spectator +(202889, 0, 0, 0, 1, 0, '66321 55944 66365'), -- Forsaken Coliseum Spectator +(202866, 0, 0, 0, 1, 0, '66321 55944 66363'), -- Dwarven Coliseum Spectator, 66363 - Ironforge Pennant +(202871, 0, 0, 0, 1, 0, '66321 55944 66363'), -- Dwarven Coliseum Spectator +(202892, 0, 0, 0, 1, 0, '66321 55944 66365'), -- Forsaken Coliseum Spectator, 66365 - Undercity Pennant +(202930, 0, 0, 0, 1, 0, '66321 55944'), -- [ph] Argent Raid Spectator - FX - Dwarf +(202902, 0, 0, 0, 1, 0, '66321 55944'), -- Draenei Coliseum Spectator +(202869, 0, 0, 0, 1, 0, '66321 55944'), -- Dwarven Coliseum Spectator +(202867, 0, 0, 0, 1, 0, '66321 55944'); -- Dwarven Coliseum Spectator diff --git a/sql/updates/world/3.3.5/2016_04_20_03_world.sql b/sql/updates/world/3.3.5/2016_04_20_03_world.sql new file mode 100644 index 00000000000..11fc8de7329 --- /dev/null +++ b/sql/updates/world/3.3.5/2016_04_20_03_world.sql @@ -0,0 +1,4 @@ +-- +DELETE FROM `smart_scripts` WHERE `entryorguid` IN (27435) AND `source_type`=0 AND `id`=2; +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(27435, 0, 2, 0, 63, 0, 100, 0, 0, 0, 0, 0, 18, 512, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Wintergarde Mine Bomb - Just created - Set immune to NPC'); diff --git a/sql/updates/world/3.3.5/2016_04_22_00_world.sql b/sql/updates/world/3.3.5/2016_04_22_00_world.sql new file mode 100644 index 00000000000..e98ef9cf7e6 --- /dev/null +++ b/sql/updates/world/3.3.5/2016_04_22_00_world.sql @@ -0,0 +1,20 @@ +DELETE FROM `smart_scripts` WHERE `entryorguid`=2964700 AND `source_type`=9; +DELETE FROM `smart_scripts` WHERE `entryorguid`IN(29647,29884) AND `source_type`=0; + +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(29647, 0, 0, 1, 62, 0, 100, 0, 9852, 2, 0, 0, 72, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'Gymer - On Gossip Option 2 Selected - Close Gossip'), -- 21:50:33.764 +(29647, 0, 1, 2, 61, 0, 100, 0, 0, 0, 0, 0, 11, 55568, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'Gymer - On Gossip Option 2 Selected - Cast Summon Gymer (Force)'), -- 21:50:33.967 +(29647, 0, 4, 0, 1, 0, 100, 0, 10000, 20000, 30000, 40000, 1, 1, 5000, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Gymer - Out of Combat - Say Line 1'), +(29647, 0, 5, 0, 20, 0, 100, 0, 12916, 0, 0, 0, 1, 7, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Gymer - On Quest reward - Say Line 7'), +(29884, 0, 0, 1, 54, 0, 100, 0, 0, 0, 0, 0, 86, 55430, 2, 7, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Gymer - On Just Summoned - Cast Gymers Buddy'), -- 21:50:35.090 +(29884, 0, 1, 0, 61, 0, 100, 1, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Gymer - On Just Summoned - Set Passive'), +(29884, 0, 2, 3, 27, 0, 100, 1, 0, 0, 0, 0, 44, 256, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Gymer - On Passenger Boarded - Set Phase 256'), +(29884, 0, 3, 0, 61, 0, 100, 1, 0, 0, 0, 0, 1, 8, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Gymer - On Passenger Boarded - Say Line 8 (No Repeat)'), +(29884, 0, 4, 0, 61, 0, 100, 1, 0, 0, 0, 0, 11, 55461, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Gymer - On Passenger Boarded - Cast Storms Fury'), +(29884, 0, 5, 6, 28, 0, 100, 1, 0, 0, 0, 0, 44, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Gymer - On Passenger Removed - Set Phase 1'), +(29884, 0, 6, 7, 61, 0, 100, 0, 0, 0, 0, 0, 1, 10, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Gymer - On Passenger Removed - Say Line 10'), +(29884, 0, 7, 0, 61, 0, 100, 0, 0, 0, 0, 0, 41, 5000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Gymer - On Passenger Removed - Despawn after 5 seconds'); + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=22 AND `SourceEntry`=29884; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES +(22, 6, 29884, 0, 0, 31, 0, 4, 0, 0, 0, 0, 0, '', 'Gymer only despawns if player leaves vehicle (not if mob thrown)'); diff --git a/sql/updates/world/3.3.5/2016_04_23_00_world.sql b/sql/updates/world/3.3.5/2016_04_23_00_world.sql new file mode 100644 index 00000000000..fe5d5c7ccb6 --- /dev/null +++ b/sql/updates/world/3.3.5/2016_04_23_00_world.sql @@ -0,0 +1,7 @@ +-- +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=19 AND (`SourceEntry`=11586 OR `SourceEntry`=11585); +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceEntry`,`ConditionTypeOrReference`,`ConditionValue1`,`Comment`) VALUES +(19, 11585, 14, 10172, "Accept quest 11585 - Quest 10172 needs to be incomplete"), +(19, 11586, 8, 10172, "Accept quest 11586 - Quest 10172 needs to be rewarded"); + +UPDATE `quest_template_addon` SET `ExclusiveGroup`=11585 WHERE `ID`IN(11585,11586); diff --git a/sql/updates/world/3.3.5/2016_04_23_01_world.sql b/sql/updates/world/3.3.5/2016_04_23_01_world.sql new file mode 100644 index 00000000000..d1be7adacfc --- /dev/null +++ b/sql/updates/world/3.3.5/2016_04_23_01_world.sql @@ -0,0 +1,4 @@ +DELETE FROM `spell_script_names` WHERE `ScriptName` IN ('spell_item_decahedral_dwarven_dice', 'spell_item_worn_troll_dice'); +INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES +(47770, 'spell_item_decahedral_dwarven_dice'), +(47776, 'spell_item_worn_troll_dice'); diff --git a/sql/updates/world/3.3.5/2016_04_23_02_world.sql b/sql/updates/world/3.3.5/2016_04_23_02_world.sql new file mode 100644 index 00000000000..e3806947c9c --- /dev/null +++ b/sql/updates/world/3.3.5/2016_04_23_02_world.sql @@ -0,0 +1,19 @@ +-- +UPDATE `creature_template` SET `npcflag`=4096 WHERE `entry`=2404; +UPDATE `creature_template` SET `npcflag`=2 WHERE `entry`=2910; +UPDATE `creature_template` SET `npcflag`=81 WHERE `entry`=7231; +UPDATE `creature_template` SET `npcflag`=128 WHERE `entry`=8121; +UPDATE `creature_template` SET `npcflag`=2 WHERE `entry`=15309; + +DELETE FROM `npc_vendor` WHERE `entry`=8121; +INSERT INTO `npc_vendor` (`entry`, `slot`, `item`) VALUES +(8121, 0, 5740), +(8121, 0, 8624), +(8121, 0, 8625), +(8121, 0, 8626), +(8121, 0, 9312), +(8121, 0, 9313), +(8121, 0, 9314), +(8121, 0, 9315), +(8121, 0, 9317), +(8121, 0, 9318); diff --git a/sql/updates/world/3.3.5/2016_04_24_00_world_335.sql b/sql/updates/world/3.3.5/2016_04_24_00_world_335.sql new file mode 100644 index 00000000000..065c31601cd --- /dev/null +++ b/sql/updates/world/3.3.5/2016_04_24_00_world_335.sql @@ -0,0 +1,3 @@ +-- +-- spell aura effect 53055 from Hand of Salvation should not break invisibility +INSERT INTO `spell_custom_attr` (`entry`,`attributes`) VALUES (53055, 64); diff --git a/sql/updates/world/3.3.5/2016_04_24_01_world.sql b/sql/updates/world/3.3.5/2016_04_24_01_world.sql new file mode 100644 index 00000000000..0d9f3aa6bd7 --- /dev/null +++ b/sql/updates/world/3.3.5/2016_04_24_01_world.sql @@ -0,0 +1,22 @@ +-- +DELETE FROM `smart_scripts` WHERE `entryorguid` IN (17998,17999,18000,18002) AND `id`=1; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(17998,0,1,0,8,0,100,0,31736,0,0,0,12,18340,4,30000,0,0,0,8,0,0,0,-752.349, 5940.811, 18.261, 4.444397,"Umbrafen Steam Pump Credit Marker - On Spellhit 'Ironvine Seeds' - Summon Creature 'Steam Pump Overseer'"), +(17999,0,1,0,8,0,100,0,31736,0,0,0,12,18340,4,30000,0,0,0,8,0,0,0,-227.935, 6307.861, 21.967, 5.719622,"Lagoon Steam Pump Credit Marker - On Spellhit 'Ironvine Seeds' - Summon Creature 'Steam Pump Overseer'"), +(18000,0,1,0,8,0,100,0,31736,0,0,0,12,18340,4,30000,0,0,0,8,0,0,0,579.913, 6342.902, 23.849, 2.159061,"Serpent Steam Pump Credit Marker - On Spellhit 'Ironvine Seeds' - Summon Creature 'Steam Pump Overseer'"), +(18002,0,1,0,8,0,100,0,31736,0,0,0,12,18340,4,30000,0,0,0,8,0,0,0,477.12, 8189.803, 21.985, 0.486592,"Marshlight Steam Pump Credit Marker - On Spellhit 'Ironvine Seeds' - Summon Creature 'Steam Pump Overseer'"); + +SET @ENTRY := 18340; + +UPDATE `creature_template_addon` SET `auras`="6961 33962" WHERE `entry`=@ENTRY; +UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry`=@ENTRY; +DELETE FROM `smart_scripts` WHERE `source_type`=0 AND `entryorguid`=@ENTRY; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@ENTRY,0,0,1,54,0,100,0,0,0,0,0,1,0,0,0,0,0,0,21,40,0,0,0,0,0,0,'Steam Pump Overseer - Just summoned - Say text'), +(@ENTRY,0,1,0,61,0,100,0,0,0,0,0,49,0,0,0,0,0,0,21,40,0,0,0,0,0,0,'Steam Pump Overseer - Just summoned - Start attack'); + +DELETE FROM `creature_text` WHERE `entry`=@ENTRY; +INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`language`,`probability`,`emote`,`duration`,`sound`,`comment`, `BroadcastTextId`) VALUES +(@ENTRY,0,0, 'I will show you not to cross us again!',12,0,100,0,0,0, 'Steam Pump Overseer', 15202), +(@ENTRY,0,1, 'Warlord Kalithresh will hear of this insolence!',12,0,100,0,0,0, 'Steam Pump Overseer', 15201), +(@ENTRY,0,2, 'I''ll make you pay for that!',12,0,100,0,0,0, 'Steam Pump Overseer', 15199); diff --git a/sql/updates/world/3.3.5/2016_04_25_00_world.sql b/sql/updates/world/3.3.5/2016_04_25_00_world.sql new file mode 100644 index 00000000000..2c603dc5d64 --- /dev/null +++ b/sql/updates/world/3.3.5/2016_04_25_00_world.sql @@ -0,0 +1,2 @@ +-- +UPDATE `creature` SET `modelid`=11686 WHERE `id`=39010; diff --git a/sql/updates/world/3.3.5/2016_04_25_01_world.sql b/sql/updates/world/3.3.5/2016_04_25_01_world.sql new file mode 100644 index 00000000000..f83b99f1710 --- /dev/null +++ b/sql/updates/world/3.3.5/2016_04_25_01_world.sql @@ -0,0 +1,42 @@ +DELETE FROM `smart_scripts` WHERE `entryorguid` IN(24161) AND `source_type`=0 AND `id`>4; +DELETE FROM `smart_scripts` WHERE `entryorguid` IN(24162,24016) AND `source_type`=0 AND `id`>3; +DELETE FROM `smart_scripts` WHERE `entryorguid` IN(24015) AND `source_type`=0 AND `id`>2; + +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(24161, 0, 5, 6, 11, 0, 100, 0, 0, 0, 0, 0, 18, 768, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Oric the Baleful - On Spawn - Set Immune to combat'), +(24161, 0, 6, 0, 61, 0, 100, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Oric the Baleful - On Spawn - Set Invisible'), +(24161, 0, 7, 8, 38, 0, 100, 1, 1, 1, 0, 0, 47, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Oric the Baleful - On Data Set - Enable combat Immune to combat'), +(24161, 0, 8, 9, 61, 0, 100, 1, 0, 0, 0, 0, 19, 768, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Oric the Baleful - On Data Set - Set visible'), +(24161, 0, 9, 0, 61, 0, 100, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Oric the Baleful - On Data Set - Say'), +(24162, 0, 4, 5, 11, 0, 100, 0, 0, 0, 0, 0, 18, 768, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Gunnar Thorvardsson - On Spawn - Set Immune to combat'), +(24162, 0, 5, 0, 61, 0, 100, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Gunnar Thorvardsson - On Spawn - Set Invisible'), +(24162, 0, 6, 7, 38, 0, 100, 1, 1, 1, 0, 0, 47, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Gunnar Thorvardsson - On Data Set - Enable combat Immune to combat'), +(24162, 0, 7, 8, 61, 0, 100, 1, 0, 0, 0, 0, 19, 768, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Gunnar Thorvardsson - On Data Set - Set visible'), +(24162, 0, 8, 0, 61, 0, 100, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Gunnar Thorvardsson - On Data Set - Say'), +(24016, 0, 4, 5, 11, 0, 100, 0, 0, 0, 0, 0, 18, 768, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Ulf the Bloodletter - On Spawn - Set Immune to combat'), +(24016, 0, 5, 0, 61, 0, 100, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Ulf the Bloodletter - On Spawn - Set Invisible'), +(24016, 0, 6, 7, 38, 0, 100, 1, 1, 1, 0, 0, 47, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Ulf the Bloodletter - On Data Set - Enable combat Immune to combat'), +(24016, 0, 7, 8, 61, 0, 100, 1, 0, 0, 0, 0, 19, 768, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Ulf the Bloodletter - On Data Set - Set visible'), +(24016, 0, 8, 0, 61, 0, 100, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Ulf the Bloodletter - On Data Set - Say'), +(24015, 0, 3, 0, 6, 0, 15, 0, 0, 0, 0, 0, 45, 1, 1, 0, 0, 0, 0, 19, 24161, 0, 0, 0, 0, 0, 0, 'Winterskorn Defender - On Death - Set Data on Oric the Baleful'), +(24015, 0, 4, 0, 6, 0, 15, 0, 0, 0, 0, 0, 45, 1, 1, 0, 0, 0, 0, 19, 24162, 0, 0, 0, 0, 0, 0, 'Winterskorn Defender - On Death - Set Data on Gunnar Thorvardsson'), +(24015, 0, 5, 0, 6, 0, 15, 0, 0, 0, 0, 0, 45, 1, 1, 0, 0, 0, 0, 19, 24016, 0, 0, 0, 0, 0, 0, 'Winterskorn Defender - On Death - Set Data on Ulf the Bloodletter'); + +DELETE FROM `creature_text` WHERE `entry` IN(24161,24162,24016); +INSERT INTO `creature_text` (`entry`, `groupid`, `id`, `text`, `type`, `language`, `probability`, `emote`, `duration`, `sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES +(24161, 0, 0, 'Enemies of the Winterskorn, you will be torn limb from limb!', 14, 0, 100, 0, 0, 0, 22867, 0, 'Oric the Baleful'), +(24016, 0, 0, 'Drive this scum from the Vrykul homeland!', 14, 0, 100, 0, 0, 0, 22868, 0, 'Ulf the Bloodletter'), +(24162, 0, 0, 'Gunnar, son of Thorvard, has arrived! Prepare to meet your demise!', 14, 0, 100, 0, 0, 0, 22863, 0, 'Gunnar Thorvardsson'); + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=22 AND `SourceEntry` IN(24161,24162,24016,24015); +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES +(22, 6, 24161, 0, 0, 36, 1, 0, 0, 0, 0, 0, 0, '', 'Only execute SAI if Oric the Baleful alive'), +(22, 5, 24016, 0, 0, 36, 1, 0, 0, 0, 0, 0, 0, '', 'Only execute SAI if Ulf the Bloodletter alive'), +(22, 5, 24162, 0, 0, 36, 1, 0, 0, 0, 0, 0, 0, '', 'Only execute SAI if Gunnar Thorvardsson alive'), +(22, 4, 24015, 0, 0, 9, 0, 11282, 0, 0, 0, 0, 0, '', 'Only execute SAI if player has A Lesson in Fear taken'), +(22, 5, 24015, 0, 0, 9, 0, 11282, 0, 0, 0, 0, 0, '', 'Only execute SAI if player has A Lesson in Fear taken'), +(22, 6, 24015, 0, 0, 9, 0, 11282, 0, 0, 0, 0, 0, '', 'Only execute SAI if player has A Lesson in Fear taken'); + +UPDATE `smart_scripts` SET `link`=0 WHERE `entryorguid`=29647 AND `source_type`=0 AND `id`=1 AND `link`=2; +UPDATE `smart_scripts` SET `link`=4 WHERE `entryorguid`=29884 AND `source_type`=0 AND `id`=3 AND `link`=0; + diff --git a/sql/updates/world/3.3.5/2016_04_25_02_world.sql b/sql/updates/world/3.3.5/2016_04_25_02_world.sql new file mode 100644 index 00000000000..31d98dd616c --- /dev/null +++ b/sql/updates/world/3.3.5/2016_04_25_02_world.sql @@ -0,0 +1,48 @@ +-- +SET @Aura1:=44880; +SET @Flare:=24916; +SET @Grow:=44944; +SET @Visual:=44877; +SET @MiniExplosion:=44943; +SET @Unstable:=24958; +SET @Aura2:=46196; +SET @Explosion:=46225; +SET @credit:=44947; +SET @Flame:=22323; + +UPDATE `creature_template` SET `unit_flags`=776, `faction`=1629, `InhabitType`=4, `AIName`='SmartAI' WHERE `entry`in (@Flare, @Unstable); +UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry`in (@Flame); + +DELETE FROM `creature_template_addon` WHERE `entry`=@Flare; +INSERT INTO `creature_template_addon` (`entry`,`bytes2`,`auras`) VALUES (@Flare,1,@Aura1); + +DELETE FROM `smart_scripts` WHERE `entryorguid` = @Flame AND `source_type` = 0; +DELETE FROM `smart_scripts` WHERE `entryorguid` = @Flare AND `source_type` = 0; +DELETE FROM `smart_scripts` WHERE `entryorguid` = @Flare*100 AND `source_type` = 9; +DELETE FROM `smart_scripts` WHERE `entryorguid` = @Flare*100+1 AND `source_type` = 9; +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(@Flare, 0, 0, 0, 54, 0, 100, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Flare - Just summoned - React passif'), +(@Flare, 0, 1, 0, 23, 0, 100, 1, @Grow, 8, 0, 0, 80, @Flare*100, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Flare - has aura x 8 - Action list'), +(@Flare*100, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 11, @MiniExplosion, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Flare - Action list - cast'), +(@Flare*100, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 3, @Unstable, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Flare - Action list - morph'), +(@Flare*100, 9, 2, 0, 0, 0, 100, 0, 0, 0, 0, 0, 28, @Aura1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Flare - Action list - Remove aura'), +(@Flare*100, 9, 3, 0, 0, 0, 100, 0, 0, 0, 0, 0, 11, @Aura2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Flare - Action list - Add aura'), +(@Flare*100, 9, 4, 0, 0, 0, 100, 0, 1000, 1000, 0, 0, 53, 1, @Flare, 0, 0, 500, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Flare - Action list - Start way point'), +(@Flare, 0, 2, 0, 58, 0, 100, 0, 0, 0, 0, 0, 80, @Flare*100+1, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Unstable - On way point Ended - Action list'), +(@Flare*100+1, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 11, @Explosion, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Flare - Action list - Cast'), +(@Flare*100+1, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 11, @credit, 0, 0, 0, 0, 0, 23, 0, 0, 0, 0, 0, 0, 0, 'Unstable - Action list - Cast'), +(@Flare*100+1, 9, 2, 0, 0, 0, 100, 0, 500, 500, 0, 0, 41, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Flare - Action list - despawn'), +(@Flare, 0, 3, 0, 38, 0, 100, 0, 1, 1, 0, 0, 11, @Visual, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Flare - On data set- cast'), +(@Flame, 0, 0, 0, 0, 0, 100, 0, 3000, 3000, 5000, 5000, 11, 36247, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 'Flare - IC - Cast'), +(@Flame, 0, 1, 0, 6, 0, 100, 0, 0, 0, 0, 0, 45, 1, 1, 0, 0, 0, 0, 19, @Flare, 40, 0, 0, 0, 0, 0, 'Flare - On death - Set Data'); + +DELETE FROM `waypoints` WHERE `entry`=@Flare; +INSERT INTO `waypoints` (`entry`,`pointid`,`position_x`,`position_y`,`position_z`,`point_comment`) VALUES +(@Flare,1, 828.737000, 2509.100098, 300.700012,'Flare'); + +DELETE FROM `spell_linked_spell` WHERE `spell_trigger` = @Visual; +INSERT INTO `spell_linked_spell` VALUES (@Visual, @Grow, 0, 'Flare Aura'); + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry`=@Visual; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`SourceId`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionTarget`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorType`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES +(13,1,@Visual,0,0,31,0,3,@Flare,0,0,0,0,'','Only the Flare is a target for the spell.'); diff --git a/sql/updates/world/3.3.5/2016_04_25_03_world.sql b/sql/updates/world/3.3.5/2016_04_25_03_world.sql new file mode 100644 index 00000000000..7bbd279e943 --- /dev/null +++ b/sql/updates/world/3.3.5/2016_04_25_03_world.sql @@ -0,0 +1,47 @@ +SET @CGUID := 145119; + +DELETE FROM `creature` WHERE `id`=21788; +INSERT INTO `creature` (`guid`, `id`, `map`, `zoneId`, `areaId`, `spawnMask`, `phaseMask`, `modelid`, `equipment_id`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `spawndist`, `currentwaypoint`, `curhealth`, `curmana`, `MovementType`, `npcflag`, `unit_flags`, `dynamicflags`, `VerifiedBuild`) VALUES +(@CGUID+0, 21788, 530, 0, 0, 1, 1, 0, 0, -3090.62, 2402.483, 63.14528, 4.310963, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 0) (Auras: 37509 - 37509) +(@CGUID+1, 21788, 530, 0, 0, 1, 1, 0, 0, -3115.362, 2440.234, 64.67137, 1.902409, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 0) (Auras: 37509 - 37509) +(@CGUID+2, 21788, 530, 0, 0, 1, 1, 0, 0, -3138.009, 2452.761, 63.82878, 4.153883, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 0) (Auras: 37509 - 37509) +(@CGUID+3, 21788, 530, 0, 0, 1, 1, 0, 0, -3068.807, 2447.557, 64.62611, 1.380292, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 0) (Auras: 37509 - 37509) +(@CGUID+4, 21788, 530, 0, 0, 1, 1, 0, 0, -3125.387, 2489.521, 62.06233, 5.113815, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 0) (Auras: 37509 - 37509) +(@CGUID+5, 21788, 530, 0, 0, 1, 1, 0, 0, -3061.514, 2459.645, 65.18143, 4.520403, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 0) (Auras: 37509 - 37509) +(@CGUID+6, 21788, 530, 0, 0, 1, 1, 0, 0, -3122.754, 2501.015, 62.70392, 5.51524, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 0) (Auras: 37509 - 37509) +(@CGUID+7, 21788, 530, 0, 0, 1, 1, 0, 0, -3034.208, 2499.923, 63.14324, 1.48353, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 0) (Auras: 37509 - 37509) +(@CGUID+8, 21788, 530, 0, 0, 1, 1, 0, 0, -3079.527, 2527.942, 62.65857, 0.1570796, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 0) (Auras: 37509 - 37509) +(@CGUID+9, 21788, 530, 0, 0, 1, 1, 0, 0, -3067.415, 2495.909, 64.73977, 1.570796, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 0) (Auras: 37509 - 37509) +(@CGUID+10, 21788, 530, 0, 0, 1, 1, 0, 0, -3130.252, 2537.187, 61.81245, 0.9250245, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 3744) (Auras: 37509 - 37509) +(@CGUID+11, 21788, 530, 0, 0, 1, 1, 0, 0, -3036.085, 2528.19, 63.41149, 5.166174, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 3744) (Auras: 37509 - 37509) +(@CGUID+12, 21788, 530, 0, 0, 1, 1, 0, 0, -3001.511, 2507.445, 61.33947, 1.553343, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 3744) (Auras: 37509 - 37509) +(@CGUID+13, 21788, 530, 0, 0, 1, 1, 0, 0, -3020.436, 2502.759, 62.7676, 0.296706, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 3744) (Auras: 37509 - 37509) +(@CGUID+14, 21788, 530, 0, 0, 1, 1, 0, 0, -3061.437, 2541.203, 62.35847, 4.361612, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 3744) (Auras: 37509 - 37509) +(@CGUID+15, 21788, 530, 0, 0, 1, 1, 0, 0, -3022.704, 2512.111, 68.65653, 0.3839724, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 3744) (Auras: 37509 - 37509) +(@CGUID+16, 21788, 530, 0, 0, 1, 1, 0, 0, -3016.363, 2549.719, 79.11957, 1.291544, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 3744) (Auras: 37509 - 37509) +(@CGUID+17, 21788, 530, 0, 0, 1, 1, 0, 0, -3104.333, 2552.007, 61.75181, 5.380099, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 3744) (Auras: 37509 - 37509) +(@CGUID+18, 21788, 530, 0, 0, 1, 1, 0, 0, -3115.356, 2556.791, 61.91945, 0.3141593, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 3744) (Auras: 37509 - 37509) +(@CGUID+19, 21788, 530, 0, 0, 1, 1, 0, 0, -3133.627, 2548.74, 62.05401, 6.195919, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 3744) (Auras: 37509 - 37509) +(@CGUID+20, 21788, 530, 0, 0, 1, 1, 0, 0, -2985.531, 2556.819, 76.62669, 3.961897, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 3744) (Auras: 37509 - 37509) +(@CGUID+21, 21788, 530, 0, 0, 1, 1, 0, 0, -2987.325, 2568.416, 76.62669, 5.846853, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 3744) (Auras: 37509 - 37509) +(@CGUID+22, 21788, 530, 0, 0, 1, 1, 0, 0, -3116.468, 2572.71, 61.88921, 0.1047198, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 3744) (Auras: 37509 - 37509) +(@CGUID+23, 21788, 530, 0, 0, 1, 1, 0, 0, -3090.439, 2579.877, 61.85312, 4.817109, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 3744) (Auras: 37509 - 37509) +(@CGUID+24, 21788, 530, 0, 0, 1, 1, 0, 0, -3147.669, 2577.585, 62.38097, 1.867502, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 3744) (Auras: 37509 - 37509) +(@CGUID+25, 21788, 530, 0, 0, 1, 1, 0, 0, -3133.15, 2585.913, 61.80721, 2.86234, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 3744) (Auras: 37509 - 37509) +(@CGUID+26, 21788, 530, 0, 0, 1, 1, 0, 0, -3073.789, 2609.983, 61.81239, 1.117011, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 3744) (Auras: 37509 - 37509) +(@CGUID+27, 21788, 530, 0, 0, 1, 1, 0, 0, -3163.902, 2579.588, 62.70355, 0.4886922, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 3744) (Auras: 37509 - 37509) +(@CGUID+28, 21788, 530, 0, 0, 1, 1, 0, 0, -3144.146, 2617.151, 61.85558, 3.752458, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 3744) (Auras: 37509 - 37509) +(@CGUID+29, 21788, 530, 0, 0, 1, 1, 0, 0, -2963.017, 2518.091, 78.19579, 0.1047198, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 3744) (Auras: 37509 - 37509) +(@CGUID+30, 21788, 530, 0, 0, 1, 1, 0, 0, -2965.681, 2540.958, 76.62669, 4.45059, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 3744) (Auras: 37509 - 37509) +(@CGUID+31, 21788, 530, 0, 0, 1, 1, 0, 0, -2977.325, 2574.976, 76.62669, 1.413717, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 3744) (Auras: 37509 - 37509) +(@CGUID+32, 21788, 530, 0, 0, 1, 1, 0, 0, -2999.423, 2619.978, 76.7438, 1.658063, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 3744) (Auras: 37509 - 37509) +(@CGUID+33, 21788, 530, 0, 0, 1, 1, 0, 0, -3046.553, 2641.27, 76.62669, 5.916666, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 3744) (Auras: 37509 - 37509) +(@CGUID+34, 21788, 530, 0, 0, 1, 1, 0, 0, -3028.977, 2656.449, 77.04675, 4.206244, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 3744) (Auras: 37509 - 37509) +(@CGUID+35, 21788, 530, 0, 0, 1, 1, 0, 0, -2945.421, 2632.53, 91.97811, 3.910418, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 3744) (Auras: 37509 - 37509) +(@CGUID+36, 21788, 530, 0, 0, 1, 1, 0, 0, -2907.585, 2603.013, 93.76357, 2.426008, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 3744) (Auras: 37509 - 37509) +(@CGUID+37, 21788, 530, 0, 0, 1, 1, 0, 0, -2903.634, 2615.304, 93.76357, 3.071779, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 3744) (Auras: 37509 - 37509) +(@CGUID+38, 21788, 530, 0, 0, 1, 1, 0, 0, -2926.175, 2646.125, 93.73645, 3.682645, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 3744) (Auras: 37509 - 37509) +(@CGUID+39, 21788, 530, 0, 0, 1, 1, 0, 0, -2932.268, 2652.535, 93.76186, 3.961897, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 3744) (Auras: 37509 - 37509) +(@CGUID+40, 21788, 530, 0, 0, 1, 1, 0, 0, -2939.042, 2675.208, 93.76357, 4.433136, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463); -- 21788 (Area: 3744) (Auras: 37509 - 37509) + +UPDATE `creature_template_addon` SET `bytes1`=65536, `bytes2`=1 WHERE `entry`=21788; diff --git a/sql/updates/world/3.3.5/2016_04_26_00_world.sql b/sql/updates/world/3.3.5/2016_04_26_00_world.sql new file mode 100644 index 00000000000..72201221944 --- /dev/null +++ b/sql/updates/world/3.3.5/2016_04_26_00_world.sql @@ -0,0 +1,9 @@ +-- +UPDATE `creature_template` SET `flags_extra`=`flags_extra`|128 WHERE `entry` IN (33395,14031,22586,22585,14030,22584,14027,22583,14028,14029,22581,14026,33402,31878,33691,33942,34189,31462,37634,34153,39011,39012,39013,20654,31461,31670,33907,33906,33353,33352,34228,31875,30757,21584,34131,26337); +UPDATE `creature_template` SET `flags_extra`=`flags_extra`|2 WHERE `entry`=30777; + +UPDATE `creature_template` SET `flags_extra`=`flags_extra`|130 WHERE `entry` IN (21625,31874); + +UPDATE `creature_template` SET `flags_extra`=`flags_extra`|256 WHERE `entry` IN (20596,20745); + +UPDATE `creature_template` SET `flags_extra`=`flags_extra`&~1 WHERE `entry` IN (27309,27308,27307,27303); diff --git a/sql/updates/world/3.3.5/2016_04_26_01_world.sql b/sql/updates/world/3.3.5/2016_04_26_01_world.sql new file mode 100644 index 00000000000..2021a40a9e7 --- /dev/null +++ b/sql/updates/world/3.3.5/2016_04_26_01_world.sql @@ -0,0 +1,57 @@ +SET @CGUID := 145160; + +DELETE FROM `creature` WHERE `id`=21795; +INSERT INTO `creature` (`guid`, `id`, `map`, `zoneId`, `areaId`, `spawnMask`, `phaseMask`, `modelid`, `equipment_id`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `spawndist`, `currentwaypoint`, `curhealth`, `curmana`, `MovementType`, `npcflag`, `unit_flags`, `dynamicflags`, `VerifiedBuild`) VALUES +(@CGUID+0, 21795, 530, 0, 0, 1, 1, 0, 0, -3942.646, 2125.487, 96.96626, 5.357957, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509) +(@CGUID+1, 21795, 530, 0, 0, 1, 1, 0, 0, -3943.109, 2193.898, 102.1291, 3.368572, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509) +(@CGUID+2, 21795, 530, 0, 0, 1, 1, 0, 0, -4037.24, 2260.579, 113.4364, 3.5118, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509) +(@CGUID+3, 21795, 530, 0, 0, 1, 1, 0, 0, -4023.835, 2206.558, 109.6129, 4.895111, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509) +(@CGUID+4, 21795, 530, 0, 0, 1, 1, 0, 0, -4030.965, 2168.763, 107.4985, 2.480213, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509) +(@CGUID+5, 21795, 530, 0, 0, 1, 1, 0, 0, -3951.485, 2265.172, 99.24145, 2.606144, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509) +(@CGUID+6, 21795, 530, 0, 0, 1, 1, 0, 0, -4042.551, 2183.728, 109.3237, 3.009561, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509) +(@CGUID+7, 21795, 530, 0, 0, 1, 1, 0, 0, -3984.742, 2197.148, 102.0214, 4.5442, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509) +(@CGUID+8, 21795, 530, 0, 0, 1, 1, 0, 0, -3956.684, 2233.825, 101.9551, 1.479018, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509) +(@CGUID+9, 21795, 530, 0, 0, 1, 1, 0, 0, -4019.452, 2140.292, 104.274, 0.1288698, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509) +(@CGUID+10, 21795, 530, 0, 0, 1, 1, 0, 0, -4006.475, 2120.42, 115.6417, 1.27439, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509) +(@CGUID+11, 21795, 530, 0, 0, 1, 1, 0, 0, -3940.616, 2152.896, 100.4848, 2.463561, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509) +(@CGUID+12, 21795, 530, 0, 0, 1, 1, 0, 0, -4053.673, 2245.217, 112.0474, 0.036458, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509) +(@CGUID+13, 21795, 530, 0, 0, 1, 1, 0, 0, -3939.613, 2223.242, 101.9156, 3.891035, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509) +(@CGUID+14, 21795, 530, 0, 0, 1, 1, 0, 0, -3973.463, 2119.737, 103.7858, 2.866639, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509) +(@CGUID+15, 21795, 530, 0, 0, 1, 1, 0, 0, -3988.523, 2153.718, 104.368, 6.001884, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509) +(@CGUID+16, 21795, 530, 0, 0, 1, 1, 0, 0, -4070.058, 2227.373, 113.4363, 3.759574, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509) +(@CGUID+17, 21795, 530, 0, 0, 1, 1, 0, 0, -4075.326, 2180.252, 107.5067, 3.183229, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509) +(@CGUID+18, 21795, 530, 0, 0, 1, 1, 0, 0, -4054.947, 2124.536, 137.2578, 2.750937, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509) +(@CGUID+19, 21795, 530, 0, 0, 1, 1, 0, 0, -4087.524, 2167.491, 111.391, 5.241858, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509) +(@CGUID+20, 21795, 530, 0, 0, 1, 1, 0, 0, -4089.124, 2203.606, 97.22453, 5.805306, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509) +(@CGUID+21, 21795, 530, 0, 0, 1, 1, 0, 0, -4080.437, 2179.819, 100.2801, 5.450742, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509) +(@CGUID+22, 21795, 530, 0, 0, 1, 1, 0, 0, -4092.307, 2185.567, 100.2807, 0.1027414, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509) +(@CGUID+23, 21795, 530, 0, 0, 1, 1, 0, 0, -4092.907, 2184.13, 106.9471, 5.606272, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509) +(@CGUID+24, 21795, 530, 0, 0, 1, 1, 0, 0, -3918.483, 2046.919, 95.28484, 6.051655, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509) +(@CGUID+25, 21795, 530, 0, 0, 1, 1, 0, 0, -3913.848, 2107.107, 96.72884, 4.46708, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509) +(@CGUID+26, 21795, 530, 0, 0, 1, 1, 0, 0, -3947.833, 2040.741, 95.10477, 1.199215, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509) +(@CGUID+27, 21795, 530, 0, 0, 1, 1, 0, 0, -3915.87, 2102.719, 96.12863, 1.258105, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509) +(@CGUID+28, 21795, 530, 0, 0, 1, 1, 0, 0, -3839.461, 2121.8, 94.53188, 4.859396, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509) +(@CGUID+29, 21795, 530, 0, 0, 1, 1, 0, 0, -3862.718, 2217.159, 95.1391, 3.999115, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509) +(@CGUID+30, 21795, 530, 0, 0, 1, 1, 0, 0, -3849.665, 2175.306, 95.58624, 3.913765, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509) +(@CGUID+31, 21795, 530, 0, 0, 1, 1, 0, 0, -4053.544, 2279.983, 112.0487, 4.612492, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509) +(@CGUID+32, 21795, 530, 0, 0, 1, 1, 0, 0, -4066.031, 2258.548, 94.8257, 1.571143, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509) +(@CGUID+33, 21795, 530, 0, 0, 1, 1, 0, 0, -4054.627, 2277.048, 121.7723, 4.634171, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509) +(@CGUID+34, 21795, 530, 0, 0, 1, 1, 0, 0, -4070.104, 2263.355, 112.0474, 5.739568, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509) +(@CGUID+35, 21795, 530, 0, 0, 1, 1, 0, 0, -4084.999, 2245.3, 121.7718, 5.480127, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509) +(@CGUID+36, 21795, 530, 0, 0, 1, 1, 0, 0, -4087.486, 2244.981, 112.0474, 2.109367, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509) +(@CGUID+37, 21795, 530, 0, 0, 1, 1, 0, 0, -4073.188, 2267.943, 94.82581, 1.50432, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509) +(@CGUID+38, 21795, 530, 0, 0, 1, 1, 0, 0, -4071.124, 2294.895, 110.6591, 0.204018, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509) +(@CGUID+39, 21795, 530, 0, 0, 1, 1, 0, 0, -4101.815, 2259.789, 110.659, 4.624498, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509) +(@CGUID+40, 21795, 530, 0, 0, 1, 1, 0, 0, -4075.109, 2296.344, 121.7728, 2.60921, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509) +(@CGUID+41, 21795, 530, 0, 0, 1, 1, 0, 0, -4094.75, 2260.984, 103.9927, 0.0229529, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509) +(@CGUID+42, 21795, 530, 0, 0, 1, 1, 0, 0, -4088.135, 2265.592, 103.9921, 3.303511, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509) +(@CGUID+43, 21795, 530, 0, 0, 1, 1, 0, 0, -4087.79, 2283.696, 103.9927, 1.226644, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509) +(@CGUID+44, 21795, 530, 0, 0, 1, 1, 0, 0, -4094.398, 2277.201, 112.0475, 1.09602, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509) +(@CGUID+45, 21795, 530, 0, 0, 1, 1, 0, 0, -4071.222, 2290.098, 103.9934, 0.974121, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509) +(@CGUID+46, 21795, 530, 0, 0, 1, 1, 0, 0, -3823.303, 2124.582, 93.3121, 5.473604, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509) +(@CGUID+47, 21795, 530, 0, 0, 1, 1, 0, 0, -3982.052, 1996.922, 95.26698, 6.067729, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509) +(@CGUID+48, 21795, 530, 0, 0, 1, 1, 0, 0, -3830.084, 2177.76, 93.64696, 5.581445, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509) +(@CGUID+49, 21795, 530, 0, 0, 1, 1, 0, 0, -3821.952, 2218.491, 92.7454, 2.951487, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509) +(@CGUID+50, 21795, 530, 0, 0, 1, 1, 0, 0, -3856.967, 2241.917, 97.24121, 0.3141558, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463); -- 21795 (Area: 3745) (Auras: 37509 - 37509) + +UPDATE `creature_template_addon` SET `bytes1`=65536, `bytes2`=1 WHERE `entry`=21795; diff --git a/sql/updates/world/3.3.5/2016_04_26_02_world.sql b/sql/updates/world/3.3.5/2016_04_26_02_world.sql new file mode 100644 index 00000000000..4df837e0d8f --- /dev/null +++ b/sql/updates/world/3.3.5/2016_04_26_02_world.sql @@ -0,0 +1,16 @@ +-- +SET @ENTRY := 8035; +-- Apply taunt sound effect instead of the Avatar of Hakkar's aggro sound +UPDATE `creature_text` SET `sound`=3216 WHERE `entry` = @ENTRY AND `groupid` = 1 AND `id` = 0; +-- Apply UNIT_FLAG_DISABLE_MOVE, UNIT_FLAG_PACIFIED, and UNIT_FLAG_DISARMED +-- Extra OR's are for at-a-glance convenience +UPDATE `creature_template` SET `unit_flags`= `unit_flags` | 4 | 131072 | 2097152 WHERE `Entry`= @ENTRY; +-- Inserting an SAI event to make Dark Iron Land Mines not detonate prematurely. +DELETE FROM `smart_scripts` WHERE `entryorguid` = @ENTRY AND `source_type`=0; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@ENTRY,0,0,0,1,0,100,3,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,'Dark Iron Land Mine - Out of Combat - Say Line 0'), +(@ENTRY,0,1,0,1,0,100,3,5000,5000,0,0,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,'Dark Iron Land Mine - Out of Combat - Say Line 1'), +(@ENTRY,0,2,0,1,0,100,3,10000,10000,0,0,1,2,0,0,0,0,0,1,0,0,0,0,0,0,0,'Dark Iron Land Mine - Out of Combat - Say Line 2'), +(@ENTRY,0,3,0,1,0,100,3,10000,10000,0,0,19,131072,0,0,0,0,0,1,0,0,0,0,0,0,0,'Dark Iron Land Mine - Out of Combat - Remove Pacified Flag after 10s'), +(@ENTRY,0,4,0,9,0,100,3,0,8,0,0,11,4043,0,0,0,0,0,1,0,0,0,0,0,0,0,'Dark Iron Land Mine - Within 0-8 Range - Cast \'Detonation\''), +(@ENTRY,0,5,0,9,0,100,3,0,8,0,0,41,0,0,0,0,0,0,1,0,0,0,0,0,0,0,'Dark Iron Land Mine - Within 0-8 Range - Despawn Instant'); diff --git a/sql/updates/world/3.3.5/2016_04_26_03_world.sql b/sql/updates/world/3.3.5/2016_04_26_03_world.sql new file mode 100644 index 00000000000..659006afcef --- /dev/null +++ b/sql/updates/world/3.3.5/2016_04_26_03_world.sql @@ -0,0 +1,99 @@ + +DELETE FROM creature WHERE `id` IN(24277,24516,24517); +INSERT INTO creature (`guid`, `id`, `map`, `zoneId`, `areaId`, `spawnMask`, `phaseMask`, `modelid`, `equipment_id`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `spawndist`, `currentwaypoint`, `curhealth`, `curmana`, `MovementType`, `npcflag`, `unit_flags`, `dynamicflags`, `VerifiedBuild`) VALUES +(45211, 24277, 571, 0, 0, 1, 1, 0, 0, 2578.047, -3028.564, 115.3411, 0, 120, 0, 0, 0, 0, 2, 0, 0, 0, 21463), -- 24277 (Area: 4054) (Auras: ) +(114439, 24516, 571, 0, 0, 1, 1, 0, 0, 2245.904, -3021.815, 135.1308, 1.318242, 120, 0, 0, 0, 0, 2, 0, 0, 0, 21463), -- 24516 (Area: 0) +(114637, 24517, 571, 0, 0, 1, 1, 0, 0, 1886.899, -3555.015, 147.7859, 2.676408, 120, 0, 0, 0, 0, 2, 0, 0, 0, 21463); -- 24517 (Area: 3999) (Auras: 52071 - 52071) + +DELETE FROM `waypoint_data` WHERE `id` IN(452110,1144390,1146370); + +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`, `move_type`, `action`, `action_chance`, `wpguid`) VALUES +(452110, 1, 2603.876, -3028.025, 117.0937, 0, 0, 0, 0, 100, 0), +(452110, 2, 2643.243, -3014.203, 104.8926, 0, 0, 0, 0, 100, 0), +(452110, 3, 2667.486, -3001.944, 99.91364, 0, 0, 0, 0, 100, 0), +(452110, 4, 2686.615, -2995.257, 94.60037, 0, 0, 0, 0, 100, 0), +(452110, 5, 2708.851, -2996.379, 92.56187, 0, 0, 0, 0, 100, 0), +(452110, 6, 2731.851, -2997.098, 91.55309, 0, 0, 0, 0, 100, 0), +(452110, 7, 2751.252, -3001.074, 89.84369, 0, 0, 0, 0, 100, 0), +(452110, 8, 2779.356, -3012.149, 91.26218, 0, 0, 0, 0, 100, 0), +(452110, 9, 2790.117, -3024.486, 94.64268, 0, 0, 0, 0, 100, 0), +(452110, 10, 2793.189, -3046.271, 97.1767, 0, 0, 0, 0, 100, 0), +(452110, 11, 2787.66, -3063.327, 99.79316, 0, 0, 0, 0, 100, 0), +(452110, 12, 2768.723, -3078.092, 104.6359, 0, 0, 0, 0, 100, 0), +(452110, 13, 2744.823, -3091.001, 111.5423, 0, 0, 0, 0, 100, 0), +(452110, 14, 2725.268, -3106.576, 111.8766, 0, 0, 0, 0, 100, 0), +(452110, 15, 2697.289, -3117.357, 110.0175, 0, 0, 0, 0, 100, 0), +(452110, 16, 2671.67, -3121.725, 118.3925, 0, 0, 0, 0, 100, 0), +(452110, 17, 2647.262, -3119.072, 123.8932, 0, 0, 0, 0, 100, 0), +(452110, 18, 2621.482, -3114.164, 127.1552, 0, 0, 0, 0, 100, 0), +(452110, 19, 2597.5, -3107.631, 127.1276, 0, 0, 0, 0, 100, 0), +(452110, 20, 2562.354, -3115.057, 123.5328, 0, 0, 0, 0, 100, 0), +(452110, 21, 2547.443, -3131.256, 128.2941, 0, 0, 0, 0, 100, 0), +(452110, 22, 2537.48, -3152.528, 130.5185, 0, 0, 0, 0, 100, 0), +(452110, 23, 2523.183, -3170.009, 137.3546, 0, 0, 0, 0, 100, 0), +(452110, 24, 2499.98, -3176.15, 146.2999, 0, 0, 0, 0, 100, 0), +(452110, 25, 2477.218, -3173.943, 146.8427, 0, 0, 0, 0, 100, 0), +(452110, 26, 2466.798, -3181.938, 148.4451, 0, 0, 0, 0, 100, 0), +(452110, 27, 2449.986, -3186.217, 148.8962, 0, 0, 0, 0, 100, 0), +(452110, 28, 2435.967, -3212.301, 150.5083, 0, 0, 0, 0, 100, 0), +(452110, 29, 2430.812, -3224.802, 150.1544, 0, 0, 0, 0, 100, 0), +(452110, 30, 2427.15, -3236.885, 149.6805, 0, 0, 0, 0, 100, 0), +(452110, 31, 2420.321, -3249.048, 148.5472, 0, 0, 0, 0, 100, 0), +(452110, 32, 2403.638, -3257.211, 150.8997, 0, 0, 0, 0, 100, 0), +(452110, 33, 2386.398, -3251.84, 150.9332, 0, 0, 0, 0, 100, 0), +(452110, 34, 2376.512, -3235.288, 151.3786, 0, 0, 0, 0, 100, 0), +(452110, 35, 2375.435, -3213.906, 154.4518, 0, 0, 0, 0, 100, 0), +(452110, 36, 2368.87, -3195.879, 154.6864, 0, 0, 0, 0, 100, 0), +(452110, 37, 2383.123, -3178.886, 155.935, 0, 0, 0, 0, 100, 0), +(452110, 38, 2398.307, -3176.602, 155.8448, 0, 0, 0, 0, 100, 0), +(452110, 39, 2412.706, -3183.355, 153.6713, 0, 0, 0, 0, 100, 0), +(452110, 40, 2436.154, -3172.414, 148.4366, 0, 0, 0, 0, 100, 0), +(452110, 41, 2439.1, -3152.812, 145.9067, 0, 0, 0, 0, 100, 0), +(452110, 42, 2423.416, -3137.387, 147.4658, 0, 0, 0, 0, 100, 0), +(452110, 43, 2420.221, -3122.801, 146.8984, 0, 0, 0, 0, 100, 0), +(452110, 44, 2432.173, -3109.894, 147.6966, 0, 0, 0, 0, 100, 0), +(452110, 45, 2443.513, -3098.615, 147.4875, 0, 0, 0, 0, 100, 0), +(452110, 46, 2458.256, -3078.243, 142.1544, 0, 0, 0, 0, 100, 0), +(452110, 47, 2475.883, -3064.164, 139.0425, 0, 0, 0, 0, 100, 0), +(452110, 48, 2507.794, -3040.304, 124.8166, 0, 0, 0, 0, 100, 0), +(452110, 49, 2531.649, -3026.078, 119.3878, 0, 0, 0, 0, 100, 0), +(452110, 50, 2560.749, -3028.565, 114.5343, 0, 0, 0, 0, 100, 0), +(452110, 51, 2582.748, -3028.564, 115.9288, 0, 0, 0, 0, 100, 0), +(1144390, 1, 2261.844 , -2975.589 , 137.7219, 0, 0, 0, 0, 100, 0), +(1144390, 2, 2288.57 , -2967.957 , 134.1304, 0, 0, 0, 0, 100, 0), +(1144390, 3, 2312.078 , -2973.851 , 131.6859, 0, 0, 0, 0, 100, 0), +(1144390, 4, 2327.24 , -2996.011 , 135.0435, 0, 0, 0, 0, 100, 0), +(1144390, 5, 2319.611 , -3020.818 , 136.6337, 0, 0, 0, 0, 100, 0), +(1144390, 6, 2293.551 , -3033.061 , 136.8072, 0, 0, 0, 0, 100, 0), +(1144390, 7, 2270.958 , -3049.189 , 136.8092, 0, 0, 0, 0, 100, 0), +(1144390, 8, 2261.982 , -3069.591 , 137.1458, 0, 0, 0, 0, 100, 0), +(1144390, 9, 2244.48 , -3111.4 , 136.8513, 0, 0, 0, 0, 100, 0), +(1144390, 10, 2234.337 , -3129.741 , 138.2859, 0, 0, 0, 0, 100, 0), +(1144390, 11, 2205.15 , -3149.454 , 140.4617, 0, 0, 0, 0, 100, 0), +(1144390, 12, 2178.708 , -3143.635 , 139.101, 0, 0, 0, 0, 100, 0), +(1144390, 13, 2159.131 , -3118.843 , 139.0326, 0, 0, 0, 0, 100, 0), +(1144390, 14, 2157.424 , -3090.945 , 138.6674, 0, 0, 0, 0, 100, 0), +(1144390, 15, 2184.693 , -3076.778 , 137.7539, 0, 0, 0, 0, 100, 0), +(1144390, 16, 2205.282 , -3067.448 , 138.6362, 0, 0, 0, 0, 100, 0), +(1144390, 17, 2241.108 , -3040.399 , 136.0237, 0, 0, 0, 0, 100, 0), +(1144390, 18, 2251.254 , -3001.044 , 135.3165, 0, 0, 0, 0, 100, 0), +(1146370, 1, 1851.814 , -3531.93 , 143.9488, 0, 0, 0, 0, 100, 0), +(1146370, 2, 1845.242 , -3513.312 , 143.5822, 0, 0, 0, 0, 100, 0), +(1146370, 3, 1850.21 , -3485.009 , 141.7585, 0, 0, 0, 0, 100, 0), +(1146370, 4, 1876.234 , -3453.859 , 139.5074, 0, 0, 0, 0, 100, 0), +(1146370, 5, 1914.745 , -3432.741 , 140.1635, 0, 0, 0, 0, 100, 0), +(1146370, 6, 1944.544 , -3444.092 , 139.0286, 0, 0, 0, 0, 100, 0), +(1146370, 7, 1957.72 , -3473.06 , 139.4977, 0, 0, 0, 0, 100, 0), +(1146370, 8, 1961.842 , -3512.568 , 142.8533, 0, 0, 0, 0, 100, 0), +(1146370, 9, 1954.096 , -3543.72 , 147.4886, 0, 0, 0, 0, 100, 0), +(1146370, 10, 1939.206 , -3558.753 , 147.6136, 0, 0, 0, 0, 100, 0), +(1146370, 11, 1923.051 , -3563.351 , 147.5182, 0, 0, 0, 0, 100, 0), +(1146370, 12, 1899.894 , -3561.537 , 147.5989, 0, 0, 0, 0, 100, 0), +(1146370, 13, 1876.972 , -3550.032 , 147.9288, 0, 0, 0, 0, 100, 0); + +DELETE FROM `creature_template_addon` WHERE `entry` IN(24516,24517); +INSERT INTO `creature_template_addon` (`entry`, `path_id`, `mount`, `bytes1`, `bytes2`, `emote`, `auras`) VALUES +(24516, 1144390, 0, 0, 4097, 0, NULL), +(24517, 1146370, 0, 0, 4097, 0, NULL); + + diff --git a/sql/updates/world/3.3.5/2016_04_28_00_world.sql b/sql/updates/world/3.3.5/2016_04_28_00_world.sql new file mode 100644 index 00000000000..377f019f899 --- /dev/null +++ b/sql/updates/world/3.3.5/2016_04_28_00_world.sql @@ -0,0 +1,3 @@ +-- +UPDATE `creature_template` SET `ScriptName`="" WHERE `entry`=28033; +UPDATE `creature_template` SET `ScriptName`="npc_the_etymidian" WHERE `entry`=28092; diff --git a/sql/updates/world/3.3.5/2016_04_29_00_world.sql b/sql/updates/world/3.3.5/2016_04_29_00_world.sql new file mode 100644 index 00000000000..14c700c0795 --- /dev/null +++ b/sql/updates/world/3.3.5/2016_04_29_00_world.sql @@ -0,0 +1,55 @@ +-- +UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry`=29796; +DELETE FROM `smart_scripts` WHERE `entryorguid`=29796 AND `source_type` = 0; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(29796,0,0,0,19,0,100,0,12886,0,0,0,85,55253,0,0,0,0,0,7,0,0,0,0,0,0,0,'Gretta the Arbiter - On quest accept - cast Spell'); + +DELETE FROM `smart_scripts` WHERE `entryorguid`=29694 AND `source_type` = 0; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(29694, 0, 0, 0, 0, 0, 100, 0, 2000, 5000, 10000, 15000, 11, 32736, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, "Hyldsmeet Drakerider - In Combat - Cast 'Mortal Strike'"), +(29694, 0, 1, 0, 6, 0, 100, 0, 0, 0, 0, 0, 33, 29800, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, "Hyldsmeet Drakerider - On Death - Kill credit Spell"); + +UPDATE `creature_template` SET `AIName`='SmartAI', `InhabitType`=4, `speed_run`=3.2 WHERE `entry` IN (29679); +DELETE FROM `smart_scripts` WHERE `entryorguid`=29679 AND `source_type` = 0; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(29679, 0, 0, 0, 27, 0, 100, 0, 0, 0, 0, 0, 53, 1, 29679, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Hyldsmeet Proto-Drake - ON PASSENGER_BOARDED - Start waypoint'); + +DELETE FROM `creature_template_addon` WHERE `entry`=29679; +INSERT INTO `creature_template_addon` (`entry`, `path_id`, `mount`, `bytes1`, `bytes2`, `emote`, `auras`) VALUES +(29679, 0, 0, 33554432, 0, 0, '55971'); + +DELETE FROM `waypoints` WHERE `entry`=29679; +INSERT INTO `waypoints` (`entry`,`pointid`,`position_x`,`position_y`,`position_z`,`point_comment`) VALUES +(29679,1,6985.165039, -1662.842163, 868.941956, 'Hyldsmeet Proto-Drake'), +(29679,2,6935.585449, -1516.853760, 968.493896, 'Hyldsmeet Proto-Drake'), +(29679,3,6926.762207, -1282.424927, 1127.864380, 'Hyldsmeet Proto-Drake'), +(29679,4,7365.684082, -644.429688, 1928.750610, 'Hyldsmeet Proto-Drake'), +(29679,5,7388.145508, -652.783569, 1909.863647, 'Hyldsmeet Proto-Drake'), +(29679,6,7439.698730, -661.380981, 1887.756714, 'Hyldsmeet Proto-Drake'), +(29679,7,7494.946777, -650.403015, 1883.039795, 'Hyldsmeet Proto-Drake'), +(29679,8,7548.416992, -601.006348, 1882.505737, 'Hyldsmeet Proto-Drake'), +(29679,9,7575.110352, -541.134949, 1881.668701, 'Hyldsmeet Proto-Drake'), +(29679,10,7550.558594, -458.574036, 1877.870972, 'Hyldsmeet Proto-Drake'), +(29679,11,7482.576172, -404.054077, 1878.095581, 'Hyldsmeet Proto-Drake'), +(29679,12,7390.999023, -404.312683, 1882.240234, 'Hyldsmeet Proto-Drake'), +(29679,13,7324.988770, -455.605713, 1874.051270, 'Hyldsmeet Proto-Drake'), +(29679,14,7289.477051, -552.180786, 1879.989258, 'Hyldsmeet Proto-Drake'), +(29679,15,7332.199707, -623.493713, 1887.427734, 'Hyldsmeet Proto-Drake'), +(29679,16,7367.857910, -647.534546, 1895.689453, 'Hyldsmeet Proto-Drake'), +(29679,17,7388.145508, -652.783569, 1909.863647, 'Hyldsmeet Proto-Drake'), +(29679,18,7439.698730, -661.380981, 1887.756714, 'Hyldsmeet Proto-Drake'), +(29679,19,7494.946777, -650.403015, 1883.039795, 'Hyldsmeet Proto-Drake'), +(29679,20,7548.416992, -601.006348, 1882.505737, 'Hyldsmeet Proto-Drake'), +(29679,21,7575.110352, -541.134949, 1881.668701, 'Hyldsmeet Proto-Drake'), +(29679,22,7550.558594, -458.574036, 1877.870972, 'Hyldsmeet Proto-Drake'), +(29679,23,7482.576172, -404.054077, 1878.095581, 'Hyldsmeet Proto-Drake'), +(29679,24,7390.999023, -404.312683, 1882.240234, 'Hyldsmeet Proto-Drake'), +(29679,25,7324.988770, -455.605713, 1874.051270, 'Hyldsmeet Proto-Drake'), +(29679,26,7289.477051, -552.180786, 1879.989258, 'Hyldsmeet Proto-Drake'), +(29679,27,7332.199707, -623.493713, 1887.427734, 'Hyldsmeet Proto-Drake'), +(29679,28,6926.762207, -1282.424927, 1127.864380, 'Hyldsmeet Proto-Drake'), +(29679,29,6935.585449, -1516.853760, 968.493896, 'Hyldsmeet Proto-Drake'), +(29679,30,6985.165039, -1662.842163, 868.941956, 'Hyldsmeet Proto-Drake'), +(29679,31,6998.042969, -1664.234253, 867.953247, 'Hyldsmeet Proto-Drake'), +(29679,32,7037.400879, -1725.409302, 838.695618, 'Hyldsmeet Proto-Drake'), +(29679,33,7076.637695, -1770.263184, 825.775391, 'Hyldsmeet Proto-Drake'); diff --git a/sql/updates/world/3.3.5/2016_04_29_01_world.sql b/sql/updates/world/3.3.5/2016_04_29_01_world.sql new file mode 100644 index 00000000000..c5b0311e1bc --- /dev/null +++ b/sql/updates/world/3.3.5/2016_04_29_01_world.sql @@ -0,0 +1,5 @@ +DELETE FROM `vehicle_template_accessory` WHERE `entry`=29460; +INSERT INTO `vehicle_template_accessory` (`entry`, `accessory_entry`, `seat_id`, `minion`, `description`, `summontype`, `summontimer`) VALUES +(29460, 29458, 0, 1, "Brunnhildar Drakerider", 8, 0); + +UPDATE `npc_spellclick_spells` SET `spell_id`=46598 WHERE `npc_entry`=29460; diff --git a/sql/updates/world/3.3.5/2016_05_01_00_world.sql b/sql/updates/world/3.3.5/2016_05_01_00_world.sql new file mode 100644 index 00000000000..5a4d6c3197e --- /dev/null +++ b/sql/updates/world/3.3.5/2016_05_01_00_world.sql @@ -0,0 +1 @@ +DELETE FROM `trinity_string` WHERE `entry`=5007; diff --git a/sql/updates/world/3.3.5/2016_05_01_01_world.sql b/sql/updates/world/3.3.5/2016_05_01_01_world.sql new file mode 100644 index 00000000000..30096e55335 --- /dev/null +++ b/sql/updates/world/3.3.5/2016_05_01_01_world.sql @@ -0,0 +1,68 @@ +DELETE FROM `waypoints` WHERE `entry`=28308; +INSERT INTO `waypoints` (`entry`, `pointid`, `position_x`, `position_y`, `position_z`, `point_comment`) VALUES +(28308, 1, 5268.226 ,4425.439 ,-95.55899, 'Captive Crocolisk'), +(28308, 2, 5249.557 ,4405.892 ,-96.04365, 'Captive Crocolisk'), +(28308, 3, 5266.678 ,4365.464 ,-98.19455, 'Captive Crocolisk'), +(28308, 4, 5289.138 ,4366.553 ,-102.234, 'Captive Crocolisk'), +(28308, 5, 5330.018 ,4363.27 ,-121.0311, 'Captive Crocolisk'), +(28308, 6, 5349.229 ,4341.059 ,-134.0126, 'Captive Crocolisk'), +(28308, 7, 5365.038 ,4333.716 ,-141.5817, 'Captive Crocolisk'), +(28308, 8, 5405.443 ,4307.841 ,-142.03, 'Captive Crocolisk'), +(28308, 9, 5434.999 ,4305.659 ,-136.4706, 'Captive Crocolisk'), +(28308, 10, 5464.708 ,4302.066 ,-133.1981, 'Captive Crocolisk'), +(28308, 11, 5490.555 ,4294.395 ,-127.5203, 'Captive Crocolisk'), +(28308, 12, 5503.808 ,4269.717 ,-110.3168, 'Captive Crocolisk'), +(28308, 13, 5518.324 ,4255.308 ,-103.0638, 'Captive Crocolisk'), +(28308, 14, 5540.53 ,4259.77 ,-102.3979, 'Captive Crocolisk'), +(28308, 15, 5564.194 ,4263.45 ,-102.7574, 'Captive Crocolisk'), +(28308, 16, 5585.45 ,4261.137 ,-99.54807, 'Captive Crocolisk'), +(28308, 17, 5609.614 ,4259.657 ,-98.87333, 'Captive Crocolisk'), +(28308, 18, 5633.434 ,4259.228 ,-98.53442, 'Captive Crocolisk'), +(28308, 19, 5660.568 ,4260.985 ,-98.63537, 'Captive Crocolisk'), +(28308, 20, 5681.639 ,4266.31 ,-99.26748, 'Captive Crocolisk'), +(28308, 21, 5708.126 ,4273.348 ,-102.9183, 'Captive Crocolisk'), +(28308, 22, 5748.732 ,4284.135 ,-112.0557, 'Captive Crocolisk'), +(28308, 23, 5839.82 ,4368.61 ,-112.0805, 'Captive Crocolisk'), +(28308, 24, 5897.276 ,4408.44 ,-95.25065, 'Captive Crocolisk'), +(28308, 25, 5925.311 ,4440.624 ,-94.77592, 'Captive Crocolisk'), +(28308, 26, 5953.005 ,4476.29 ,-94.3763, 'Captive Crocolisk'), +(28308, 27, 5964.229 ,4503.729 ,-92.81553, 'Captive Crocolisk'), +(28308, 28, 5960.583 ,4546.558 ,-95.65462, 'Captive Crocolisk'), +(28308, 29, 5965.167 ,4579.141 ,-97.39779, 'Captive Crocolisk'), +(28308, 30, 5969.295 ,4613.739 ,-98.05751, 'Captive Crocolisk'), +(28308, 31, 5975.809 ,4659.289 ,-99.27143, 'Captive Crocolisk'), +(28308, 32, 5992.961 ,4699.554 ,-99.30317, 'Captive Crocolisk'), +(28308, 33, 6015.139 ,4743.752 ,-97.52377, 'Captive Crocolisk'), +(28308, 34, 6035.183 ,4788.787 ,-94.66938, 'Captive Crocolisk'), +(28308, 35, 6064.951 ,4827.502 ,-94.54885, 'Captive Crocolisk'), +(28308, 36, 6065.57 ,4870.553 ,-94.47726, 'Captive Crocolisk'), +(28308, 37, 6096.612 ,4885.741 ,-94.44479, 'Captive Crocolisk'), +(28308, 38, 6120.387 ,4902.048 ,-95.06882, 'Captive Crocolisk'), +(28308, 39, 6139.616 ,4913.349 ,-94.8635, 'Captive Crocolisk'), +(28308, 40, 6141.208, 4914.293, -92.7175, 'Captive Crocolisk'); + +UPDATE `creature_template` SET `AIName`='SmartAI', `InhabitType`=4 WHERE `entry`=28307; +UPDATE `smart_scripts` SET `link`=1 WHERE `entryorguid`=28298 AND `source_type`=0 AND `id`=0 AND `link`=0; + +DELETE FROM `smart_scripts` WHERE `entryorguid`IN(28307,28308) AND `source_type`=0; +DELETE FROM `smart_scripts` WHERE `entryorguid`IN(28216) AND `source_type`=0 AND `id`>17; +DELETE FROM `smart_scripts` WHERE `entryorguid`IN(28298) AND `source_type`=0 AND `id`=1; + +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(28216, 0, 18, 19, 38, 0, 100, 0, 1, 3, 0, 0, 1, 6, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Zepik the Gorloc Hunter - On Data Set 1 3 - Say Line 6'), +(28216, 0, 19, 0, 61, 0, 100, 0, 0, 0, 0, 0, 41, 3000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Zepik the Gorloc Hunter - On Data Set 1 3 - Despawn'), +(28298, 0, 1, 0, 61, 0, 100, 0, 0, 0, 0, 0, 45, 1, 3, 0, 0, 0, 0, 19, 28216, 0, 0, 0, 0, 0, 0, 'Captive Crocolisk - On Gossip Option 0 Selected - Set Data on Zepik'), +(28307, 0, 0, 0, 1, 0, 100, 0, 0, 0, 3000, 3000, 11, 51256, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Croclisk Chain Bunny - OOC - Cast Captive Crocolisk Chains'), +(28308, 0, 0, 0, 54, 0, 100, 0, 0, 0, 0, 0, 80, 2830800, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Captive Crocolisk - On Just Summoned - Run Script (Phase 1) (No Repeat)'), +(28308, 0, 1, 2, 40, 0, 100, 0, 39, 0, 0, 0, 11, 50630, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Captive Crocolisk - On reached WP42 - Cast Eject All Passengers'), +(28308, 0, 2, 3, 61, 0, 100, 0, 0, 0, 0, 0, 15, 12536, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'Captive Crocolisk - On reached WP42 - Quest Credit \'A Rough Ride\''), +(28308, 0, 3, 0, 61, 0, 100, 0, 0, 0, 0, 0, 85, 52545, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'Captive Crocolisk - On reached WP42 - Cast Forceitem Zepik'), +(28308, 0, 4, 0, 40, 0, 100, 0, 40, 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Captive Crocolisk - On reached WP43 - Despawn'); + +DELETE FROM `creature_text` WHERE `entry`=28216 AND `groupid`=6; +INSERT INTO `creature_text` (`entry`, `groupid`, `id`, `text`, `type`, `language`, `probability`, `emote`, `duration`, `sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES +(28216, 6, 0, 'Enjoy ride! Call me when you get there.', 12, 0, 100, 0, 0, 0, 28881, 0, 'Zepik'); + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry`=51256; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES +(13, 1, 51256, 0, 0, 31, 0, 3, 28298, 0, 0, 0, 0, '', 'Captive Crocolisk Chains targets captive crocolisk'); diff --git a/sql/updates/world/3.3.5/2016_05_02_00_world.sql b/sql/updates/world/3.3.5/2016_05_02_00_world.sql new file mode 100644 index 00000000000..2063baf1ad7 --- /dev/null +++ b/sql/updates/world/3.3.5/2016_05_02_00_world.sql @@ -0,0 +1,14 @@ +UPDATE `smart_scripts` SET `link`=5 WHERE `entryorguid`=28082 AND `source_type`=0 AND `id` IN(0,1) AND `link`=0; +UPDATE `smart_scripts` SET `link`=6 WHERE `entryorguid`=28082 AND `source_type`=0 AND `id` IN(2,3) AND `link`=0; +UPDATE `smart_scripts` SET `link`=7 WHERE `entryorguid`=28082 AND `source_type`=0 AND `id` IN(4) AND `link`=0; + +DELETE FROM `smart_scripts` WHERE `entryorguid`=28082 AND `source_type`=0 AND `id` IN(5,6,7); +DELETE FROM `smart_scripts` WHERE `entryorguid`=28027 AND `source_type`=0 AND `id` IN(9,10,11); + +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(28082, 0, 5, 0, 61, 0, 100, 0, 0, 0, 0, 0, 85, 51186, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'High-Shaman Rakjak - Link - Cast Summon Goregek the Bristlepine Hunter'), +(28082, 0, 6, 0, 61, 0, 100, 0, 0, 0, 0, 0, 85, 51188, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'High-Shaman Rakjak - Link - Cast Summon Dajik the Wasp Hunter'), +(28082, 0, 7, 0, 61, 0, 100, 0, 0, 0, 0, 0, 85, 51189, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'High-Shaman Rakjak - Link - Cast Summon Zepik the Gorloc Hunter'), +(28027, 0, 9, 0, 19, 0, 100, 0, 12571, 0, 0, 0, 85, 51190, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'High-Oracle Soo-say - On Quest Accept - Cast Summon Lafoo'), +(28027, 0, 10, 0, 19, 0, 100, 0, 12574, 0, 0, 0, 85, 51191, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'High-Oracle Soo-say - On Quest Accept - Cast Summon Jaloot'), +(28027, 0, 11, 0, 19, 0, 100, 0, 12578, 0, 0, 0, 85, 51192, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'High-Oracle Soo-say - On Quest Accept - Cast Summon Moodle'); diff --git a/sql/updates/world/3.3.5/2016_05_02_01_world.sql b/sql/updates/world/3.3.5/2016_05_02_01_world.sql new file mode 100644 index 00000000000..1671abee38f --- /dev/null +++ b/sql/updates/world/3.3.5/2016_05_02_01_world.sql @@ -0,0 +1,18 @@ +-- Beaten Corpse (Mankrik's wife) in quest 4921 "Lost in Battle": +UPDATE `creature_template` SET `gossip_menu_id`= 2871 WHERE `entry`= 10668; + +-- new gossip_menu.entry for creature 10668 (Beaten Corpse): +DELETE FROM `gossip_menu` WHERE `entry` IN (2871,2872) AND `text_id` IN (3557,3558); +INSERT INTO `gossip_menu` (`entry`,`text_id`) VALUES +(2871, 3557), +(2872, 3558); + +-- new gossip_menu_option for creature 10668 (Beaten Corpse): +DELETE FROM `gossip_menu_option` WHERE `menu_id`= 2871 AND `OptionBroadcastTextID`= 5964; +INSERT INTO `gossip_menu_option` (`menu_id`,`id`,`option_icon`,`option_text`,`OptionBroadcastTextID`,`option_id`,`npc_option_npcflag`,`action_menu_id`,`action_poi_id`,`box_coded`,`box_money`,`box_text`,`BoxBroadcastTextID`) VALUES +(2871, 0, 0, 'I inspect the body further.', 5964, 1, 1, 2872, 0, 0, 0, '', 0); + +-- condition for gossip_menu_option 2871 in Quest ID 4921 "Lost in Battle": +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`= 15 AND `SourceGroup`= 2871; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`SourceId`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionTarget`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorType`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES +(15, 2871,0, 0,0, 9,0, 4921, 0,0,0,0,0, '', 'Show gossip menu option 2871 only if Quest 4921 is taken (active)'); diff --git a/sql/updates/world/3.3.5/2016_05_04_00_world.sql b/sql/updates/world/3.3.5/2016_05_04_00_world.sql new file mode 100644 index 00000000000..e4043768774 --- /dev/null +++ b/sql/updates/world/3.3.5/2016_05_04_00_world.sql @@ -0,0 +1 @@ +DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=70157 AND `spell_effect`=69700 AND `type`=2; diff --git a/sql/updates/world/3.3.5/2016_05_04_01_world.sql b/sql/updates/world/3.3.5/2016_05_04_01_world.sql new file mode 100644 index 00000000000..8a40bd66b2a --- /dev/null +++ b/sql/updates/world/3.3.5/2016_05_04_01_world.sql @@ -0,0 +1,69 @@ +SET @CGUID := 84723; + +UPDATE `creature_template` SET `InhabitType`=4 WHERE `entry`in(29066); + +DELETE FROM creature WHERE `id` IN(28069,28840); +INSERT INTO creature (`guid`, `id`, `map`, `zoneId`, `areaId`, `spawnMask`, `phaseMask`, `modelid`, `equipment_id`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `spawndist`, `currentwaypoint`, `curhealth`, `curmana`, `MovementType`, `npcflag`, `unit_flags`, `dynamicflags`, `VerifiedBuild`) VALUES +(@CGUID+0, 28069, 571, 0, 0, 1, 1, 0, 0, 5734.697, 3308.838, 299.8264, 1.867502, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 28069 (Area: 0) +(@CGUID+1, 28069, 571, 0, 0, 1, 1, 0, 0, 5728.474, 3438.191, 300.8422, 0.1060605, 120, 0, 0, 0, 0, 2, 0, 0, 0, 21463), -- 28069 (Area: 0) +(@CGUID+2, 28069, 571, 0, 0, 1, 1, 0, 0, 5717.042, 3428.265, 300.9259, 1.797689, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 28069 (Area: 0) +(@CGUID+3, 28069, 571, 0, 0, 1, 1, 0, 0, 5697.737, 3426.803, 300.9259, 1.570796, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 28069 (Area: 0) +(@CGUID+4, 28069, 571, 0, 0, 1, 1, 0, 0, 5738.866, 3156.665, 293.8326, 4.814398, 120, 0, 0, 0, 0, 2, 0, 0, 0, 21463), -- 28069 (Area: -1) (Auras: ) +(@CGUID+5, 28069, 571, 0, 0, 1, 1, 0, 0, 5706.989, 3306.817, 299.718, 1.518436, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 28069 (Area: 4412) +(@CGUID+6, 28840, 571, 0, 0, 1, 1, 0, 0, 5737.756, 3273.594, 299.117, 2.794445, 120, 0, 0, 0, 0, 2, 0, 0, 0, 21463), -- 28840 (Area: 4412) (Auras: 55030 - 55030) +(@CGUID+7, 28069, 571, 0, 0, 1, 1, 0, 0, 5752.529, 3141.505, 294.1674, 3.351032, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 28069 (Area: 4412) +(@CGUID+8, 28069, 571, 0, 0, 1, 1, 0, 0, 5728.323, 3137.707, 294.1627, 0.715585, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 28069 (Area: 4412) +(@CGUID+9, 28069, 571, 0, 0, 1, 1, 0, 0, 5737.385, 3051.348, 288.0696, 1.239184, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 28069 (Area: -1) +(@CGUID+10, 28069, 571, 0, 0, 1, 1, 0, 0, 5781.281, 3081.078, 288.0696, 3.089233, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 28069 (Area: 4412) +(@CGUID+11, 28069, 571, 0, 0, 1, 1, 0, 0, 5717.863, 3074.304, 288.0696, 0.4014257, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 28069 (Area: 4412) +(@CGUID+12, 28069, 571, 0, 0, 1, 1, 0, 0, 5767.666, 3052.907, 288.0696, 2.181662, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 28069 (Area: 4412) +(@CGUID+13, 28069, 571, 0, 0, 1, 1, 0, 0, 5704.075, 3429.402, 300.8421, 1.239184, 120, 0, 0, 0, 0, 2, 0, 0, 0, 21463); -- 28069 (Area: 4412) + +DELETE FROM `waypoint_data` WHERE `id` =(@CGUID*10)+1; +DELETE FROM `waypoint_data` WHERE `id` =(@CGUID*10)+4; +DELETE FROM `waypoint_data` WHERE `id` =(@CGUID*10)+6; +DELETE FROM `waypoint_data` WHERE `id` =(@CGUID*10)+13; + + +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`, `move_type`, `action`, `action_chance`, `wpguid`) VALUES +((@CGUID*10)+6, 1, 5712.777, 3273.745, 299.1278, 0, 0, 0, 0, 100, 0), +((@CGUID*10)+6, 2, 5705.582, 3264.395, 299.1169, 0, 0, 0, 0, 100, 0), +((@CGUID*10)+6, 3, 5704.035, 3252.411, 299.1169, 0, 0, 0, 0, 100, 0), +((@CGUID*10)+6, 4, 5711.498, 3241.038, 299.117, 0, 0, 0, 0, 100, 0), +((@CGUID*10)+6, 5, 5725.473, 3233.009, 299.1144, 0, 0, 0, 0, 100, 0), +((@CGUID*10)+6, 6, 5738.392, 3238.95, 299.1152, 0, 0, 0, 0, 100, 0), +((@CGUID*10)+6, 7, 5744.125, 3248.184, 299.1169, 0, 0, 0, 0, 100, 0), +((@CGUID*10)+6, 8, 5747.937, 3262.18, 299.1169, 0, 0, 0, 0, 100, 0), +((@CGUID*10)+6, 9, 5737.756, 3273.594, 299.117, 0, 0, 0, 0, 100, 0), +((@CGUID*10)+6, 10, 5723.768, 3278.654, 299.138, 0, 0, 0, 0, 100, 0), +((@CGUID*10)+4, 1, 5737.638, 3168.66, 293.8326, 0, 0, 0, 0, 100, 0), +((@CGUID*10)+4, 2, 5734.833, 3190.47, 294.0836, 0, 0, 0, 0, 100, 0), +((@CGUID*10)+4, 3, 5733.381, 3205.572, 295.6976, 0, 0, 0, 0, 100, 0), +((@CGUID*10)+4, 4, 5734.833, 3190.47, 294.0836, 0, 0, 0, 0, 100, 0), +((@CGUID*10)+4, 5, 5737.638, 3168.66, 293.8326, 0, 0, 0, 0, 100, 0), +((@CGUID*10)+4, 6, 5739.323, 3152.199, 293.8326, 0, 0, 0, 0, 100, 0), +((@CGUID*10)+4, 7, 5742.777, 3128.636, 294.0135, 0, 0, 0, 0, 100, 0), +((@CGUID*10)+4, 8, 5744.988, 3100.412, 287.9503, 0, 0, 0, 0, 100, 0), +((@CGUID*10)+4, 9, 5746.909, 3085.88, 287.758, 0, 0, 0, 0, 100, 0), +((@CGUID*10)+4, 10, 5744.988, 3100.412, 287.9503, 0, 0, 0, 0, 100, 0), +((@CGUID*10)+4, 11, 5742.777, 3128.636, 294.0135, 0, 0, 0, 0, 100, 0), +((@CGUID*10)+4, 12, 5739.323, 3152.199, 293.8326, 0, 0, 0, 0, 100, 0), +((@CGUID*10)+1, 1, 5754.452, 3440.957, 300.8421, 0, 0, 0, 0, 100, 0), +((@CGUID*10)+1, 2, 5721.435, 3437.441, 300.8421, 0, 0, 0, 0, 100, 0), +((@CGUID*10)+1, 3, 5690.508, 3433.794, 300.8422, 0, 0, 0, 0, 100, 0), +((@CGUID*10)+1, 4, 5655.392, 3430.241, 300.8421, 0, 0, 0, 0, 100, 0), +((@CGUID*10)+1, 5, 5690.508, 3433.794, 300.8422, 0, 0, 0, 0, 100, 0), +((@CGUID*10)+1, 6, 5721.435, 3437.441, 300.8421, 0, 0, 0, 0, 100, 0), +((@CGUID*10)+13, 1, 5709.812, 3394.623, 300.8422, 0, 0, 0, 0, 100, 0), +((@CGUID*10)+13, 2, 5713.209, 3367.164, 300.2528, 0, 0, 0, 0, 100, 0), +((@CGUID*10)+13, 3, 5715.425, 3346.877, 300.0398, 0, 0, 0, 0, 100, 0), +((@CGUID*10)+13, 4, 5718.081, 3324.582, 299.8054, 0, 0, 0, 0, 100, 0), +((@CGUID*10)+13, 5, 5715.425, 3346.877, 300.0398, 0, 0, 0, 0, 100, 0), +((@CGUID*10)+13, 6, 5713.209, 3367.164, 300.2528, 0, 0, 0, 0, 100, 0); + +DELETE FROM `creature_addon` WHERE `guid` IN(@CGUID+1,@CGUID+4,@CGUID+6,@CGUID+13); +INSERT INTO `creature_addon` (`guid`, `path_id`, `mount`, `bytes1`, `bytes2`, `emote`, `auras`) VALUES +(@CGUID+1, (@CGUID*10)+1, 0, 0, 4097, 0, NULL), +(@CGUID+4, (@CGUID*10)+4, 0, 0, 4097, 0, NULL), +(@CGUID+6, (@CGUID*10)+6, 0, 0, 4097, 0, NULL), +(@CGUID+13, (@CGUID*10)+13, 0, 0, 4097, 0, NULL); diff --git a/sql/updates/world/3.3.5/2016_05_04_02_world.sql b/sql/updates/world/3.3.5/2016_05_04_02_world.sql new file mode 100644 index 00000000000..4bb7870a4ea --- /dev/null +++ b/sql/updates/world/3.3.5/2016_05_04_02_world.sql @@ -0,0 +1,2 @@ +UPDATE `quest_template_addon` SET `RewardMailTemplateID`=184, `RewardMailDelay`=900 WHERE `ID`=10966; +UPDATE `quest_template_addon` SET `RewardMailTemplateID`=185, `RewardMailDelay`=900 WHERE `ID`=10967; diff --git a/sql/updates/world/3.3.5/2016_05_05_00_world.sql b/sql/updates/world/3.3.5/2016_05_05_00_world.sql new file mode 100644 index 00000000000..ba99f5df1a6 --- /dev/null +++ b/sql/updates/world/3.3.5/2016_05_05_00_world.sql @@ -0,0 +1,13 @@ +DELETE FROM `smart_scripts` WHERE `entryorguid`=27292 AND `source_type`=0; +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(27292, 0, 0, 1, 62, 0, 100, 0, 9512, 0, 0, 0, 11, 48606, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'Flamebringer - On gossip select - Cast Summon Flamebringer Cue'), +(27292, 0, 1, 0, 61, 0, 100, 0, 0, 0, 0, 0, 72, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'Flamebringer - On gossip select - Close gossip'), +(27292, 0, 2, 3, 54, 0, 100, 0, 0, 0, 0, 0, 83, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Flamebringer - On summon - Remove npcflag'), +(27292, 0, 3, 4, 61, 0, 100, 0, 0, 0, 0, 0, 11, 48598, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'Flamebringer - On Just Summoned -Cast Ride Flamebringer Cue'), +(27292, 0, 4, 0, 61, 0, 100, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Flamebringer - Linked with previous Event -Set Passive'), +(27292, 0, 5, 6, 27, 0, 100, 0, 0, 0, 0, 0, 11, 48602, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Flamebringer - On passenger Boarded - Cast Flight'), +(27292, 0, 6, 0, 61, 0, 100, 0, 0, 0, 0, 0, 19, 768, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Flamebringer - On passenger Boarded - Enable Combat'), +(27292, 0, 7, 8, 28, 0, 100, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Flamebringer - On passenger removed - Evade'), +(27292, 0, 8, 0, 61, 0, 100, 0, 0, 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Flamebringer - On passenger removed - Despawn'); + +UPDATE `creature_template_addon` SET `auras`='' WHERE `entry`=27292; diff --git a/sql/updates/world/3.3.5/2016_05_05_01_world.sql b/sql/updates/world/3.3.5/2016_05_05_01_world.sql new file mode 100644 index 00000000000..d1e0ebcadb0 --- /dev/null +++ b/sql/updates/world/3.3.5/2016_05_05_01_world.sql @@ -0,0 +1,71 @@ +SET @CGUID := 10998; + +DELETE FROM creature WHERE `guid` IN(@CGUID,@CGUID+1); +INSERT INTO creature (`guid`, `id`, `map`, `zoneId`, `areaId`, `spawnMask`, `phaseMask`, `modelid`, `equipment_id`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `spawndist`, `currentwaypoint`, `curhealth`, `curmana`, `MovementType`, `npcflag`, `unit_flags`, `dynamicflags`, `VerifiedBuild`) VALUES +(@CGUID+0, 28139, 571, 0, 0, 1, 1, 0, 0, 5268.422, 4522.266, -83.79454, 4.956735, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 28069 (Area: 0) +(@CGUID+1, 28139, 571, 0, 0, 1, 1, 0, 0, 5257.281, 4501.662, -85.16033, 0.296706, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463); -- 28069 (Area: 0) + +UPDATE `creature_template` SET `ainame`='SmartAI', `scriptname`='' WHERE `entry` IN(29043,28139,29116); +DELETE FROM `smart_scripts` WHERE `entryorguid` IN(29043,28139,29116) AND `source_type`=0; +DELETE FROM `smart_scripts` WHERE `entryorguid` IN(-@CGUID,-@CGUID-1) AND `source_type`=0; + +DELETE FROM `smart_scripts` WHERE `entryorguid` =2904300 AND `source_type`=9; + +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(29043, 0, 0, 0, 11, 0, 100, 0, 0, 0, 0, 0, 22, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Rejek - On Spawn - Set Phase 1'), +(29043, 0, 1, 0, 20, 1, 100, 0, 12758, 0, 0, 0, 80, 2904300, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Rejek - On Quest Reward 12758 (Phase 1) - Run Script'), +(29116, 0, 0, 0, 54, 0, 100, 0, 0, 0, 0, 0, 11, 53170, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Stormwatcher Head - On Just Summoned - Cast Ride Rejek'), +(29116, 0, 1, 0, 38, 0, 100, 0, 1, 1, 0, 0, 28, 53170, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Stormwatcher Head - On Data Set - Remove Aura Ride Rejek'), +(-@CGUID-0, 0, 0, 1, 38, 0, 100, 0, 1, 1, 0, 0, 47, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Frenzyheart Pup - On Data set - Set Visible'), +(-@CGUID-1, 0, 0, 1, 38, 0, 100, 0, 1, 1, 0, 0, 47, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Frenzyheart Pup - On Data set - Set Visible'), +(-@CGUID-0, 0, 1, 0, 61, 0, 100, 0, 1, 1, 0, 0, 53, 1, (@CGUID*10)+0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Frenzyheart Pup - On Data set - start WP'), +(-@CGUID-1, 0, 1, 0, 61, 0, 100, 0, 1, 1, 0, 0, 53, 1, (@CGUID*10)+1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Frenzyheart Pup - On Data set - start WP'), +(-@CGUID-0, 0, 3, 0, 40, 0, 100, 0, 2, (@CGUID*10)+0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Frenzyheart Pup - On Reached WP - Set Invisible'), +(-@CGUID-1, 0, 3, 0, 40, 0, 100, 0, 2, (@CGUID*10)+1, 0, 0, 47, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Frenzyheart Pup - On Reached WP - Set Invisible'), +(-@CGUID-0, 0, 3, 4, 40, 0, 100, 0, 1, (@CGUID*10)+0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 5.585053, 'Frenzyheart Pup - On Reached WP - Set Orientation'), +(-@CGUID-1, 0, 3, 4, 40, 0, 100, 0, 1, (@CGUID*10)+1, 0, 0, 66, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 5.986479, 'Frenzyheart Pup - On Reached WP - Set Orientation'), +(-@CGUID-0, 0, 4, 6, 61, 0, 100, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Frenzyheart Pup - On Reached WP - Say'), +(-@CGUID-1, 0, 4, 6, 61, 0, 100, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Frenzyheart Pup - On Reached WP - Say'), +(-@CGUID-0, 0, 5, 0, 38, 0, 100, 0, 3, 3, 0, 0, 11, 42963, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Frenzyheart Pup - On Data set - Cast Cosmetic - Combat Knockdown Self'), +(-@CGUID-1, 0, 5, 0, 38, 0, 100, 0, 3, 3, 0, 0, 11, 42963, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Frenzyheart Pup - On Data set - Cast Cosmetic - Combat Knockdown Self'), +(-@CGUID-0, 0, 6, 0, 61, 0, 100, 0, 0, 0, 0, 0, 54, 22500, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Frenzyheart Pup - On Reached WP - Pause WP'), +(-@CGUID-1, 0, 6, 0, 61, 0, 100, 0, 0, 0, 0, 0, 54, 22500, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Frenzyheart Pup - On Reached WP - Pause WP'), +(-@CGUID-0, 0, 7, 0, 11, 0, 100, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Frenzyheart Pup - On Spawn - Set Invisible'), +(-@CGUID-1, 0, 7, 0, 11, 0, 100, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Frenzyheart Pup - On Spawn - Set Invisible'), +(2904300, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 22, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Rejek - Script - Set Phase 2'), -- 16:44:29.469 +(2904300, 9, 1, 0, 0, 0, 100, 0, 2000, 2000, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Rejek - Script - Say Line 0'), -- 16:44:31.812 +(2904300, 9, 2, 0, 0, 0, 100, 0, 0, 0, 0, 0, 45, 1, 1, 0, 0, 0, 0, 10, @CGUID+0, 28139, 0, 0, 0, 0, 0, 'Rejek - Script - Set Data'), +(2904300, 9, 3, 0, 0, 0, 100, 0, 0, 0, 0, 0, 45, 1, 1, 0, 0, 0, 0, 10, @CGUID+1, 28139, 0, 0, 0, 0, 0, 'Rejek - Script - Set Data'), +(2904300, 9, 4, 0, 0, 0, 100, 0, 10000, 10000, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Rejek - Script - Say Line 1'), -- 16:44:41.562 +(2904300, 9, 5, 0, 0, 0, 100, 0, 4000, 4000, 0, 0, 66, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 5.410521, 'Rejek - Script - Set Orientation'), -- 16:44:45.109 +(2904300, 9, 6, 0, 0, 0, 100, 0, 1000, 1000, 0, 0, 5, 35, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Rejek - Script - Play emote OneShotAttackUnarmed'), -- 16:44:46.344 +(2904300, 9, 7, 0, 0, 0, 100, 0, 0, 0, 0, 0, 11, 53171, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Rejek - Script - Cast Summon Stormwatcher Head'), -- 16:44:46.344 +(2904300, 9, 8, 0, 0, 0, 100, 0, 3000, 3000, 0, 0, 66, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 2.460914, 'Rejek - Script - Set Orientation'), -- 16:44:47.531 +(2904300, 9, 9, 0, 0, 0, 100, 0, 1500, 1500, 0, 0, 1, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Rejek - Script - Say Line 2'), -- 16:44:48.844 +(2904300, 9, 10, 0, 0, 0, 100, 0, 3000, 3000, 0, 0, 45, 3, 3, 0, 0, 0, 0, 10, @CGUID+0, 28139, 0, 0, 0, 0, 0, 'Rejek - Script - Set Data'), -- 16:44:51.359 +(2904300, 9, 11, 0, 0, 0, 100, 0, 0, 0, 0, 0, 45, 3, 3, 0, 0, 0, 0, 10, @CGUID+1, 28139, 0, 0, 0, 0, 0, 'Rejek - Script - Set Data'), -- 16:44:51.359 +(2904300, 9, 12, 0, 0, 0, 100, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 19, 28139, 0, 0, 0, 0, 0, 0, 'Rejek - Script - Say Line 2 on Frenzyheart Pup'), -- 16:44:51.359 +(2904300, 9, 13, 0, 0, 0, 100, 0, 6000, 6000, 0, 0, 1, 3, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Rejek - Script - Say Line 3'), -- 16:44:57.312 +(2904300, 9, 14, 0, 0, 0, 100, 0, 9000, 9000, 0, 0, 45, 1, 1, 0, 0, 0, 0, 19, 29116, 0, 0, 0, 0, 0, 0, 'Rejek - Script - Say Line 3'), -- 16:45:06.937 +(2904300, 9, 15, 0, 0, 0, 100, 0, 0, 0, 0, 0, 22, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Rejek - Script - Set Phase 1'); + +DELETE FROM `creature_text` WHERE `entry` IN(29043,28139); +INSERT INTO `creature_text` (`entry`, `groupid`, `id`, `text`, `type`, `language`, `probability`, `emote`, `duration`, `sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES +(29043, 0, 0, 'Who wants to see Rejek''s new helmet?', 12, 0, 100, 1, 0, 0, 29460, 0, 'Rejek'), +(29043, 1, 0, 'Ok, Rejek show!', 12, 0, 100, 1, 0, 0, 29463, 0, 'Rejek'), +(29043, 2, 0, 'What you think?', 12, 0, 100, 1, 0, 0, 29464, 0, 'Rejek'), +(29043, 3, 0, 'Rejek like! If helmet scares pups, Rejek can''t wait to see what it does to big-tongue cowards!', 12, 0, 100, 35, 0, 0, 29466, 0, 'Rejek'), +(28139, 0, 0, 'I wanna see!', 12, 0, 100, 396, 0, 0, 29461, 0, 'Frenzyheart Pup'), +(28139, 1, 0, 'Show me too!', 12, 0, 100, 1, 0, 0, 29462, 0, 'Frenzyheart Pup'), +(28139, 2, 0, 'Metalhead ate Rejek! Run!', 12, 0, 100, 1, 0, 0, 29465, 0, 'Frenzyheart Pup'); + +DELETE FROM `waypoints` WHERE `entry` IN((@CGUID*10)+0,(@CGUID*10)+1); +INSERT INTO `waypoints` (`entry`, `pointid`, `position_x`, `position_y`, `position_z`, `point_comment`) VALUES +((@CGUID*10)+0, 1, 5267.188, 4506.771, -84.47479, 'Frenzyheart Pup'), +((@CGUID*10)+0, 2, 5267.754, 4522.471, -83.85757, 'Frenzyheart Pup'), +((@CGUID*10)+1, 1, 5264.369, 4503.333, -84.65268, 'Frenzyheart Pup'), +((@CGUID*10)+1, 2, 5243.813, 4501.6, -84.7424, 'Frenzyheart Pup'); + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry`=53170; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES +(13, 1, 53170, 0, 0, 31, 0, 3, 29043, 0, 0, 0, 0, '', 'Ride Rejek'); diff --git a/sql/updates/world/3.3.5/2016_05_07_00_world.sql b/sql/updates/world/3.3.5/2016_05_07_00_world.sql new file mode 100644 index 00000000000..41a35083921 --- /dev/null +++ b/sql/updates/world/3.3.5/2016_05_07_00_world.sql @@ -0,0 +1,2 @@ +-- +UPDATE `smart_scripts` SET `action_param3`=1 WHERE `entryorguid`=3296 AND `source_type`=0 AND `id`=1; diff --git a/sql/updates/world/3.3.5/2016_05_07_01_world.sql b/sql/updates/world/3.3.5/2016_05_07_01_world.sql new file mode 100644 index 00000000000..1479c1bfba2 --- /dev/null +++ b/sql/updates/world/3.3.5/2016_05_07_01_world.sql @@ -0,0 +1,31 @@ +DELETE FROM `smart_scripts` WHERE `entryorguid` IN(29043) AND `source_type`=0 AND `id`>1; +DELETE FROM `smart_scripts` WHERE `entryorguid` =2904301 AND `source_type`=9; +DELETE FROM `creature_text` WHERE `entry` IN(29043) AND `groupid`>3; + +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(29043, 0, 2, 3, 20, 1, 100, 0, 12732, 0, 0, 0, 64, 1, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'Rejek - On Quest Reward 12732 (Phase 1) - Store Target'), +(29043, 0, 3, 0, 61, 1, 100, 0, 0, 0, 0, 0, 80, 2904301, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Rejek - On Quest Reward 12732 (Phase 1) - Run Script 2'), +(2904301, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 22, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Rejek - Script 2 - Set Phase 2'), -- 09:55:57.422 +(2904301, 9, 1, 0, 0, 0, 100, 0, 3000, 3000, 0, 0, 1, 4, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Rejek - Script 2 - Say Line 4'), -- 09:56:00.703 +(2904301, 9, 2, 0, 0, 0, 100, 0, 5000, 5000, 0, 0, 5, 7, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Rejek - Script 2 - Play Emote OneShotEat'), -- 09:56:05.469 +(2904301, 9, 3, 0, 0, 0, 100, 0, 0, 0, 0, 0, 11, 52968, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Rejek - Script 2 - Cast Heartblood Rage'), -- 09:56:05.469 +(2904301, 9, 4, 0, 0, 0, 100, 0, 2000, 2000, 0, 0, 1, 5, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Rejek - Script 2 - Say Line 5'), -- 09:56:07.891 +(2904301, 9, 5, 0, 0, 0, 100, 0, 4000, 4000, 0, 0, 5, 36, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Rejek - Script 2 - Play Emote OneShotAttack1H'), -- 09:56:11.578 +(2904301, 9, 6, 0, 0, 0, 100, 0, 2000, 2000, 0, 0, 5, 35, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Rejek - Script 2 - Play Emote OneShotAttackUnarmed'), -- 09:56:13.984 +(2904301, 9, 7, 0, 0, 0, 100, 0, 3000, 3000, 0, 0, 1, 6, 0, 0, 0, 0, 0, 12, 1, 0, 0, 0, 0, 0, 0, 'Rejek - Script 2 - Say Line 6'), -- 09:56:16.500 +(2904301, 9, 8, 0, 0, 0, 100, 0, 0, 0, 0, 0, 22, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Rejek - Script 2 - Set Phase 1'); + +INSERT INTO `creature_text` (`entry`, `groupid`, `id`, `text`, `type`, `language`, `probability`, `emote`, `duration`, `sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES +(29043, 4, 0, 'Still warm, just the way Rejek likes it.', 12, 0, 100, 1, 0, 0, 0, 0, 'Rejek'), +(29043, 5, 0, 'Rejek feel strong! Rejek crush big-tongue skulls between his hands!', 12, 0, 100, 34, 0, 0, 0, 0, 'Rejek'), +(29043, 6, 0, 'Rejek and $n will teach the enemies of the Frenzyheart to fear us!', 12, 0, 100, 53, 0, 0, 0, 0, 'Rejek'); + +DELETE FROM `smart_scripts` WHERE `entryorguid`=2816100 AND `source_type`=9 AND `id`=0 AND `link`=0; +DELETE FROM `smart_scripts` WHERE `entryorguid`=28161 AND `source_type`=0 AND `id`=4 AND `link`=0; +UPDATE `smart_scripts` SET `link`=0 WHERE `entryorguid`=28161 AND `source_type`=0 AND `id`=0 AND `link`=4; + +DELETE FROM `smart_scripts` WHERE `entryorguid` IN(4968) AND `source_type`=0 AND `id`=1; +UPDATE `smart_scripts` SET `link`=1 WHERE `entryorguid`=4968 AND `source_type`=0 AND `id`=0 AND `link`=0; + +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(4968, 0, 1, 0, 61, 0, 100, 0, 0, 0, 0, 0, 11, 23122, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'Lady Jaina Proudmoore - On Gossip Select - Cast Jaina''s Autograph'); diff --git a/sql/updates/world/3.3.5/2016_05_08_00_world.sql b/sql/updates/world/3.3.5/2016_05_08_00_world.sql new file mode 100644 index 00000000000..cfbe1f6b9ad --- /dev/null +++ b/sql/updates/world/3.3.5/2016_05_08_00_world.sql @@ -0,0 +1,11 @@ +SET @CGUID:=84737; + +-- Add missing Caravan Mule & Guard Didier <Brotherhood of the Light> spawns +DELETE FROM `creature` WHERE `guid` BETWEEN @CGUID+0 AND @CGUID+5; +INSERT INTO `creature` (`guid`, `id`, `map`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `curhealth`) VALUES +(@CGUID+0, 16232, 0, 2308.195, -5297.163, 82.0796, 1.780236, 120, 0), -- [65] Caravan Mule +(@CGUID+1, 16232, 0, 2309.498, -5294.246, 82.07687, 1.727876, 120, 0), -- [66] Caravan Mule +(@CGUID+2, 16232, 0, 2306.324, -5294.137, 82.07687, 1.815142, 120, 0), -- [67] Caravan Mule +(@CGUID+3, 16232, 0, 2308.93, -5290.619, 82.10618, 1.797689, 120, 0), -- [68] Caravan Mule +(@CGUID+4, 16232, 0, 2305.878, -5290.338, 82.33588, 1.832596, 120, 0), -- [69] Caravan Mule +(@CGUID+5, 16226, 0, 2305.295, -5286.124, 82.02069, 4.834562, 120, 0); -- [70] Guard Didier <Brotherhood of the Light> diff --git a/sql/updates/world/3.3.5/2016_05_09_00_world.sql b/sql/updates/world/3.3.5/2016_05_09_00_world.sql new file mode 100644 index 00000000000..3c21ed52350 --- /dev/null +++ b/sql/updates/world/3.3.5/2016_05_09_00_world.sql @@ -0,0 +1,2 @@ +-- +UPDATE `creature` SET `unit_flags` = 4104 WHERE `id` = 12430; diff --git a/sql/updates/world/3.3.5/2016_05_09_01_world.sql b/sql/updates/world/3.3.5/2016_05_09_01_world.sql new file mode 100644 index 00000000000..b75eb63dd2b --- /dev/null +++ b/sql/updates/world/3.3.5/2016_05_09_01_world.sql @@ -0,0 +1,21 @@ +DELETE FROM creature_text WHERE `entry` in(28116,28115); +INSERT INTO creature_text (`entry`, `groupid`, `id`, `text`, `type`, `language`, `probability`, `emote`, `duration`, `sound`, `BroadcastTextId`, `comment`) VALUES +(28115, 0, 0, 'You feel a massive jolt of energy as your body binds with that of Soo-holu.', 42, 0, 100, 0, 0, 0, 29003, 'Soo-holu to Player'), +(28116, 0, 0, 'You feel rage rise within you as your body binds with Kartak.', 42, 0, 100, 0, 0, 0, 29005, 'Kartak the Abominable to Player'); + +UPDATE `creature_template` SET `spell1`=52316, `spell2`=52271, `spell3`=52311, `spell4`=52272, `spell5`=52274, `VehicleId`=257 WHERE `entry`=28116; +UPDATE `creature_template` SET `spell1`=52331, `spell2`=52358, `spell3`=53032, `spell4`=52321, `spell5`=0, `VehicleId`=257 WHERE `entry`=28115; + +UPDATE `creature_template` SET `ainame`='SmartAI', `scriptname`='' WHERE `entry` IN(28115,28116); +DELETE FROM `smart_scripts` WHERE `entryorguid` IN(28115,28116) AND `source_type`=0; + +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(28115, 0, 0, 1, 54, 0, 100, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Soo-holu <Will of the Titans> - On Just Summoned - Set Passive'), +(28115, 0, 1, 0, 61, 0, 100, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Soo-holu <Will of the Titans> - On Just Summoned - Say'), +(28116, 0, 0, 1, 54, 0, 100, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Kartak the Abominable - On Just Summoned - Set Passive'), +(28116, 0, 1, 0, 61, 0, 100, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Kartak the Abominable - On Just Summoned - Say'); + +UPDATE `gameobject` SET `position_x`=5110.322754, `position_y`=5466.666504, `position_z`=-91.836319 WHERE `guid`=99745; +UPDATE `creature_text` SET `BroadcastTextId`=29247 WHERE `entry`=29043 AND `groupid`=4 AND `id`=0; +UPDATE `creature_text` SET `BroadcastTextId`=29248 WHERE `entry`=29043 AND `groupid`=5 AND `id`=0; +UPDATE `creature_text` SET `BroadcastTextId`=29249 WHERE `entry`=29043 AND `groupid`=6 AND `id`=0; diff --git a/sql/updates/world/3.3.5/2016_05_09_02_world.sql b/sql/updates/world/3.3.5/2016_05_09_02_world.sql new file mode 100644 index 00000000000..968ac92561e --- /dev/null +++ b/sql/updates/world/3.3.5/2016_05_09_02_world.sql @@ -0,0 +1,41 @@ +UPDATE `creature_template` SET `ScriptName`='npc_rocket_propelled_warhead' WHERE `entry`=27593; + +DELETE FROM `spell_script_names` WHERE `ScriptName` IN ('spell_z_check', 'spell_vehicle_warhead_fuse', 'spell_warhead_detonate','spell_warhead_fuse'); +INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES +(61678, 'spell_z_check'), +(49107, 'spell_vehicle_warhead_fuse'), +(49250, 'spell_warhead_detonate'), +(49181, 'spell_warhead_fuse'); + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry`=49332; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES +(13,1,49332,0,1,31,0,3,27702,0,0,0,0,'',"Spell 'Warhead Seeking Mine' can hit 'Horde Lumberboat'"), +(13,1,49332,0,2,31,0,3,27688,0,0,0,0,'',"Spell 'Warhead Seeking Mine' can hit 'Alliance Lumberboat'"); + +-- Warhead Explosion Bunny SAI +UPDATE `creature_template` SET `InhabitType`=4, `AIName`='SmartAI' WHERE `entry`=27663; +DELETE FROM `smart_scripts` WHERE `entryorguid`=27663 AND `source_type`=0; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(27663,0,0,0,54,0,100,0,0,0,0,0,11,49290,0,0,0,0,0,1,0,0,0,0,0,0,0,'Warhead Explosion Bunny - Just Summoned - Cast \'Torpedo Explosion\''); + +-- Alliance Lumberboat Explosions SAI +UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry`=27689; +DELETE FROM `smart_scripts` WHERE `entryorguid`=27689 AND `source_type`=0; +DELETE FROM `smart_scripts` WHERE `entryorguid`=2768900 AND `source_type`=9; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(27689,0,0,0,8,0,100,0,49290,0,0,0,80,2768900,0,0,0,0,0,1,0,0,0,0,0,0,0,'Alliance Lumberboat Explosions - On SpellHit \'Warhead Seeking Mine\' - Cast \'Horde Boat to Torpedo\''), +(2768900,9,0,0,0,0,100,0,0,0,0,0,11,42344,0,0,0,0,0,1,0,0,0,0,0,0,0,'Alliance Lumberboat Explosions - ActionList - Cast \'Cosmetic - Flame Patch 0.5\''), +(2768900,9,1,0,0,0,50,0,11000,11000,0,0,11,42345,0,0,0,0,0,1,0,0,0,0,0,0,0,'Alliance Lumberboat Explosions - ActionList - Cast \'Cosmetic - Flame Patch\''), +(2768900,9,2,0,0,0,50,0,11000,11000,0,0,11,42346,0,0,0,0,0,1,0,0,0,0,0,0,0,'Alliance Lumberboat Explosions - ActionList - Cast \'Cosmetic - Flame Patch 2.0\''); + +-- Horde Lumberboat SAI +UPDATE `creature_template` SET `InhabitType`=4, `AIName`='SmartAI' WHERE `entry`=27702; +DELETE FROM `smart_scripts` WHERE `entryorguid`=27702 AND `source_type`=0; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(27702,0,0,0,8,0,100,0,49332,0,0,0,11,49372,0,0,0,0,0,9,27593,0,100,0,0,0,0,'Horde Lumberboat - On SpellHit \'Warhead Seeking Mine\' - Cast \'Horde Boat to Torpedo\''); + +-- Alliance Lumberboat SAI +UPDATE `creature_template` SET `InhabitType`=4, `AIName`='SmartAI' WHERE `entry`=27688; +DELETE FROM `smart_scripts` WHERE `entryorguid`=27688 AND `source_type`=0; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(27688,0,0,0,8,0,100,0,49332,0,0,0,11,49257,0,0,0,0,0,9,27593,0,100,0,0,0,0,'Alliance Lumberboat - On SpellHit \'Warhead Seeking Mine\' - Cast \'Alliance Boat to Torpedo\''); diff --git a/sql/updates/world/3.3.5/2016_05_09_03_world.sql b/sql/updates/world/3.3.5/2016_05_09_03_world.sql new file mode 100644 index 00000000000..149d829c9f7 --- /dev/null +++ b/sql/updates/world/3.3.5/2016_05_09_03_world.sql @@ -0,0 +1,3 @@ +SET @MODIFIER := 50; +UPDATE `creature_template` SET `mechanic_immune_mask`=617299839, `DamageModifier`=@MODIFIER WHERE `entry` IN (35403,35405); +UPDATE `creature_template` SET `mechanic_immune_mask`=617299839, `ScriptName`='boss_ioc_horde_alliance' WHERE `entry` IN (34922,34924); diff --git a/sql/updates/world/3.3.5/2016_05_09_04_world.sql b/sql/updates/world/3.3.5/2016_05_09_04_world.sql new file mode 100644 index 00000000000..111b000efeb --- /dev/null +++ b/sql/updates/world/3.3.5/2016_05_09_04_world.sql @@ -0,0 +1,41 @@ +UPDATE `creature_template` SET `unit_flags`=33554432, `flags_extra`=0 WHERE `entry`=25744; +DELETE FROM `creature_summon_groups` WHERE `summonerId`=25741; + +DELETE FROM `spell_script_names` WHERE `ScriptName` IN +('spell_summon_blood_elves_script', +'spell_muru_darkness', +'spell_dark_fiend_skin', +'spell_transform_visual_missile_periodic', +'spell_summon_blood_elves_periodic'); +INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES +(46050,'spell_summon_blood_elves_script'), +(45996,'spell_muru_darkness'), +(45934,'spell_dark_fiend_skin'), +(46205,'spell_transform_visual_missile_periodic'), +(46041,'spell_summon_blood_elves_periodic'); + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry` IN (46208,46178); +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`SourceId`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionTarget`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition` ,`ErrorTextId`,`ScriptName`,`Comment`) VALUES +(13,1,46208,0,0,31,0,3,25741,0,0,0,'','Spell \'Transform Visual Missile\' targets M\'uru'), +(13,1,46178,0,0,31,0,3,25741,0,0,0,'','Spell \'Transform Visual Missile\' targets M\'uru'); + +UPDATE `creature_model_info` SET `BoundingRadius`=1, `CombatReach`=2 WHERE `DisplayID`=23842; +UPDATE `creature_model_info` SET `BoundingRadius`=6, `CombatReach`=6 WHERE `DisplayID`=23428; +UPDATE `creature_model_info` SET `BoundingRadius`=1, `CombatReach`=1.5 WHERE `DisplayID`=22471; +UPDATE `creature_model_info` SET `BoundingRadius`=0.48, `CombatReach`=11.2 WHERE `DisplayID`=22838; +UPDATE `creature_model_info` SET `BoundingRadius`=0.8893, `CombatReach`=2.5 WHERE `DisplayID`=23177; +UPDATE `creature_model_info` SET `BoundingRadius`=6, `CombatReach`=15 WHERE `DisplayID`=23200; +UPDATE `creature_model_info` SET `BoundingRadius`=0.8893, `CombatReach`=2.5 WHERE `DisplayID`=23334; +UPDATE `creature_model_info` SET `BoundingRadius`=0.612, `CombatReach`=3 WHERE `DisplayID`=23350; +UPDATE `creature_model_info` SET `BoundingRadius`=0.75, `CombatReach`=3.75 WHERE `DisplayID`=23473; +UPDATE `creature_model_info` SET `BoundingRadius`=0.6, `CombatReach`=3 WHERE `DisplayID`=23474; +UPDATE `creature_model_info` SET `BoundingRadius`=0.6, `CombatReach`=3 WHERE `DisplayID`=23476; +UPDATE `creature_model_info` SET `BoundingRadius`=0.6, `CombatReach`=3 WHERE `DisplayID`=23477; +UPDATE `creature_model_info` SET `BoundingRadius`=0.6, `CombatReach`=3 WHERE `DisplayID`=23478; +UPDATE `creature_model_info` SET `BoundingRadius`=0.754676, `CombatReach`=3 WHERE `DisplayID`=23479; +UPDATE `creature_model_info` SET `BoundingRadius`=0.51705, `CombatReach`=2.025 WHERE `DisplayID`=23531; +UPDATE `creature_model_info` SET `BoundingRadius`=0.51705, `CombatReach`=2.025 WHERE `DisplayID`=23533; +UPDATE `creature_model_info` SET `BoundingRadius`=0.51705, `CombatReach`=2.025 WHERE `DisplayID`=23537; +UPDATE `creature_model_info` SET `BoundingRadius`=1, `CombatReach`=1.5 WHERE `DisplayID`=23717; +UPDATE `creature_model_info` SET `BoundingRadius`=3, `CombatReach`=4.5 WHERE `DisplayID`=26628; +UPDATE `creature_model_info` SET `BoundingRadius`=0.25, `CombatReach`=0.375 WHERE `DisplayID`=29280; diff --git a/sql/updates/world/3.3.5/2016_05_11_00_world.sql b/sql/updates/world/3.3.5/2016_05_11_00_world.sql new file mode 100644 index 00000000000..9be7c8d3a0d --- /dev/null +++ b/sql/updates/world/3.3.5/2016_05_11_00_world.sql @@ -0,0 +1,33 @@ +-- +DELETE FROM `command` WHERE `name` IN ('server shutdown force','server restart force'); +INSERT INTO `command` (`name`,`permission`) VALUES ('server shutdown force', 839),('server restart force', 840); +UPDATE `command` SET `help`="Syntax: .server shutdown [force] #delay [#exit_code] [reason] + +Shut the server down after #delay seconds. Use #exit_code or 0 as program exit code. Specify 'force' to allow short-term shutdown despite other players being connected." WHERE `name` IN ('server shutdown','server shutdown force'); +UPDATE `command` SET `help`="Syntax: .server restart [force] #delay [#exit_code] [reason] + +Restart the server after #delay seconds. Use #exit_code or 2 as program exit code. Specify 'force' to allow short-term shutdown despite other players being connected." WHERE `name` IN ('server restart','server restart force'); + + +DELETE FROM `command` WHERE `permission` IN (571,575); +INSERT INTO `command` (`name`,`permission`,`help`) VALUES +("npc add", 571, "Syntax: .npc add #entry + Spawn a creature using template #entry and save it to the database. + If you want a temporary spawn that is not saved to the database, use .npc add temp instead."), +("npc add temp", 575, "Syntax: .npc add temp [loot/noloot] #entry +Adds temporary NPC, not saved to database. + Specify 'loot' to have the NPC's corpse stick around for some time after death, allowing it to be looted. + Specify 'noloot' to have the corpse disappear immediately."); + +DELETE FROM `command` WHERE `permission`=837; +INSERT INTO `command` (`name`,`permission`,`help`) VALUES ("npc evade",837,"Syntax: .npc evade [reason] [force] +Makes the targeted NPC enter evade mode.\nDefaults to specifying EVADE_REASON_OTHER, override this by providing the reason string (ex.: .npc evade EVADE_REASON_BOUNDARY).\nSpecify 'force' to clear any pre-existing evade state before evading - this may cause weirdness, use at your own risk."); + +DELETE FROM `command` WHERE `permission`=838; +INSERT INTO `command` (`name`,`permission`,`help`) VALUES ("pet level",838,"Syntax: .pet level #dLevel +Increases/decreases the pet's level by #dLevel. Pet's level cannot exceed the owner's level."); + +DELETE FROM `trinity_string` WHERE `entry` IN (11015,11016); +INSERT INTO `trinity_string` (`entry`,`content_default`) VALUES +(11015,"This creature does not have an active CreatureAI assigned to it."), +(11016,"Select a player or player pet."); diff --git a/sql/updates/world/3.3.5/2016_05_11_01_world.sql b/sql/updates/world/3.3.5/2016_05_11_01_world.sql new file mode 100644 index 00000000000..95fa08ab742 --- /dev/null +++ b/sql/updates/world/3.3.5/2016_05_11_01_world.sql @@ -0,0 +1,16 @@ +ALTER TABLE `spell_proc` + CHANGE `spellId` `SpellId` int(11) NOT NULL DEFAULT 0 FIRST, + CHANGE `schoolMask` `SchoolMask` tinyint(3) unsigned NOT NULL DEFAULT 0 AFTER `SpellId`, + CHANGE `spellFamilyName` `SpellFamilyName` smallint(5) unsigned NOT NULL DEFAULT 0 AFTER `SchoolMask`, + CHANGE `spellFamilyMask0` `SpellFamilyMask0` int(10) unsigned NOT NULL DEFAULT 0 AFTER `SpellFamilyName`, + CHANGE `spellFamilyMask1` `SpellFamilyMask1` int(10) unsigned NOT NULL DEFAULT 0 AFTER `SpellFamilyMask0`, + CHANGE `spellFamilyMask2` `SpellFamilyMask2` int(10) unsigned NOT NULL DEFAULT 0 AFTER `SpellFamilyMask1`, + CHANGE `typeMask` `ProcFlags` int(10) unsigned NOT NULL DEFAULT 0 AFTER `SpellFamilyMask2`, + CHANGE `spellTypeMask` `SpellTypeMask` int(10) unsigned NOT NULL DEFAULT 0 AFTER `ProcFlags`, + CHANGE `spellPhaseMask` `SpellPhaseMask` int(10) unsigned NOT NULL DEFAULT 0 AFTER `SpellTypeMask`, + CHANGE `hitMask` `HitMask` int(10) unsigned NOT NULL DEFAULT 0 AFTER `SpellPhaseMask`, + CHANGE `attributesMask` `AttributesMask` int(10) unsigned NOT NULL DEFAULT 0 AFTER `HitMask`, + CHANGE `ratePerMinute` `ProcsPerMinute` float NOT NULL DEFAULT 0 AFTER `AttributesMask`, + CHANGE `chance` `Chance` float NOT NULL DEFAULT 0 AFTER `ProcsPerMinute`, + CHANGE `cooldown` `Cooldown` int(10) unsigned NOT NULL DEFAULT 0 AFTER `Chance`, + CHANGE `charges` `Charges` tinyint(3) unsigned NOT NULL DEFAULT 0 AFTER `Cooldown`; diff --git a/sql/updates/world/3.3.5/2016_05_20_00_world.sql b/sql/updates/world/3.3.5/2016_05_20_00_world.sql new file mode 100644 index 00000000000..67fc3e7a5d7 --- /dev/null +++ b/sql/updates/world/3.3.5/2016_05_20_00_world.sql @@ -0,0 +1,37 @@ +DELETE FROM `spell_script_names` WHERE `ScriptName` IN +('spell_mage_blazing_speed','spell_pri_blessed_recovery','spell_dru_forms_trinket','spell_dru_t9_feral_relic', +'spell_sha_nature_guardian','spell_warl_nether_protection','spell_hun_piercing_shots','spell_hun_t9_4p_bonus', +'spell_sha_lightning_shield','spell_dk_acclimation','spell_dk_advantage_t10_4p','spell_dk_improved_blood_presence_triggered', +'spell_rog_t10_2p_bonus','spell_pal_illumination','spell_item_soul_preserver','spell_item_death_choice', +'spell_item_lightning_capacitor','spell_item_thunder_capacitor','spell_item_toc25_normal_caster_trinket','spell_item_toc25_heroic_caster_trinket', +'spell_igb_battle_experience_check','spell_gen_blood_reserve','spell_item_darkmoon_card_greatness', +'spell_item_charm_witch_doctor','spell_item_mana_drain'); + +INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES +(-49200, 'spell_dk_acclimation'), -- DK Acclimation +(70656, 'spell_dk_advantage_t10_4p'), -- DK Advantage t10 4p melee +(63611, 'spell_dk_improved_blood_presence_triggered'), -- DK Improved blood Presence Triggered +(37336, 'spell_dru_forms_trinket'), -- Druid Forms Trinket +(67353, 'spell_dru_t9_feral_relic'), -- Druid T9 Feral Relic (Idol of Mutilation) +(64568, 'spell_gen_blood_reserve'), -- Blood Reserve (weapon enchant proc) +(-53234, 'spell_hun_piercing_shots'), -- Hunter Piercing Shots +(-67151, 'spell_hun_t9_4p_bonus'), -- Hunter T9 Bonus +(71201, 'spell_igb_battle_experience_check'), -- Battle Experience (Gunship - ICC) +(60510, 'spell_item_soul_preserver'), -- Soul Preserver +(67702, 'spell_item_death_choice'), -- Death Choice Trinket +(67771, 'spell_item_death_choice'), -- Death Choice Trinket +(37657, 'spell_item_lightning_capacitor'), -- Lightning Capcitor +(54841, 'spell_item_thunder_capacitor'), -- Thunder Capacitor +(67712, 'spell_item_toc25_normal_caster_trinket'), -- Item - Coliseum 25 Normal Caster Trinket +(67758, 'spell_item_toc25_heroic_caster_trinket'), -- Item - Coliseum 25 Heroic Caster Trinket +(57345, 'spell_item_darkmoon_card_greatness'), -- Darkmoon Card: Greatness +(43820, 'spell_item_charm_witch_doctor'), -- Charm of the Witch Doctor +(27522, 'spell_item_mana_drain'), -- Mana Drain +(40336, 'spell_item_mana_drain'), -- Mana Drain +(-31641, 'spell_mage_blazing_speed'), -- Mage Blazing Speed +(-20210, 'spell_pal_illumination'), -- Paladin Illumination (for Holy Shock) +(-27811, 'spell_pri_blessed_recovery'), -- Priest Blessed Recovery +(70805, 'spell_rog_t10_2p_bonus'), -- Rogue T10 2P bonus +(-30881, 'spell_sha_nature_guardian'), -- Shaman Nature's Guardian +(-324, 'spell_sha_lightning_shield'), -- Shaman Lightning Shield +(-30299, 'spell_warl_nether_protection'); -- Warlock Nether protection diff --git a/sql/updates/world/3.3.5/2016_05_23_00_world.sql b/sql/updates/world/3.3.5/2016_05_23_00_world.sql new file mode 100644 index 00000000000..b2b9b9b0b34 --- /dev/null +++ b/sql/updates/world/3.3.5/2016_05_23_00_world.sql @@ -0,0 +1,225 @@ +SET @CGUID:=145211; + +-- Add missing creature spawns in Ghostlands & Eversong Woods +DELETE FROM `creature` WHERE `guid` BETWEEN @CGUID+0 AND @CGUID+215; +INSERT INTO `creature` (`guid`, `id`, `map`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `curhealth`) VALUES +(@CGUID+0 , 1420, 530, 6785.898, -7607.692, 128.1121, 3.815103, 120, 0), -- Toad +(@CGUID+1 , 1420, 530, 6753.482, -7647.198, 128.3187, 3.793595, 120, 0), -- 1420 (Area: -1) +(@CGUID+2 , 2914, 530, 6830.517, -7396.761, 46.36444, 2.204267, 120, 0), -- Snake +(@CGUID+3 , 2914, 530, 6967.708, -7464.932, 47.05861, 1.433785, 120, 0), -- 2914 (Area: 3508) +(@CGUID+4 , 2914, 530, 6764.093, -7363.276, 50.46708, 2.048597, 120, 0), -- 2914 (Area: 3517) +(@CGUID+5 , 2914, 530, 6703.647, -7402.308, 51.60884, 5.743487, 120, 0), -- 2914 (Area: 3517) +(@CGUID+6 , 2914, 530, 9898.549, -6844.095, 21.79119, 5.635744, 120, 0), -- 2914 (Area: 0) +(@CGUID+7 , 2914, 530, 9200.372, -7787.419, 114.7875, 3.199877, 120, 0), -- 2914 (Area: 3480) +(@CGUID+8 , 2914, 530, 9155.745, -7848.188, 106.3085, 5.677832, 120, 0), -- 2914 (Area: 3480) (possible waypoints or random movement) +(@CGUID+9 , 2914, 530, 8850.941, -7711.045, 142.8265, 0.9482585, 120, 0), -- 2914 (Area: 0) +(@CGUID+10 , 2914, 530, 8728.21, -7871.131, 167.5767, 3.596344, 120, 0), -- 2914 (Area: 3476) +(@CGUID+11 , 2914, 530, 8637.07, -8030.312, 172.4991, 0.7605414, 120, 0), -- 2914 (Area: 3476) (possible waypoints or random movement) +(@CGUID+12 , 2914, 530, 8105.803, -7868.944, 182.6229, 3.106677, 120, 0), -- 2914 (Area: 3476) +(@CGUID+13 , 13321, 530, 6804.864, -7692.796, 123.9494, 1.613627, 120, 0), -- Frog +(@CGUID+14 , 13321, 530, 7139.874, -6836.952, 42.78193, 3.004393, 120, 0), -- 13321 (Area: 0) +(@CGUID+15 , 13321, 530, 6874.098, -6292.956, 28.83097, 2.986305, 120, 0), -- 13321 (Area: 0) +(@CGUID+16 , 13321, 530, 6896.695, -6237.083, 27.97087, 3.193066, 120, 0), -- 13321 (Area: 0) +(@CGUID+17 , 16355, 530, 6590.018, -6665.895, 47.47748, 3.028023, 120, 0), -- Lesser Scourgebat +(@CGUID+18 , 16355, 530, 6615.374, -6649.544, 47.67059, 2.618959, 120, 0), -- 16355 (Area: 3861) +(@CGUID+19 , 16355, 530, 6678.834, -6669.411, 46.41251, 2.527587, 120, 0), -- 16355 (Area: 3861) +(@CGUID+20 , 16355, 530, 6751.53, -6650.502, 40.92892, 3.361847, 120, 0), -- 16355 (Area: 3861) +(@CGUID+21 , 16355, 530, 6694.581, -6614.153, 42.82938, 1.788726, 120, 0), -- 16355 (Area: 3861) +(@CGUID+22 , 16355, 530, 6746.584, -6637.266, 40.26681, 1.167443, 120, 0), -- 16355 (Area: 3861) +(@CGUID+23 , 16355, 530, 6613.917, -6613.427, 45.56771, 1.741399, 120, 0), -- 16355 (Area: 0) +(@CGUID+24 , 16355, 530, 6709.029, -6582.425, 38.43601, 3.079052, 120, 0), -- 16355 (Area: 0) +(@CGUID+25 , 16355, 530, 6655.542, -6584.168, 47.69909, 1.860139, 120, 0), -- 16355 (Area: 0) +(@CGUID+26 , 16355, 530, 6777.141, -6576.169, 22.53009, 2.004029, 120, 0), -- 16355 (Area: 5779) +(@CGUID+27 , 16355, 530, 6820.745, -6629.127, 29.34797, 4.576158, 120, 0), -- 16355 (Area: 0) +(@CGUID+28 , 16355, 530, 6913.5, -6392.067, 32.9911, 1.252754, 120, 0), -- 16355 (Area: 3514) +(@CGUID+29 , 16355, 530, 6786.887, -6389.533, 33.69895, 1.401155, 120, 0), -- 16355 (Area: 3514) +(@CGUID+30 , 16355, 530, 6834.158, -6266.923, 28.88157, 0.7696482, 120, 0), -- 16355 (Area: 0) +(@CGUID+31 , 16355, 530, 6811.086, -6309.688, 32.27558, 6.07257, 120, 0), -- 16355 (Area: 0) +(@CGUID+32 , 16355, 530, 6746.925, -6374.906, 38.59792, 0.9527051, 120, 0), -- 16355 (Area: 0) +(@CGUID+33 , 16355, 530, 6743.388, -6254.041, 35.68666, 0.4505479, 120, 0), -- 16355 (Area: 0) +(@CGUID+34 , 16352, 530, 6607.711, -7228.053, 47.55958, 2.182768, 120, 0), -- Greater Spindleweb +(@CGUID+35 , 16352, 530, 6840.333, -6911.398, 80.30796, 5.87111, 120, 0), -- 16352 (Area: 0) +(@CGUID+36 , 16352, 530, 6950.854, -6882.652, 51.16842, 4.52, 120, 0), -- 16352 (Area: 3506) +(@CGUID+37 , 16352, 530, 6768.055, -6851.429, 87.48727, 5.528165, 120, 0), -- 16352 (Area: 0) +(@CGUID+38 , 16352, 530, 6770.479, -6850.35, 87.49597, 3.62482, 120, 0), -- 16352 (Area: 0) +(@CGUID+39 , 16352, 530, 6559.612, -6826.08, 105.455, 4.570914, 120, 0), -- 16352 (Area: 0) +(@CGUID+40 , 16352, 530, 6601.431, -6767.694, 109.1149, 4.307267, 120, 0), -- 16352 (Area: 0) +(@CGUID+41 , 16352, 530, 6599.975, -6751.242, 116.5198, 3.551486, 120, 0), -- 16352 (Area: 0) +(@CGUID+42 , 16352, 530, 7008.281, -6705.673, 28.26144, 4.884287, 120, 0), -- 16352 (Area: 0) +(@CGUID+43 , 16352, 530, 6871.393, -6317.614, 32.46682, 3.043771, 120, 0), -- 16352 (Area: 3514) +(@CGUID+44 , 16352, 530, 6878.775, -6305.776, 31.08891, 5.672717, 120, 0), -- 16352 (Area: 3514) +(@CGUID+45 , 16352, 530, 6843.483, -6281.33, 26.38034, 3.213944, 120, 0), -- 16352 (Area: 0) +(@CGUID+46 , 16352, 530, 6876.344, -6120.826, 27.65071, 0.7722683, 120, 0), -- 16352 (Area: 0) +(@CGUID+47 , 16352, 530, 6918.788, -6012.118, 16.0651, 0.2698549, 120, 0), -- 16352 (Area: 0) +(@CGUID+48 , 16352, 530, 6780.824, -5914.694, 55.04383, 4.475933, 120, 0), -- 16352 (Area: 0) +(@CGUID+49 , 16352, 530, 6833.493, -5866.168, 14.88271, 0.9358938, 120, 0), -- 16352 (Area: 0) +(@CGUID+50 , 16352, 530, 6840.229, -5885.817, 18.84746, 0.9175394, 120, 0), -- 16352 (Area: 0) +(@CGUID+51 , 16352, 530, 6880.296, -5831.833, 12.60031, 4.379216, 120, 0), -- 16352 (Area: 0) +(@CGUID+52 , 16352, 530, 6921.029, -5888.282, 11.06036, 3.010598, 120, 0), -- 16352 (Area: 0) +(@CGUID+53 , 16349, 530, 6889.151, -7353.237, 48.22483, 4.51504, 120, 0), -- Ghostclaw Ravager +(@CGUID+54 , 16349, 530, 6842.837, -7303.427, 54.16766, 1.288876, 120, 0), -- 16349 (Area: 3517) +(@CGUID+55 , 16349, 530, 6546.021, -7284.988, 56.26369, 1.260878, 120, 0), -- 16349 (Area: 3517) +(@CGUID+56 , 16349, 530, 6679.54, -7225.896, 45.35223, 4.113977, 120, 0), -- 16349 (Area: 3517) +(@CGUID+57 , 16349, 530, 6643.776, -7193.75, 54.53874, 0, 120, 0), -- 16349 (Area: 3517) +(@CGUID+58 , 16349, 530, 6814.677, -6882.684, 88.09016, 2.293302, 120, 0), -- 16349 (Area: 0) +(@CGUID+59 , 16349, 530, 6721.141, -6838.881, 103.265, 6.057627, 120, 0), -- 16349 (Area: 0) +(@CGUID+60 , 16349, 530, 6697.734, -6834.776, 102.7457, 6.008372, 120, 0), -- 16349 (Area: 0) +(@CGUID+61 , 16349, 530, 6650.794, -6857.804, 114.3118, 2.645206, 120, 0), -- 16349 (Area: 0) +(@CGUID+62 , 16349, 530, 6848.059, -6343.108, 31.09843, 4.492753, 120, 0), -- 16349 (Area: 3514) +(@CGUID+63 , 16349, 530, 6946.989, -6384.78, 39.4313, 4.954051, 120, 0), -- 16349 (Area: 3514) +(@CGUID+64 , 16349, 530, 6912.969, -6363.86, 34.72787, 3.331182, 120, 0), -- 16349 (Area: 3514) +(@CGUID+65 , 16349, 530, 6766.795, -6363.485, 39.13235, 0.5625338, 120, 0), -- 16349 (Area: 0) +(@CGUID+66 , 16349, 530, 6946.226, -6247.874, 32.41405, 5.925901, 120, 0), -- 16349 (Area: 0) +(@CGUID+67 , 16349, 530, 6788.563, -6065.623, 76.42849, 3.921466, 120, 0), -- 16349 (Area: 0) +(@CGUID+68 , 16349, 530, 6792.339, -6061.395, 74.22968, 3.969122, 120, 0), -- 16349 (Area: 0) +(@CGUID+69 , 16349, 530, 6810.644, -5954.92, 53.78344, 3.796812, 120, 0), -- 16349 (Area: 0) +(@CGUID+70 , 16348, 530, 7063.472, -7130.528, 46.0153, 6.204991, 120, 0), -- Ghostclaw Lynx +(@CGUID+71 , 16348, 530, 7284.161, -6991.957, 49.69464, 1.443535, 120, 0), -- 16348 (Area: 0) +(@CGUID+72 , 16348, 530, 7213.42, -6959.183, 48.15844, 1.778343, 120, 0), -- 16348 (Area: 0) +(@CGUID+73 , 16348, 530, 7250.096, -6969.17, 47.61874, 1.986341, 120, 0), -- 16348 (Area: 0) +(@CGUID+74 , 16348, 530, 7050.619, -6915.433, 49.37156, 2.73385, 120, 0), -- 16348 (Area: 0) +(@CGUID+75 , 16348, 530, 7451.216, -7814.882, 147.9057, 3.899374, 120, 0), -- 16348 (Area: 3516) +(@CGUID+76 , 16348, 530, 7396.958, -7735.421, 126.7814, 2.59045, 120, 0), -- 16348 (Area: 3516) +(@CGUID+77 , 16348, 530, 7340.802, -7687.29, 114.7227, 0.2125256, 120, 0), -- 16348 (Area: 3516) +(@CGUID+78 , 16348, 530, 7183.236, -7268.509, 46.15837, 4.739726, 120, 0), -- 16348 (Area: -1) +(@CGUID+79 , 16348, 530, 7229.547, -7256.011, 50.49553, 3.413854, 120, 0), -- 16348 (Area: -1) +(@CGUID+80 , 16348, 530, 7087.505, -7228.648, 47.83735, 2.820592, 120, 0), -- 16348 (Area: -1) +(@CGUID+81 , 16348, 530, 7216.22, -6980.535, 45.21544, 2.602345, 120, 0), -- 16348 (Area: -1) +(@CGUID+82 , 16348, 530, 7314.215, -6966.182, 50.0986, 1.607889, 120, 0), -- 16348 (Area: 0) +(@CGUID+83 , 16348, 530, 7330.698, -6964.013, 48.61691, 2.429726, 120, 0), -- 16348 (Area: 0) +(@CGUID+84 , 16348, 530, 7381.186, -6840.756, 49.09549, 5.203093, 120, 0), -- 16348 (Area: 0) +(@CGUID+85 , 16348, 530, 7338.635, -6880.206, 47.74126, 3.243301, 120, 0), -- 16348 (Area: 0) +(@CGUID+86 , 16348, 530, 7245.959, -6846.432, 44.47991, 3.107588, 120, 0), -- 16348 (Area: 0) +(@CGUID+87 , 16348, 530, 7271.94, -6770.036, 41.23086, 3.766337, 120, 0), -- 16348 (Area: 0) +(@CGUID+88 , 16348, 530, 7214.612, -6826.908, 47.06087, 1.656858, 120, 0), -- 16348 (Area: 0) +(@CGUID+89 , 16354, 530, 7076.276, -6972.893, 46.59879, 5.554435, 120, 0), -- Vampiric Mistbat +(@CGUID+90 , 16354, 530, 7017.884, -6890.591, 51.47795, 0.1461384, 120, 0), -- 16354 (Area: 0) (Auras: 29363 - 29363) +(@CGUID+91 , 16354, 530, 7113.623, -6924.28, 47.51407, 1.275599, 120, 0), -- 16354 (Area: 0) (Auras: 29363 - 29363) +(@CGUID+92 , 16354, 530, 7120.204, -6986.206, 46.46815, 3.014331, 120, 0), -- 16354 (Area: 0) (Auras: 29363 - 29363) +(@CGUID+93 , 16354, 530, 7042.884, -7063.796, 47.43617, 0.2345574, 120, 0), -- 16354 (Area: 0) (Auras: 29363 - 29363) +(@CGUID+94 , 16354, 530, 7126.826, -6958.08, 46.08292, 1.337121, 120, 0), -- 16354 (Area: 0) (Auras: 29363 - 29363) +(@CGUID+95 , 16354, 530, 7014.953, -7154.451, 44.05517, 4.580289, 120, 0), -- 16354 (Area: 0) (Auras: 29363 - 29363) +(@CGUID+96 , 16354, 530, 7049.035, -7179.571, 44.51942, 2.854439, 120, 0), -- 16354 (Area: 0) (Auras: 29363 - 29363) +(@CGUID+97 , 16354, 530, 7192.258, -6990.721, 45.789, 6.118358, 120, 0), -- 16354 (Area: 3493) (Auras: 29363 - 29363) +(@CGUID+98 , 16354, 530, 7297.3, -6952.889, 48.22968, 0.04103268, 120, 0), -- 16354 (Area: 0) (Auras: 29363 - 29363) +(@CGUID+99 , 16354, 530, 7256.268, -6915.919, 49.01978, 6.275373, 120, 0), -- 16354 (Area: 0) (Auras: 29363 - 29363) +(@CGUID+100, 16354, 530, 7100.769, -6852.027, 48.50787, 3.594324, 120, 0), -- 16354 (Area: 0) (Auras: 29363 - 29363) +(@CGUID+101, 16354, 530, 7115.031, -6797.596, 43.95771, 4.893901, 120, 0), -- 16354 (Area: 0) (Auras: 29363 - 29363) +(@CGUID+102, 16354, 530, 7046.083, -6001.001, 5.373741, 1.707996, 120, 0), -- 16354 (Area: 0) (Auras: 29363 - 29363) +(@CGUID+103, 16354, 530, 7657.632, -7820.115, 155.0192, 0.007812341, 120, 0), -- 16354 (Area: 5780) (Auras: 29363 - 29363) +(@CGUID+104, 16354, 530, 7625.615, -7846.144, 163.4028, 4.013608, 120, 0), -- 16354 (Area: 5780) (Auras: 29363 - 29363) +(@CGUID+105, 16354, 530, 7122.203, -7253.339, 46.5706, 5.714052, 120, 0), -- 16354 (Area: -1) (Auras: 29363 - 29363) +(@CGUID+106, 16354, 530, 7217.567, -6982.356, 45.42596, 2.619296, 120, 0), -- 16354 (Area: -1) (Auras: 29363 - 29363) +(@CGUID+107, 16354, 530, 7117.631, -7009.641, 45.96103, 1.385088, 120, 0), -- 16354 (Area: -1) (Auras: 29363 - 29363) +(@CGUID+108, 16354, 530, 7166.285, -6976.54, 44.8732, 4.951204, 120, 0), -- 16354 (Area: -1) (Auras: 29363 - 29363) +(@CGUID+109, 16354, 530, 7312.727, -6912.875, 50.63189, 4.525721, 120, 0), -- 16354 (Area: 0) (Auras: 29363 - 29363) +(@CGUID+110, 16354, 530, 7320.769, -6873.548, 46.65247, 4.479732, 120, 0), -- 16354 (Area: 0) (Auras: 29363 - 29363) +(@CGUID+111, 16354, 530, 7280.374, -6883.919, 46.72137, 2.94094, 120, 0), -- 16354 (Area: 0) (Auras: 29363 - 29363) +(@CGUID+112, 16354, 530, 7311.557, -6785.887, 42.1341, 3.170881, 120, 0), -- 16354 (Area: 0) (Auras: 29363 - 29363) +(@CGUID+113, 16354, 530, 7346.644, -6818.584, 45.92062, 3.949025, 120, 0), -- 16354 (Area: 0) (Auras: 29363 - 29363) +(@CGUID+114, 16354, 530, 7288.737, -6849.499, 44.25882, 4.882647, 120, 0), -- 16354 (Area: 0) (Auras: 29363 - 29363) +(@CGUID+115, 16354, 530, 7377.227, -6753.976, 31.68961, 0.03127035, 120, 0), -- 16354 (Area: 0) (Auras: 29363 - 29363) +(@CGUID+116, 16354, 530, 7416.598, -6716.583, 28.30837, 0.7370265, 120, 0), -- 16354 (Area: 0) (Auras: 29363 - 29363) +(@CGUID+117, 16354, 530, 7353.333, -6720.048, 30.60197, 2.399705, 120, 0), -- 16354 (Area: 0) (Auras: 29363 - 29363) +(@CGUID+118, 16354, 530, 7259.75, -6787.555, 40.84682, 6.201098, 120, 0), -- 16354 (Area: 0) (Auras: 29363 - 29363) +(@CGUID+119, 16354, 530, 7108.942, -6779.335, 39.96529, 5.709267, 120, 0), -- 16354 (Area: 0) (Auras: 29363 - 29363) +(@CGUID+120, 16354, 530, 7133.71, -6917.99, 50.83417, 2.893063, 120, 0), -- 16354 (Area: 0) (Auras: 29363 - 29363) +(@CGUID+121, 16405, 530, 6988.21, -5644.906, -3.24633, 3.193715, 120, 0), -- Whitetail Frenzy (fishy!) +(@CGUID+122, 16405, 530, 7185.634, -5581.585, -7.89854, 1.237991, 120, 0), -- 16405 (Area: 3455) (possible waypoints or random movement) +(@CGUID+123, 16405, 530, 7125.062, -5516.672, -5.845787, 0.05448707, 120, 0), -- 16405 (Area: 3455) +(@CGUID+124, 16405, 530, 7250.163, -5645.383, -4.686822, 1.609466, 120, 0), -- 16405 (Area: 3455) (possible waypoints or random movement) +(@CGUID+125, 16405, 530, 7251.583, -5518.657, -14.82046, 5.090523, 120, 0), -- 16405 (Area: 3455) +(@CGUID+126, 16405, 530, 7319, -5583.684, -5.345567, 4.631339, 120, 0), -- 16405 (Area: 3455) +(@CGUID+127, 16405, 530, 7385.255, -5514.504, -23.83957, 4.482534, 120, 0), -- 16405 (Area: 3455) +(@CGUID+128, 16404, 530, 7453.585, -5582.35, -4.679311, 1.291544, 120, 0), -- Yellowgill Frenzy (fishy!) +(@CGUID+129, 16404, 530, 7650.671, -5514.592, -49.15406, 0.4712389, 120, 0), -- 16404 (Area: 3455) +(@CGUID+130, 16404, 530, 7584.502, -5583.413, -24.85344, 3.455752, 120, 0), -- 16404 (Area: 3455) +(@CGUID+131, 16404, 530, 7583.759, -5452.181, -46.03991, 2.70526, 120, 0), -- 16404 (Area: 3455) +(@CGUID+132, 16404, 530, 7714.01, -5449.991, -64.69885, 5.61996, 120, 0), -- 16404 (Area: 3455) +(@CGUID+133, 16404, 530, 7646.778, -5386.804, -65.33501, 3.752458, 120, 0), -- 16404 (Area: 3455) +(@CGUID+134, 16404, 530, 7782.522, -5520.318, -25.0596, 2.251475, 120, 0), -- 16404 (Area: 3455) +(@CGUID+135, 16404, 530, 7851.458, -5451.522, -47.55369, 0.6981317, 120, 0), -- 16404 (Area: 3455) +(@CGUID+136, 16404, 530, 7916.752, -5518.634, -40.62648, 0.08726646, 120, 0), -- 16404 (Area: 3455) +(@CGUID+137, 16404, 530, 7981.461, -5584.885, -4.679321, 2.984513, 120, 0), -- 16404 (Area: 3455) +(@CGUID+138, 16404, 530, 7981.47, -5453.279, -45.36422, 2.443461, 120, 0), -- 16404 (Area: 3455) +(@CGUID+139, 16404, 530, 8049.632, -5517.96, -25.7112, 5.201081, 120, 0), -- 16404 (Area: 3455) +(@CGUID+140, 16404, 530, 8116.961, -5448.617, -46.06174, 0.6981317, 120, 0), -- 16404 (Area: 3455) +(@CGUID+141, 16404, 530, 8115.655, -5582.934, -4.67935, 3.071779, 120, 0), -- 16404 (Area: 3455) +(@CGUID+142, 16404, 530, 8181.515, -5517.779, -21.47383, 3.996804, 120, 0), -- 16404 (Area: 3455) +(@CGUID+143, 33712, 530, 8581.657, -5615.35, -1.142317, 1.903857, 120, 0), -- Golden Crawler +(@CGUID+144, 33712, 530, 8504.382, -5543.861, -1.478864, 3.13378, 120, 0), -- 33712 (Area: 3460) +(@CGUID+145, 33712, 530, 8514.937, -5619.518, -0.04902005, 2.168977, 120, 0), -- 33712 (Area: 3460) +(@CGUID+146, 33712, 530, 8415.799, -5584.587, -1.309665, 0, 120, 0), -- 33712 (Area: 3460) +(@CGUID+147, 33712, 530, 8332.279, -5641.95, -1.466211, 2.25529, 120, 0), -- 33712 (Area: 3460) +(@CGUID+148, 33712, 530, 8283.341, -5648.665, -1.085784, 0, 120, 0), -- 33712 (Area: 3460) +(@CGUID+149, 33712, 530, 8282.833, -5682.408, 1.912665, 1.05757, 120, 0), -- 33712 (Area: 3460) +(@CGUID+150, 33712, 530, 8293.516, -5772.522, 0.8719814, 5.366834, 120, 0), -- 33712 (Area: 3460) +(@CGUID+151, 33712, 530, 8308.861, -5862.752, 0.241255, 6.083331, 120, 0), -- 33712 (Area: 3460) +(@CGUID+152, 33712, 530, 9197.843, -5831.596, -1.436119, 3.801267, 120, 0), -- 33712 (Area: 3911) +(@CGUID+153, 33712, 530, 9354.067, -5992.446, 0.5006291, 4.806949, 120, 0), -- 33712 (Area: 3911) +(@CGUID+154, 33712, 530, 9355.795, -6054.746, -10.57742, 5.58345, 120, 0), -- 33712 (Area: 3911) +(@CGUID+155, 15372, 530, 10655.46, -6208.573, 44.35903, 3.352107, 120, 0), -- 15372 (Area: 3431) +(@CGUID+156, 15372, 530, 10664.23, -6132.04, 28.6685, 2.430012, 120, 0), -- 15372 (Area: 3431) +(@CGUID+157, 15372, 530, 10680.05, -6169.8, 39.0421, 1.041597, 120, 0), -- 15372 (Area: 3431) +(@CGUID+158, 721, 530, 8518.23, -5731.495, 13.00602, 3.633779, 120, 0), -- Rabbit +(@CGUID+159, 721, 530, 8639.186, -5761.18, 11.46758, 3.938846, 120, 0), -- 721 (Area: 3460) +(@CGUID+160, 721, 530, 8778.733, -5847.375, 7.75886, 4.726789, 120, 0), -- 721 (Area: 3460) +(@CGUID+161, 721, 530, 8984.896, -5983.854, 19.71628, 4.000124, 120, 0), -- 721 (Area: 3911) +(@CGUID+162, 721, 530, 9145.909, -5946.4, 28.77039, 2.019282, 120, 0), -- 721 (Area: 3911) +(@CGUID+163, 721, 530, 9231.008, -6160.386, 25.5099, 0.5819958, 120, 0), -- 721 (Area: 3911) +(@CGUID+164, 721, 530, 9452.181, -7939.893, 11.60837, 3.357151, 120, 0), -- 721 (Area: 3472) +(@CGUID+165, 721, 530, 9438.168, -7889.708, 21.39819, 2.464021, 120, 0), -- 721 (Area: 3472) +(@CGUID+166, 721, 530, 9396.646, -7802.477, 55.43135, 0.6543702, 120, 0), -- 721 (Area: 3480) +(@CGUID+167, 4075, 530, 6658.765, -6295.493, 29.20658, 2.160989, 120, 0), -- Rat +(@CGUID+168, 4075, 530, 7113.27, -5958.493, 12.98514, 1.957865, 120, 0), -- 4075 (Area: 0) +(@CGUID+169, 4075, 530, 7308.667, -5989.029, 16.2368, 2.572109, 120, 0), -- 4075 (Area: 3491) +(@CGUID+170, 15649, 530, 10060.82, -6872.714, 24.29431, 4.285359, 120, 0), -- Feral Dragonhawk Hatchling +(@CGUID+171, 15651, 530, 8653.924, -5784.069, 18.15051, 3.120111, 120, 0), -- Springpaw Stalker +(@CGUID+172, 15651, 530, 10048.03, -6717.27, 31.03372, 4.651473, 120, 0), -- 15651 (Area: 3533) +(@CGUID+173, 15651, 530, 10116.2, -7079.959, 11.65078, 5.202464, 120, 0), -- 15651 (Area: 0) +(@CGUID+174, 15651, 530, 10119.57, -7117.229, 11.13619, 5.610377, 120, 0), -- 15651 (Area: 0) +(@CGUID+175, 15651, 530, 10245.07, -7154.263, 5.379348, 3.824573, 120, 0), -- 15651 (Area: 0) +(@CGUID+176, 15651, 530, 10312.5, -7285.686, 10.4436, 3.958998, 120, 0), -- 15651 (Area: 0) +(@CGUID+177, 15651, 530, 0155.74, -7315.172, 46.89272, 1.747505, 120, 0), -- 15651 (Area: 0) +(@CGUID+178, 15651, 530, 10212.78, -7312.304, 43.83004, 2.297004, 120, 0), -- 15651 (Area: 0) +(@CGUID+179, 15651, 530, 10120.49, -7380.654, 41.25549, 3.739351, 120, 0), -- 15651 (Area: 0) +(@CGUID+180, 15651, 530, 10222.12, -7377.514, 42.6799, 6.21672, 120, 0), -- 15651 (Area: 0) +(@CGUID+181, 15651, 530, 10287.61, -7510.908, 45.47846, 4.328416, 120, 0), -- 15651 (Area: 0) +(@CGUID+182, 15651, 530, 10307.25, -7600.326, 27.67019, 1.3225, 120, 0), -- 15651 (Area: 0) +(@CGUID+183, 15651, 530, 10261.34, -7483.148, 64.01847, 4.310963, 120, 0), -- 15651 (Area: 0) +(@CGUID+184, 15651, 530, 10222.87, -7613.924, 61.70162, 2.482553, 120, 0), -- 15651 (Area: 0) +(@CGUID+185, 15650, 530, 10279.31, -7324.253, 33.49329, 4.19599, 120, 0), -- Crazed Dragonhawk +(@CGUID+186, 15650, 530, 10192.26, -7320.828, 45.92649, 5.882011, 120, 0), -- 15650 (Area: 0) (Auras: 29119 - 29119) +(@CGUID+187, 15650, 530, 10171.51, -7404.468, 48.17466, 5.125631, 120, 0), -- 15650 (Area: 0) (Auras: 29119 - 29119) +(@CGUID+188, 15650, 530, 10225.49, -7453.733, 75.07253, 4.820997, 120, 0), -- 15650 (Area: 0) (Auras: 29119 - 29119) +(@CGUID+189, 15650, 530, 10095.22, -7399.66, 33.8582, 1.982334, 120, 0), -- 15650 (Area: 0) (Auras: 29119 - 29119) +(@CGUID+190, 15650, 530, 10089.92, -7352.991, 24.48084, 3.473843, 120, 0), -- 15650 (Area: 0) (Auras: 29119 - 29119) +(@CGUID+191, 15650, 530, 10304.47, -7592.876, 23.93329, 4.038411, 120, 0), -- 15650 (Area: 0) (Auras: 29119 - 29119) +(@CGUID+192, 15650, 530, 9840.896, -7878.327, 39.42878, 0.1114382, 120, 0), -- 15650 (Area: 3472) (Auras: 29119 - 29119) +(@CGUID+193, 15650, 530, 9008.495, -8056.905, 185.9688, 1.125495, 120, 0), -- 15650 (Area: 0) (Auras: 29119 - 29119) +(@CGUID+194, 15650, 530, 9009.816, -7833.289, 159.5567, 4.887175, 120, 0), -- 15650 (Area: 0) (Auras: 29119 - 29119) +(@CGUID+195, 15650, 530, 9015.15, -7667.337, 140.8466, 4.705554, 120, 0), -- 15650 (Area: 0) (Auras: 29119 - 29119) +(@CGUID+196, 15650, 530, 8824.381, -7819.187, 175.3332, 3.444827, 120, 0), -- 15650 (Area: 0) (Auras: 29119 - 29119) +(@CGUID+197, 15650, 530, 8785.419, -7913.549, 175.9667, 0.7577809, 120, 0), -- 15650 (Area: 3476) (Auras: 29119 - 29119) +(@CGUID+198, 15650, 530, 8848.306, -7942.777, 220.488, 5.064994, 120, 0), -- 15650 (Area: 3476) (Auras: 29119 - 29119) +(@CGUID+199, 15650, 530, 8333.768, -8008.462, 206.4037, 2.313344, 120, 0), -- 15650 (Area: 3476) (Auras: 29119 - 29119) +(@CGUID+200, 15650, 530, 8269.027, -8019.356, 224.7379, 5.511599, 120, 0), -- 15650 (Area: 3476) (Auras: 29119 - 29119) +(@CGUID+201, 15650, 530, 8213.844, -7896.639, 190.6529, 2.801, 120, 0), -- 15650 (Area: 3476) (Auras: 29119 - 29119) +(@CGUID+202, 15650, 530, 8216.283, -7952.173, 209.498, 1.65485, 120, 0), -- 15650 (Area: 3476) (Auras: 29119 - 29119) +(@CGUID+203, 16541, 530, 7244.089, -7125.762, 61.12453, 0.4067548, 120, 0), -- Ghostlands Guardian +(@CGUID+204, 16541, 530, 7182.639, -7079.073, 56.25724, 2.565634, 120, 0), -- 16541 (Area: 0) +(@CGUID+205, 16541, 530, 7168.553, -7095.772, 56.25724, 2.426008, 120, 0), -- 16541 (Area: 0) +(@CGUID+206, 14881, 530, 6908.589, -7112.601, 45.76462, 0.250855, 120, 0), -- Spider +(@CGUID+207, 14881, 530, 7087.832, -7109.549, 46.94461, 3.255385, 120, 0), -- 14881 (Area: 0) +(@CGUID+208, 14881, 530, 6913.161, -6316.999, 33.59887, 5.188184, 120, 0), -- 14881 (Area: 3514) +(@CGUID+209, 14881, 530, 7177.549, -7263.504, 45.25873, 4.996254, 120, 0), -- 14881 (Area: -1) (possible waypoints or random movement) +(@CGUID+210, 14881, 530, 7295.609, -7026.236, 48.24609, 0.2017749, 120, 0), -- 14881 (Area: -1) (possible waypoints or random movement) +(@CGUID+211, 14881, 530, 7120.973, -6668.307, 45.87799, 1.187052, 120, 0), -- 14881 (Area: 0) +(@CGUID+212, 33713, 530, 6896.669, -5765.082, -2.75388, 1.12993, 120, 0), -- 33713 (Area: 0) +(@CGUID+213, 33713, 530, 6853.869, -5738.312, -9.519895, 1.390244, 120, 0), -- 33713 (Area: 0) +(@CGUID+214, 33713, 530, 7173.716, -5696.389, -4.92298, 4.901935, 120, 0), -- 33713 (Area: 3491) +(@CGUID+215, 33713, 530, 7336.688, -5723.884, 0.3463151, 6.180531, 120, 0); -- 33713 (Area: 3491) + +-- Update movement +UPDATE `creature` SET `spawndist`=15, `MovementType`=1 WHERE `guid` BETWEEN @CGUID+0 AND @CGUID+215; +UPDATE `creature` SET `spawndist`=0, `MovementType`=0 WHERE `guid` IN (@CGUID+203, @CGUID+204, @CGUID+205, @CGUID+206); diff --git a/sql/updates/world/3.3.5/2016_05_24_00_world.sql b/sql/updates/world/3.3.5/2016_05_24_00_world.sql new file mode 100644 index 00000000000..b07a3288642 --- /dev/null +++ b/sql/updates/world/3.3.5/2016_05_24_00_world.sql @@ -0,0 +1,14 @@ +SET @OGUID:=85056; + +-- Add missing objects spawns in Ghostlands & Eversong Woods +DELETE FROM `gameobject` WHERE `guid` BETWEEN @OGUID+0 AND @OGUID+8; +INSERT INTO `gameobject` (`guid`, `id`, `map`, `spawnMask`, `phaseMask`, `position_x`, `position_y`, `position_z`, `orientation`, `rotation0`, `rotation1`, `rotation2`, `rotation3`, `spawntimesecs`, `animprogress`, `state`) VALUES +(@OGUID+0, 191460, 530, 1, 1, 6947.801, -7648.626, 131.9498, 0.2191041, 0, 0, 0.1093339, 0.9940051, 120, 255, 1), -- 191460 (Area: -1) -- Bonfire +(@OGUID+1, 181326, 530, 1, 1, 6772.437, -7350.587, 48.96166, 3.141593, 0, 0, 0, 1, 120, 255, 1), -- 181326 (Area: 3517) -- Bonfire +(@OGUID+2, 191460, 530, 1, 1, 6663.345, -7398.321, 57.63737, 2.111147, 0, 0, 0.8701838, 0.4927272, 120, 255, 1), -- 191460 (Area: 3517) -- Bonfire +(@OGUID+3, 181327, 530, 1, 1, 6610.271, -7352.757, 54.1082, 3.141593, 0, 0, 0, 1, 120, 255, 1), -- 181327 (Area: 3517) -- Cauldron +(@OGUID+4, 181362, 530, 1, 1, 6773.446, -7150.986, 48.90046, 3.141534, 0, 0, 0, 1, 120, 255, 1), -- 181362 (Area: 0) -- Campfire +(@OGUID+5, 181352, 530, 1, 1, 6785.604, -7192.486, 25.77958, 3.141593, 0, 0, 0, 1, 120, 255, 1), -- 181352 (Area: 0) -- Campfire +(@OGUID+6, 181319, 530, 1, 1, 7150.752, -6823.163, 43.91896, 3.141326, 0, 0, 0, 1, 120, 255, 1), -- 181319 (Area: 0) -- Campfire +(@OGUID+7, 191460, 530, 1, 1, 7410.167, -7966.508, 161.3317, 2.984498, 0, 0, 0.9969173, 0.07845911, 120, 255, 1), -- 191460 (Area: 3516) -- Bonfire +(@OGUID+8, 191460, 530, 1, 1, 7274.042, -7768.146, 150.1007, 0.7679439, 0, 0, 0.3746067, 0.9271838, 120, 255, 1); -- 191460 (Area: 3516) -- Bonfire diff --git a/sql/updates/world/3.3.5/2016_05_24_01_world.sql b/sql/updates/world/3.3.5/2016_05_24_01_world.sql new file mode 100644 index 00000000000..58ac4b0a40e --- /dev/null +++ b/sql/updates/world/3.3.5/2016_05_24_01_world.sql @@ -0,0 +1,5 @@ +DELETE FROM `spell_script_names` WHERE `ScriptName`='spell_dru_eclipse'; +INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES +(-48516, 'spell_dru_eclipse'); + +UPDATE `spell_proc_event` SET `Cooldown`=0 WHERE `entry`=-48516; -- set cooldown to 0, handled by a script diff --git a/sql/updates/world/3.3.5/2016_05_25_00_world.sql b/sql/updates/world/3.3.5/2016_05_25_00_world.sql new file mode 100644 index 00000000000..401f374d81a --- /dev/null +++ b/sql/updates/world/3.3.5/2016_05_25_00_world.sql @@ -0,0 +1,2 @@ +-- +UPDATE `spell_script_names` SET `spell_id`=67151 WHERE (`ScriptName`='spell_hun_t9_4p_bonus'); diff --git a/sql/updates/world/3.3.5/2016_05_25_01_world_335.sql b/sql/updates/world/3.3.5/2016_05_25_01_world_335.sql new file mode 100644 index 00000000000..603e8921a69 --- /dev/null +++ b/sql/updates/world/3.3.5/2016_05_25_01_world_335.sql @@ -0,0 +1,592 @@ +RENAME TABLE `game_graveyard_zone` TO `graveyard_zone`; +ALTER TABLE `graveyard_zone` CHANGE `id` `ID` MEDIUMINT(8) UNSIGNED NOT NULL DEFAULT '0'; +ALTER TABLE `graveyard_zone` CHANGE `ghost_zone` `GhostZone` MEDIUMINT(8) UNSIGNED NOT NULL DEFAULT '0'; +ALTER TABLE `graveyard_zone` CHANGE `faction` `Faction` SMALLINT(5) UNSIGNED NOT NULL DEFAULT '0'; +ALTER TABLE `graveyard_zone` ADD COLUMN `Comment` TEXT AFTER `Faction`; + +UPDATE `command` SET `help`='Syntax: .reload all area\n\nReload areatrigger_teleport, areatrigger_tavern, graveyard_zone tables.' WHERE `permission`=613; +UPDATE `command` SET `name`='reload graveyard_zone', `help`='Syntax: .reload graveyard_zone\nReload graveyard_zone table.' WHERE `permission`=645; + +UPDATE `graveyard_zone` SET `Comment`='Redridge Mountains - Redridge Mountains' WHERE `ID`=2; +UPDATE `graveyard_zone` SET `Comment`='Duskwood, Darkshire - Duskwood' WHERE `ID`=3; +UPDATE `graveyard_zone` SET `Comment`='Westfall, Sentinel Hill GY - Westfall' WHERE `ID`=4; +UPDATE `graveyard_zone` SET `Comment`='Loch Modan, Thelsamar - Loch Modan' WHERE `ID`=6; +UPDATE `graveyard_zone` SET `Comment`='Wetlands, Crossroads GY' WHERE `ID`=7; +UPDATE `graveyard_zone` SET `Comment`='Badlands, Graveyard NE' WHERE `ID`=8; +UPDATE `graveyard_zone` SET `Comment`='The Barrens, The Crossroads - Northern Barrens' WHERE `ID`=10; +UPDATE `graveyard_zone` SET `Comment`='Desolace, Ethel Rethor GY' WHERE `ID`=31; +UPDATE `graveyard_zone` SET `Comment`='Durotar, Razor Hill GY' WHERE `ID`=32; +UPDATE `graveyard_zone` SET `Comment`='Mulgore, Red Cloud Mesa GY - Mulgore' WHERE `ID`=34; +UPDATE `graveyard_zone` SET `Comment`='Darkshore, New Auberdine GY - Darkshore' WHERE `ID`=35; +UPDATE `graveyard_zone` SET `Comment`='Deadwind Pass, Morgan''s Plot' WHERE `ID`=36; +UPDATE `graveyard_zone` SET `Comment`='Silithus, Valor''s Rest - Silithus' WHERE `ID`=70; +UPDATE `graveyard_zone` SET `Comment`='Mulgore, Bloodhoof Village GY - Mulgore' WHERE `ID`=89; +UPDATE `graveyard_zone` SET `Comment`='Teldrassil, Darnassus GY' WHERE `ID`=90; +UPDATE `graveyard_zone` SET `Comment`='Teldrassil, Dolanaar GY - Teldrassil' WHERE `ID`=91; +UPDATE `graveyard_zone` SET `Comment`='Ashenvale, Astranaar GY - Ashenvale' WHERE `ID`=92; +UPDATE `graveyard_zone` SET `Comment`='Teldrassil, Aldrassil GY - Teldrassil' WHERE `ID`=93; +UPDATE `graveyard_zone` SET `Comment`='Tirisfal Glades, Deathknell - Tirisfal Glades' WHERE `ID`=94; +UPDATE `graveyard_zone` SET `Comment`='Tirisfal Glades, Undercity' WHERE `ID`=96; +UPDATE `graveyard_zone` SET `Comment`='Silverpine Forest, The Sepulcher - Silverpine Forest' WHERE `ID`=97; +UPDATE `graveyard_zone` SET `Comment`='Hillsbrad Foothills, Tarren Mill - Hillsbrad Foothills' WHERE `ID`=98; +UPDATE `graveyard_zone` SET `Comment`='Arathi Highlands, Eastern Road - Arathi Highlands' WHERE `ID`=99; +UPDATE `graveyard_zone` SET `Comment`='Dun Morogh, Anvilmar - Dun Morogh' WHERE `ID`=100; +UPDATE `graveyard_zone` SET `Comment`='Dun Morogh, Kharanos' WHERE `ID`=101; +UPDATE `graveyard_zone` SET `Comment`='Badlands, Kargath - Badlands' WHERE `ID`=103; +UPDATE `graveyard_zone` SET `Comment`='Redridge Mountains, Lakeshire' WHERE `ID`=104; +UPDATE `graveyard_zone` SET `Comment`='Elwynn Forest, Northshire - Elwynn Forest' WHERE `ID`=105; +UPDATE `graveyard_zone` SET `Comment`='Elwynn Forest, Goldshire - Elwynn Forest' WHERE `ID`=106; +UPDATE `graveyard_zone` SET `Comment`='Elwynn Forest, Stormwind' WHERE `ID`=107; +UPDATE `graveyard_zone` SET `Comment`='Swamp of Sorrows, Stonard GY' WHERE `ID`=108; +UPDATE `graveyard_zone` SET `Comment`='Stranglethorn Vale, Booty Bay GY - Stranglethorn Vale' WHERE `ID`=109; +UPDATE `graveyard_zone` SET `Comment`='Teldrassil, Rut''theran Village GY - Teldrassil' WHERE `ID`=129; +UPDATE `graveyard_zone` SET `Comment`='Hillsbrad Foothills, Southshore' WHERE `ID`=149; +UPDATE `graveyard_zone` SET `Comment`='Alterac Valley, Snowfall Graveyard (Mid) - Alterac Valley' WHERE `ID`=169; +UPDATE `graveyard_zone` SET `Comment`='Dustwallow Marsh, Theramore Isle GY - Dustwallow Marsh' WHERE `ID`=189; +UPDATE `graveyard_zone` SET `Comment`='Tanaris, Gadgetzan GY' WHERE `ID`=209; +UPDATE `graveyard_zone` SET `Comment`='The Barrens, Camp Taurajo GY - Southern Barrens' WHERE `ID`=229; +UPDATE `graveyard_zone` SET `Comment`='The Barrens, Ratchet' WHERE `ID`=249; +UPDATE `graveyard_zone` SET `Comment`='Tirisfal Glades, Brill - Tirisfal Glades' WHERE `ID`=289; +UPDATE `graveyard_zone` SET `Comment`='Feralas, New Feathermoon Stronghold GY (A) - Feralas' WHERE `ID`=309; +UPDATE `graveyard_zone` SET `Comment`='Feralas, Camp Mojache GY (H) - Feralas' WHERE `ID`=310; +UPDATE `graveyard_zone` SET `Comment`='Thousand Needles, Splithoof Heights GY (MOVED) - Thousand Needles' WHERE `ID`=329; +UPDATE `graveyard_zone` SET `Comment`='The Hinterlands, Aerie Peak - The Hinterlands' WHERE `ID`=349; +UPDATE `graveyard_zone` SET `Comment`='Azshara, Northern Azshara GY - Azshara' WHERE `ID`=369; +UPDATE `graveyard_zone` SET `Comment`='Blasted Lands, Dreadmaul Hold GY - Blasted Lands' WHERE `ID`=370; +UPDATE `graveyard_zone` SET `Comment`='Blasted Lands, Dreadmaul Hold GY - Swamp of Sorrows' WHERE `ID`=370; +UPDATE `graveyard_zone` SET `Comment`='Stranglethorn Vale, Northern Stranglethorn GY - Stranglethorn Vale' WHERE `ID`=389; +UPDATE `graveyard_zone` SET `Comment`='Stonetalon Mountains, Webwinder Path GY - Stonetalon Mountains' WHERE `ID`=409; +UPDATE `graveyard_zone` SET `Comment`='Felwood, Morlos''Aran - Felwood' WHERE `ID`=449; +UPDATE `graveyard_zone` SET `Comment`='Un''Goro Crater, The Marshlands - Un''Goro Crater' WHERE `ID`=450; +UPDATE `graveyard_zone` SET `Comment`='Darkshore, Twilight Vale GY' WHERE `ID`=469; +UPDATE `graveyard_zone` SET `Comment`='Wetlands, Baradin Bay GY - Wetlands' WHERE `ID`=489; +UPDATE `graveyard_zone` SET `Comment`='Western Plaguelands, Chillwind Camp - Western Plaguelands' WHERE `ID`=509; +UPDATE `graveyard_zone` SET `Comment`='Eastern Plaguelands, Pestilent Scar - Eastern Plaguelands' WHERE `ID`=510; +UPDATE `graveyard_zone` SET `Comment`='Winterspring, Everlook GY - Winterspring' WHERE `ID`=511; +UPDATE `graveyard_zone` SET `Comment`='Ashenvale, Kargathia GY' WHERE `ID`=512; +UPDATE `graveyard_zone` SET `Comment`='Programmer Isle - Programmer Isle' WHERE `ID`=529; +UPDATE `graveyard_zone` SET `Comment`='Western Plaguelands, Bulwark' WHERE `ID`=569; +UPDATE `graveyard_zone` SET `Comment`='Azshara, (Overlooks) The Shattered Strand GY - Azshara' WHERE `ID`=609; +UPDATE `graveyard_zone` SET `Comment`='Alterac Valley, Horde Safe - Alterac Valley' WHERE `ID`=610; +UPDATE `graveyard_zone` SET `Comment`='Alterac Valley, Alliance Safe - Alterac Valley' WHERE `ID`=611; +UPDATE `graveyard_zone` SET `Comment`='TEST for GM Client Only - Do Not Bug - Tirisfal Glades' WHERE `ID`=629; +UPDATE `graveyard_zone` SET `Comment`='Azshara, Bitter Reaches GY - Azshara' WHERE `ID`=630; +UPDATE `graveyard_zone` SET `Comment`='Dustwallow Marsh, Brackenwall Village GY - Dustwallow Marsh' WHERE `ID`=631; +UPDATE `graveyard_zone` SET `Comment`='Moonglade GY - Moonglade' WHERE `ID`=633; +UPDATE `graveyard_zone` SET `Comment`='Eastern Plaguelands, Darrowshire - Eastern Plaguelands' WHERE `ID`=634; +UPDATE `graveyard_zone` SET `Comment`='Felwood, Irontree Woods - Felwood' WHERE `ID`=635; +UPDATE `graveyard_zone` SET `Comment`='Searing Gorge, Thorium Point - Searing Gorge' WHERE `ID`=636; +UPDATE `graveyard_zone` SET `Comment`='Durotar, Sen''jin Village GY - Durotar' WHERE `ID`=649; +UPDATE `graveyard_zone` SET `Comment`='Programmer Isle, Bucklers Cemetery 2 - Programmer Isle' WHERE `ID`=669; +UPDATE `graveyard_zone` SET `Comment`='Programmer Isle, Bucklers Cemetery 1 - Programmer Isle' WHERE `ID`=670; +UPDATE `graveyard_zone` SET `Comment`='Programmer Isle, Bucklers Cemetery 3 - Programmer Isle' WHERE `ID`=671; +UPDATE `graveyard_zone` SET `Comment`='Alterac Valley, Stormpike Graveyard (Hi) - Alterac Valley' WHERE `ID`=689; +UPDATE `graveyard_zone` SET `Comment`='Durotar, Valley of Trials GY - Durotar' WHERE `ID`=709; +UPDATE `graveyard_zone` SET `Comment`='Alterac Valley, PvP Alliance Choke Graveyard (A-choke) - Alterac Valley' WHERE `ID`=729; +UPDATE `graveyard_zone` SET `Comment`='Alterac Valley, PvP Horde Choke Graveyard (H-choke) - Alterac Valley' WHERE `ID`=749; +UPDATE `graveyard_zone` SET `Comment`='Alterac Valley, Frostwolf Relief Hut (H-base) - Alterac Valley' WHERE `ID`=750; +UPDATE `graveyard_zone` SET `Comment`='Alterac Valley, Stormpike Aid Station (A-base) - Alterac Valley' WHERE `ID`=751; +UPDATE `graveyard_zone` SET `Comment`='Warsong Gulch - Alliance Enter Loc - Warsong Gulch' WHERE `ID`=769; +UPDATE `graveyard_zone` SET `Comment`='Warsong Gulch - Horde Enter Loc - Warsong Gulch' WHERE `ID`=770; +UPDATE `graveyard_zone` SET `Comment`='Warsong Gulch - Alliance Rez Loc - Warsong Gulch' WHERE `ID`=771; +UPDATE `graveyard_zone` SET `Comment`='Warsong Gulch - Horde Rez Loc - Warsong Gulch' WHERE `ID`=772; +UPDATE `graveyard_zone` SET `Comment`='The Hinterlands, The Overlook Cliffs - The Hinterlands' WHERE `ID`=789; +UPDATE `graveyard_zone` SET `Comment`='Warsong Gulch - Horde Exit Loc - Warsong Gulch' WHERE `ID`=809; +UPDATE `graveyard_zone` SET `Comment`='Warsong Gulch - Alliance Exit Loc - Warsong Gulch' WHERE `ID`=810; +UPDATE `graveyard_zone` SET `Comment`='Alterac Valley, Alliance Exit' WHERE `ID`=829; +UPDATE `graveyard_zone` SET `Comment`='Alterac Valley, Horde Exit - Alterac Valley' WHERE `ID`=830; +UPDATE `graveyard_zone` SET `Comment`='Feralas, Dire Maul Stonemaul Hold GY - Feralas' WHERE `ID`=849; +UPDATE `graveyard_zone` SET `Comment`='Durotar, Northern Durotar GY' WHERE `ID`=850; +UPDATE `graveyard_zone` SET `Comment`='Mulgore, Thunder Bluff GY' WHERE `ID`=851; +UPDATE `graveyard_zone` SET `Comment`='Dun Morogh, Gates of Ironforge - Dun Morogh' WHERE `ID`=852; +UPDATE `graveyard_zone` SET `Comment`='Elwynn Forest, Eastvale Logging Camp' WHERE `ID`=854; +UPDATE `graveyard_zone` SET `Comment`='Western Plaguelands, Caer Darrow - Western Plaguelands' WHERE `ID`=869; +UPDATE `graveyard_zone` SET `Comment`='Arathi Basin - Horde Entrance - Arathi Basin' WHERE `ID`=889; +UPDATE `graveyard_zone` SET `Comment`='Arathi Basin - Alliance Entrance - Arathi Basin' WHERE `ID`=890; +UPDATE `graveyard_zone` SET `Comment`='Arathi Basin - Horde Exit - Arathi Basin' WHERE `ID`=891; +UPDATE `graveyard_zone` SET `Comment`='Arathi Basin - Alliance Exit - Arathi Basin' WHERE `ID`=892; +UPDATE `graveyard_zone` SET `Comment`='Arathi Basin - Graveyard, H-Mid (Farm) - Arathi Basin' WHERE `ID`=893; +UPDATE `graveyard_zone` SET `Comment`='Arathi Basin - Graveyard, Mid (Blacksmith) - Arathi Basin' WHERE `ID`=894; +UPDATE `graveyard_zone` SET `Comment`='Arathi Basin - Graveyard, A-Mid (Stables) - Arathi Basin' WHERE `ID`=895; +UPDATE `graveyard_zone` SET `Comment`='Arathi Basin - Graveyard, ALT-N (Gold Mine) - Arathi Basin' WHERE `ID`=896; +UPDATE `graveyard_zone` SET `Comment`='Arathi Basin - Graveyard, ALT-S (Lumber Mill) - Arathi Basin' WHERE `ID`=897; +UPDATE `graveyard_zone` SET `Comment`='Arathi Basin - Graveyard, A-Base (Trollbane Hall) - Arathi Basin' WHERE `ID`=898; +UPDATE `graveyard_zone` SET `Comment`='Arathi Basin - Graveyard, H-Base (Defiler''s Den) - Arathi Basin' WHERE `ID`=899; +UPDATE `graveyard_zone` SET `Comment`='Eastern Plaguelands, Blackwood Lake - Eastern Plaguelands' WHERE `ID`=909; +UPDATE `graveyard_zone` SET `Comment`='Eastern Plaguelands, Blackwood Lake - Stratholme' WHERE `ID`=909; +UPDATE `graveyard_zone` SET `Comment`='Silithus, Cenarion Hold - Ruins of Ahn''Qiraj' WHERE `ID`=910; +UPDATE `graveyard_zone` SET `Comment`='Silithus, Cenarion Hold - Silithus' WHERE `ID`=910; +UPDATE `graveyard_zone` SET `Comment`='Duskwood, Ravenhill - Duskwood' WHERE `ID`=911; +UPDATE `graveyard_zone` SET `Comment`='Eversong Woods, Sunstrider Isle - Eversong Woods' WHERE `ID`=912; +UPDATE `graveyard_zone` SET `Comment`='Silithus, Scarab Wall (AQ Only)' WHERE `ID`=913; +UPDATE `graveyard_zone` SET `Comment`='Eversong Woods, Farstrider Lodge GY - Eversong Woods' WHERE `ID`=914; +UPDATE `graveyard_zone` SET `Comment`='Ghostlands, Tranquillien - Ghostlands' WHERE `ID`=915; +UPDATE `graveyard_zone` SET `Comment`='Ghostlands, Sanctum - Ghostlands' WHERE `ID`=916; +UPDATE `graveyard_zone` SET `Comment`='Ghostlands, Amani Pass' WHERE `ID`=917; +UPDATE `graveyard_zone` SET `Comment`='Azuremyst Isle, Ammen Vale' WHERE `ID`=918; +UPDATE `graveyard_zone` SET `Comment`='Hellfire Peninsula, Thrallmar' WHERE `ID`=919; +UPDATE `graveyard_zone` SET `Comment`='Hellfire Peninsula, Honor Hold' WHERE `ID`=920; +UPDATE `graveyard_zone` SET `Comment`='Eversong Woods, Silvermoon City' WHERE `ID`=921; +UPDATE `graveyard_zone` SET `Comment`='Azuremyst, Azure Watch GY - Azuremyst Isle' WHERE `ID`=923; +UPDATE `graveyard_zone` SET `Comment`='Azuremyst, Stillpine GY' WHERE `ID`=924; +UPDATE `graveyard_zone` SET `Comment`='Bloodmyst, Blood Watch GY - Bloodmyst Isle' WHERE `ID`=925; +UPDATE `graveyard_zone` SET `Comment`='Bloodmyst, Wilderness GY' WHERE `ID`=926; +UPDATE `graveyard_zone` SET `Comment`='Eastern Plaguelands, Graveyard CG Tower - Eastern Plaguelands' WHERE `ID`=927; +UPDATE `graveyard_zone` SET `Comment`='Zangarmarsh, Zabra''jin GY' WHERE `ID`=928; +UPDATE `graveyard_zone` SET `Comment`='Nagrand, SE Graveyard - Nagrand' WHERE `ID`=930; +UPDATE `graveyard_zone` SET `Comment`='Hellfire Peninsula, Temple - Hellfire Peninsula' WHERE `ID`=933; +UPDATE `graveyard_zone` SET `Comment`='Hellfire Peninsula, Falcon Watch - Hellfire Peninsula' WHERE `ID`=934; +UPDATE `graveyard_zone` SET `Comment`='Hellfire Peninsula, Corpse Location 001 - Twisting Nether' WHERE `ID`=942; +UPDATE `graveyard_zone` SET `Comment`='Hellfire Peninsula, Corpse Location 002 - Twisting Nether' WHERE `ID`=943; +UPDATE `graveyard_zone` SET `Comment`='Hellfire Peninsula, Corpse Location 003 - Twisting Nether' WHERE `ID`=944; +UPDATE `graveyard_zone` SET `Comment`='Hellfire Peninsula, Corpse Location 005 - Twisting Nether' WHERE `ID`=945; +UPDATE `graveyard_zone` SET `Comment`='Hellfire Peninsula, Corpse Location 006 - Twisting Nether' WHERE `ID`=946; +UPDATE `graveyard_zone` SET `Comment`='Hellfire Peninsula, Corpse Location 007 - Twisting Nether' WHERE `ID`=947; +UPDATE `graveyard_zone` SET `Comment`='Hellfire Peninsula, Corpse Location 008 - Twisting Nether' WHERE `ID`=948; +UPDATE `graveyard_zone` SET `Comment`='Hellfire Peninsula, Corpse Location 009 - Twisting Nether' WHERE `ID`=949; +UPDATE `graveyard_zone` SET `Comment`='Hellfire Peninsula, Corpse Location 010 - Twisting Nether' WHERE `ID`=950; +UPDATE `graveyard_zone` SET `Comment`='Hellfire Peninsula, Corpse Location 011 - Twisting Nether' WHERE `ID`=951; +UPDATE `graveyard_zone` SET `Comment`='Hellfire Peninsula, Corpse Location 012 - Twisting Nether' WHERE `ID`=952; +UPDATE `graveyard_zone` SET `Comment`='Hellfire Peninsula, Corpse Location 013 - Twisting Nether' WHERE `ID`=953; +UPDATE `graveyard_zone` SET `Comment`='Hellfire Peninsula, Corpse Location 014 - Twisting Nether' WHERE `ID`=954; +UPDATE `graveyard_zone` SET `Comment`='Hellfire Peninsula, Corpse Location 015 - Twisting Nether' WHERE `ID`=955; +UPDATE `graveyard_zone` SET `Comment`='Hellfire Peninsula, Corpse Location 016 - Twisting Nether' WHERE `ID`=956; +UPDATE `graveyard_zone` SET `Comment`='Hellfire Peninsula, Corpse Location 017 - Twisting Nether' WHERE `ID`=957; +UPDATE `graveyard_zone` SET `Comment`='Hellfire Peninsula, Corpse Location 018 - Twisting Nether' WHERE `ID`=958; +UPDATE `graveyard_zone` SET `Comment`='Hellfire Peninsula, Corpse Location 019 - Twisting Nether' WHERE `ID`=959; +UPDATE `graveyard_zone` SET `Comment`='Hellfire Peninsula, Corpse Location 020 - Twisting Nether' WHERE `ID`=960; +UPDATE `graveyard_zone` SET `Comment`='Hellfire Peninsula, Corpse Location 021 - Twisting Nether' WHERE `ID`=961; +UPDATE `graveyard_zone` SET `Comment`='Hellfire Peninsula, Corpse Location 022 - Twisting Nether' WHERE `ID`=962; +UPDATE `graveyard_zone` SET `Comment`='Hellfire Peninsula, Corpse Location 023 - Twisting Nether' WHERE `ID`=963; +UPDATE `graveyard_zone` SET `Comment`='Hellfire Peninsula, Corpse Location 024 - Twisting Nether' WHERE `ID`=964; +UPDATE `graveyard_zone` SET `Comment`='Hellfire Peninsula, Corpse Location 025 - Twisting Nether' WHERE `ID`=965; +UPDATE `graveyard_zone` SET `Comment`='Hellfire Peninsula, Corpse Location 026 - Twisting Nether' WHERE `ID`=966; +UPDATE `graveyard_zone` SET `Comment`='Hellfire Peninsula, Corpse Location 027 - Twisting Nether' WHERE `ID`=967; +UPDATE `graveyard_zone` SET `Comment`='Hellfire Peninsula, Corpse Location 028 - Twisting Nether' WHERE `ID`=968; +UPDATE `graveyard_zone` SET `Comment`='Zangarmarsh, PvP GY' WHERE `ID`=969; +UPDATE `graveyard_zone` SET `Comment`='Zangarmarsh, Telredor GY' WHERE `ID`=970; +UPDATE `graveyard_zone` SET `Comment`='Zangarmarsh, Corpse Location 006 - Twisting Nether' WHERE `ID`=972; +UPDATE `graveyard_zone` SET `Comment`='Zangarmarsh, Cenarion GY - Zangarmarsh' WHERE `ID`=973; +UPDATE `graveyard_zone` SET `Comment`='Zangarmarsh, Corpse Location 001 - Twisting Nether' WHERE `ID`=974; +UPDATE `graveyard_zone` SET `Comment`='Zangarmarsh, Corpse Location 002 - Twisting Nether' WHERE `ID`=975; +UPDATE `graveyard_zone` SET `Comment`='Zangarmarsh, Corpse Location 003 - Twisting Nether' WHERE `ID`=976; +UPDATE `graveyard_zone` SET `Comment`='Zangarmarsh, Corpse Location 004 - Twisting Nether' WHERE `ID`=977; +UPDATE `graveyard_zone` SET `Comment`='Zangarmarsh, Corpse Location 008 - Twisting Nether' WHERE `ID`=978; +UPDATE `graveyard_zone` SET `Comment`='Zangarmarsh, Corpse Location 005 - Twisting Nether' WHERE `ID`=979; +UPDATE `graveyard_zone` SET `Comment`='Zangarmarsh, Corpse Location 007 - Twisting Nether' WHERE `ID`=980; +UPDATE `graveyard_zone` SET `Comment`='Zangarmarsh, Corpse Location 009 - Twisting Nether' WHERE `ID`=981; +UPDATE `graveyard_zone` SET `Comment`='Zangarmarsh, Corpse Location 011 - Twisting Nether' WHERE `ID`=982; +UPDATE `graveyard_zone` SET `Comment`='Zangarmarsh, Corpse Location 010 - Twisting Nether' WHERE `ID`=983; +UPDATE `graveyard_zone` SET `Comment`='Zangarmarsh, Corpse Location 012 - Twisting Nether' WHERE `ID`=984; +UPDATE `graveyard_zone` SET `Comment`='Zangarmarsh, Corpse Location 013 - Twisting Nether' WHERE `ID`=985; +UPDATE `graveyard_zone` SET `Comment`='Zangarmarsh, Corpse Location 014 - Twisting Nether' WHERE `ID`=986; +UPDATE `graveyard_zone` SET `Comment`='Zangarmarsh, Corpse Location 016 - Twisting Nether' WHERE `ID`=987; +UPDATE `graveyard_zone` SET `Comment`='Zangarmarsh, Corpse Location 015 - Twisting Nether' WHERE `ID`=988; +UPDATE `graveyard_zone` SET `Comment`='Zangarmarsh, Corpse Location 017 - Twisting Nether' WHERE `ID`=989; +UPDATE `graveyard_zone` SET `Comment`='Zangarmarsh, Corpse Location 018 - Twisting Nether' WHERE `ID`=990; +UPDATE `graveyard_zone` SET `Comment`='Zangarmarsh, Corpse Location 019 - Twisting Nether' WHERE `ID`=991; +UPDATE `graveyard_zone` SET `Comment`='Nagrand, Northwind Cleft - Nagrand' WHERE `ID`=992; +UPDATE `graveyard_zone` SET `Comment`='Nagrand, Halaa GY - Nagrand' WHERE `ID`=993; +UPDATE `graveyard_zone` SET `Comment`='Terokkar Forest, Shattrath GY' WHERE `ID`=994; +UPDATE `graveyard_zone` SET `Comment`='Terokkar Forest, Wilderness GY - Terokkar Forest' WHERE `ID`=995; +UPDATE `graveyard_zone` SET `Comment`='Nagrand, Corpse Location 001 - Twisting Nether' WHERE `ID`=999; +UPDATE `graveyard_zone` SET `Comment`='Nagrand, Corpse Location 002 - Twisting Nether' WHERE `ID`=1000; +UPDATE `graveyard_zone` SET `Comment`='Nagrand, Corpse Location 003 - Twisting Nether' WHERE `ID`=1001; +UPDATE `graveyard_zone` SET `Comment`='Nagrand, Corpse Location 004 - Twisting Nether' WHERE `ID`=1002; +UPDATE `graveyard_zone` SET `Comment`='Nagrand, Corpse Location 005 - Twisting Nether' WHERE `ID`=1003; +UPDATE `graveyard_zone` SET `Comment`='Nagrand, Corpse Location 006 - Twisting Nether' WHERE `ID`=1004; +UPDATE `graveyard_zone` SET `Comment`='Nagrand, Corpse Location 007 - Twisting Nether' WHERE `ID`=1005; +UPDATE `graveyard_zone` SET `Comment`='Nagrand, Corpse Location 008 - Twisting Nether' WHERE `ID`=1006; +UPDATE `graveyard_zone` SET `Comment`='Nagrand, Corpse Location 009 - Twisting Nether' WHERE `ID`=1007; +UPDATE `graveyard_zone` SET `Comment`='Nagrand, Corpse Location 010 - Twisting Nether' WHERE `ID`=1008; +UPDATE `graveyard_zone` SET `Comment`='Nagrand, Corpse Location 011 - Twisting Nether' WHERE `ID`=1009; +UPDATE `graveyard_zone` SET `Comment`='Nagrand, Corpse Location 012 - Twisting Nether' WHERE `ID`=1010; +UPDATE `graveyard_zone` SET `Comment`='Nagrand, Corpse Location 013 - Twisting Nether' WHERE `ID`=1011; +UPDATE `graveyard_zone` SET `Comment`='Nagrand, Corpse Location 014 - Twisting Nether' WHERE `ID`=1012; +UPDATE `graveyard_zone` SET `Comment`='Terokkar Forest, Corpse Location 001 - Twisting Nether' WHERE `ID`=1013; +UPDATE `graveyard_zone` SET `Comment`='Terokkar Forest, Corpse Location 002 - Twisting Nether' WHERE `ID`=1014; +UPDATE `graveyard_zone` SET `Comment`='Terokkar Forest, Corpse Location 003 - Twisting Nether' WHERE `ID`=1015; +UPDATE `graveyard_zone` SET `Comment`='Terokkar Forest, Corpse Location 004 - Twisting Nether' WHERE `ID`=1016; +UPDATE `graveyard_zone` SET `Comment`='Terokkar Forest, Corpse Location 005 - Twisting Nether' WHERE `ID`=1017; +UPDATE `graveyard_zone` SET `Comment`='Terokkar Forest, Corpse Location 006 - Twisting Nether' WHERE `ID`=1018; +UPDATE `graveyard_zone` SET `Comment`='Terokkar Forest, Corpse Location 007 - Twisting Nether' WHERE `ID`=1019; +UPDATE `graveyard_zone` SET `Comment`='Terokkar Forest, Corpse Location 008 - Twisting Nether' WHERE `ID`=1020; +UPDATE `graveyard_zone` SET `Comment`='Terokkar Forest, Corpse Location 009 - Twisting Nether' WHERE `ID`=1021; +UPDATE `graveyard_zone` SET `Comment`='Terokkar Forest, Corpse Location 010 - Twisting Nether' WHERE `ID`=1022; +UPDATE `graveyard_zone` SET `Comment`='Terokkar Forest, Corpse Location 011 - Twisting Nether' WHERE `ID`=1023; +UPDATE `graveyard_zone` SET `Comment`='Shadowmoon, Corpse Location 001 - Twisting Nether' WHERE `ID`=1024; +UPDATE `graveyard_zone` SET `Comment`='Shadowmoon, Corpse Location 002 - Twisting Nether' WHERE `ID`=1025; +UPDATE `graveyard_zone` SET `Comment`='Shadowmoon, Corpse Location 003 - Twisting Nether' WHERE `ID`=1026; +UPDATE `graveyard_zone` SET `Comment`='Shadowmoon, Corpse Location 004 - Twisting Nether' WHERE `ID`=1027; +UPDATE `graveyard_zone` SET `Comment`='Terokkar Forest, Corpse Location 016 - Twisting Nether' WHERE `ID`=1028; +UPDATE `graveyard_zone` SET `Comment`='Terokkar Forest, Corpse Location 017 - Twisting Nether' WHERE `ID`=1029; +UPDATE `graveyard_zone` SET `Comment`='Terokkar Forest, Corpse Location 018 - Twisting Nether' WHERE `ID`=1030; +UPDATE `graveyard_zone` SET `Comment`='Terokkar Forest, Corpse Location 019 - Twisting Nether' WHERE `ID`=1031; +UPDATE `graveyard_zone` SET `Comment`='Terokkar Forest, Corpse Location 020 - Twisting Nether' WHERE `ID`=1032; +UPDATE `graveyard_zone` SET `Comment`='Terokkar Forest, Corpse Location 021 - Twisting Nether' WHERE `ID`=1033; +UPDATE `graveyard_zone` SET `Comment`='Terokkar Forest, Corpse Location 022 - Twisting Nether' WHERE `ID`=1034; +UPDATE `graveyard_zone` SET `Comment`='Terokkar Forest, Corpse Location 023 - Twisting Nether' WHERE `ID`=1035; +UPDATE `graveyard_zone` SET `Comment`='Nagrand, Portal Plateau - Nagrand' WHERE `ID`=1037; +UPDATE `graveyard_zone` SET `Comment`='Nagrand, Elemental Plateau - Nagrand' WHERE `ID`=1038; +UPDATE `graveyard_zone` SET `Comment`='Nagrand, SW Graveyard - Nagrand' WHERE `ID`=1039; +UPDATE `graveyard_zone` SET `Comment`='Hellfire Peninsula, Throne of Kil''Jaedan - Hellfire Peninsula' WHERE `ID`=1040; +UPDATE `graveyard_zone` SET `Comment`='Hellfire Peninsula, Dark Portal - Hellfire Peninsula' WHERE `ID`=1041; +UPDATE `graveyard_zone` SET `Comment`='Terokkar Forest, Bone Wastes GY' WHERE `ID`=1042; +UPDATE `graveyard_zone` SET `Comment`='Zangarmarsh, Harborage GY - Zangarmarsh' WHERE `ID`=1043; +UPDATE `graveyard_zone` SET `Comment`='Zangarmarsh, Sporeggar GY - Zangarmarsh' WHERE `ID`=1044; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm, Stormspire GY - Netherstorm' WHERE `ID`=1045; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm, Area 52 GY - Netherstorm' WHERE `ID`=1046; +UPDATE `graveyard_zone` SET `Comment`='Shadowmoon Valley, Shadowmoon Village GY - Shadowmoon Valley' WHERE `ID`=1047; +UPDATE `graveyard_zone` SET `Comment`='Shadowmoon Valley, Wildhammer GY - Shadowmoon Valley' WHERE `ID`=1048; +UPDATE `graveyard_zone` SET `Comment`='Blade''s Edge, Sylvanaar GY - Blade''s Edge Mountains' WHERE `ID`=1049; +UPDATE `graveyard_zone` SET `Comment`='Blade''s Edge, Thunderlord GY - Blade''s Edge Mountains' WHERE `ID`=1050; +UPDATE `graveyard_zone` SET `Comment`='Terokkar Forest, Skettis GY - Terokkar Forest' WHERE `ID`=1051; +UPDATE `graveyard_zone` SET `Comment`='Shadowmoon, Corpse Location 005 - Twisting Nether' WHERE `ID`=1052; +UPDATE `graveyard_zone` SET `Comment`='Shadowmoon, Corpse Location 006 - Twisting Nether' WHERE `ID`=1053; +UPDATE `graveyard_zone` SET `Comment`='Shadowmoon, Corpse Location 007 - Twisting Nether' WHERE `ID`=1054; +UPDATE `graveyard_zone` SET `Comment`='Shadowmoon, Corpse Location 008 - Twisting Nether' WHERE `ID`=1055; +UPDATE `graveyard_zone` SET `Comment`='Shadowmoon, Corpse Location 009 - Twisting Nether' WHERE `ID`=1056; +UPDATE `graveyard_zone` SET `Comment`='Shadowmoon, Corpse Location 010 - Twisting Nether' WHERE `ID`=1057; +UPDATE `graveyard_zone` SET `Comment`='Shadowmoon, Corpse Location 011 - Twisting Nether' WHERE `ID`=1058; +UPDATE `graveyard_zone` SET `Comment`='Shadowmoon, Corpse Location 012 - Twisting Nether' WHERE `ID`=1059; +UPDATE `graveyard_zone` SET `Comment`='Shadowmoon, Corpse Location 013 - Twisting Nether' WHERE `ID`=1060; +UPDATE `graveyard_zone` SET `Comment`='Shadowmoon, Corpse Location 014 - Twisting Nether' WHERE `ID`=1061; +UPDATE `graveyard_zone` SET `Comment`='Shadowmoon, Corpse Location 015 - Twisting Nether' WHERE `ID`=1062; +UPDATE `graveyard_zone` SET `Comment`='Shadowmoon, Corpse Location 016 - Twisting Nether' WHERE `ID`=1063; +UPDATE `graveyard_zone` SET `Comment`='Shadowmoon, Corpse Location 017 - Twisting Nether' WHERE `ID`=1064; +UPDATE `graveyard_zone` SET `Comment`='Shadowmoon, Corpse Location 018 - Twisting Nether' WHERE `ID`=1065; +UPDATE `graveyard_zone` SET `Comment`='Shadowmoon, Corpse Location 019 - Twisting Nether' WHERE `ID`=1066; +UPDATE `graveyard_zone` SET `Comment`='Shadowmoon, Corpse Location 020 - Twisting Nether' WHERE `ID`=1067; +UPDATE `graveyard_zone` SET `Comment`='Shadowmoon, Corpse Location 021 - Twisting Nether' WHERE `ID`=1068; +UPDATE `graveyard_zone` SET `Comment`='Shadowmoon, Corpse Location 022 - Twisting Nether' WHERE `ID`=1069; +UPDATE `graveyard_zone` SET `Comment`='Shadowmoon, Corpse Location 023 - Twisting Nether' WHERE `ID`=1070; +UPDATE `graveyard_zone` SET `Comment`='Blade''s Edge, Corpse Location 000 - Twisting Nether' WHERE `ID`=1072; +UPDATE `graveyard_zone` SET `Comment`='Blade''s Edge, Corpse Location 001 - Twisting Nether' WHERE `ID`=1073; +UPDATE `graveyard_zone` SET `Comment`='Blade''s Edge, Corpse Location 002 - Twisting Nether' WHERE `ID`=1074; +UPDATE `graveyard_zone` SET `Comment`='Blade''s Edge, Corpse Location 003 - Twisting Nether' WHERE `ID`=1075; +UPDATE `graveyard_zone` SET `Comment`='Blade''s Edge, Corpse Location 004 - Twisting Nether' WHERE `ID`=1076; +UPDATE `graveyard_zone` SET `Comment`='Blade''s Edge, Corpse Location 005 - Twisting Nether' WHERE `ID`=1077; +UPDATE `graveyard_zone` SET `Comment`='Blade''s Edge, Corpse Location 006 - Twisting Nether' WHERE `ID`=1078; +UPDATE `graveyard_zone` SET `Comment`='Blade''s Edge, Corpse Location 007 - Twisting Nether' WHERE `ID`=1079; +UPDATE `graveyard_zone` SET `Comment`='Blade''s Edge, Corpse Location 008 - Twisting Nether' WHERE `ID`=1080; +UPDATE `graveyard_zone` SET `Comment`='Blade''s Edge, Corpse Location 009 - Twisting Nether' WHERE `ID`=1081; +UPDATE `graveyard_zone` SET `Comment`='Blade''s Edge, Corpse Location 010 - Twisting Nether' WHERE `ID`=1082; +UPDATE `graveyard_zone` SET `Comment`='Blade''s Edge, Corpse Location 011 - Twisting Nether' WHERE `ID`=1083; +UPDATE `graveyard_zone` SET `Comment`='Blade''s Edge, Corpse Location 012 - Twisting Nether' WHERE `ID`=1084; +UPDATE `graveyard_zone` SET `Comment`='Blade''s Edge, Corpse Location 013 - Twisting Nether' WHERE `ID`=1085; +UPDATE `graveyard_zone` SET `Comment`='Blade''s Edge, Corpse Location 014 - Twisting Nether' WHERE `ID`=1086; +UPDATE `graveyard_zone` SET `Comment`='Blade''s Edge, Corpse Location 015 - Twisting Nether' WHERE `ID`=1087; +UPDATE `graveyard_zone` SET `Comment`='Blade''s Edge, Corpse Location 016 - Twisting Nether' WHERE `ID`=1088; +UPDATE `graveyard_zone` SET `Comment`='Blade''s Edge, Corpse Location 017 - Twisting Nether' WHERE `ID`=1089; +UPDATE `graveyard_zone` SET `Comment`='Blade''s Edge, Corpse Location 018 - Twisting Nether' WHERE `ID`=1090; +UPDATE `graveyard_zone` SET `Comment`='Blade''s Edge, Corpse Location 019 - Twisting Nether' WHERE `ID`=1091; +UPDATE `graveyard_zone` SET `Comment`='Blade''s Edge, Corpse Location 020 - Twisting Nether' WHERE `ID`=1092; +UPDATE `graveyard_zone` SET `Comment`='Blade''s Edge, Corpse Location 021 - Twisting Nether' WHERE `ID`=1093; +UPDATE `graveyard_zone` SET `Comment`='Blade''s Edge, Corpse Location 022 - Twisting Nether' WHERE `ID`=1094; +UPDATE `graveyard_zone` SET `Comment`='Blade''s Edge, Corpse Location 023 - Twisting Nether' WHERE `ID`=1095; +UPDATE `graveyard_zone` SET `Comment`='Blade''s Edge, Corpse Location 024 - Twisting Nether' WHERE `ID`=1096; +UPDATE `graveyard_zone` SET `Comment`='Blade''s Edge, Corpse Location 025 - Twisting Nether' WHERE `ID`=1097; +UPDATE `graveyard_zone` SET `Comment`='Blade''s Edge, Corpse Location 026 - Twisting Nether' WHERE `ID`=1098; +UPDATE `graveyard_zone` SET `Comment`='Blade''s Edge, Corpse Location 027 - Twisting Nether' WHERE `ID`=1099; +UPDATE `graveyard_zone` SET `Comment`='Blade''s Edge, Corpse Location 028 - Twisting Nether' WHERE `ID`=1100; +UPDATE `graveyard_zone` SET `Comment`='Blade''s Edge, Corpse Location 029 - Twisting Nether' WHERE `ID`=1101; +UPDATE `graveyard_zone` SET `Comment`='Blade''s Edge, Corpse Location 030 - Twisting Nether' WHERE `ID`=1102; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 000 - Twisting Nether' WHERE `ID`=1134; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 001 - Twisting Nether' WHERE `ID`=1135; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 002 - Twisting Nether' WHERE `ID`=1136; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 003 - Twisting Nether' WHERE `ID`=1137; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 004 - Twisting Nether' WHERE `ID`=1138; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 005 - Twisting Nether' WHERE `ID`=1139; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 006 - Twisting Nether' WHERE `ID`=1140; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 007 - Twisting Nether' WHERE `ID`=1141; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 008 - Twisting Nether' WHERE `ID`=1142; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 009 - Twisting Nether' WHERE `ID`=1143; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 010 - Twisting Nether' WHERE `ID`=1144; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 011 - Twisting Nether' WHERE `ID`=1145; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 012 - Twisting Nether' WHERE `ID`=1146; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 013 - Twisting Nether' WHERE `ID`=1147; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 014 - Twisting Nether' WHERE `ID`=1148; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 015 - Twisting Nether' WHERE `ID`=1149; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 016 - Twisting Nether' WHERE `ID`=1150; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 017 - Twisting Nether' WHERE `ID`=1151; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 018 - Twisting Nether' WHERE `ID`=1152; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 019 - Twisting Nether' WHERE `ID`=1153; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 020 - Twisting Nether' WHERE `ID`=1154; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 021 - Twisting Nether' WHERE `ID`=1155; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 022 - Twisting Nether' WHERE `ID`=1156; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 023 - Twisting Nether' WHERE `ID`=1157; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 024 - Twisting Nether' WHERE `ID`=1158; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 025 - Twisting Nether' WHERE `ID`=1159; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 026 - Twisting Nether' WHERE `ID`=1160; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 027 - Twisting Nether' WHERE `ID`=1161; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 028 - Twisting Nether' WHERE `ID`=1162; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 029 - Twisting Nether' WHERE `ID`=1163; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 030 - Twisting Nether' WHERE `ID`=1164; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 031 - Twisting Nether' WHERE `ID`=1165; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 032 - Twisting Nether' WHERE `ID`=1166; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 033 - Twisting Nether' WHERE `ID`=1167; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 034 - Twisting Nether' WHERE `ID`=1168; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 035 - Twisting Nether' WHERE `ID`=1169; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 036 - Twisting Nether' WHERE `ID`=1170; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 037 - Twisting Nether' WHERE `ID`=1171; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 038 - Twisting Nether' WHERE `ID`=1172; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 039 - Twisting Nether' WHERE `ID`=1173; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 040 - Twisting Nether' WHERE `ID`=1174; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 041 - Twisting Nether' WHERE `ID`=1175; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 042 - Twisting Nether' WHERE `ID`=1176; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 043 - Twisting Nether' WHERE `ID`=1177; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 044 - Twisting Nether' WHERE `ID`=1178; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 045 - Twisting Nether' WHERE `ID`=1179; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 046 - Twisting Nether' WHERE `ID`=1180; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 047 - Twisting Nether' WHERE `ID`=1181; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 048 - Twisting Nether' WHERE `ID`=1182; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 049 - Twisting Nether' WHERE `ID`=1183; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 050 - Twisting Nether' WHERE `ID`=1184; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 051 - Twisting Nether' WHERE `ID`=1185; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 052 - Twisting Nether' WHERE `ID`=1186; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 053 - Twisting Nether' WHERE `ID`=1187; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 054 - Twisting Nether' WHERE `ID`=1188; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 055 - Twisting Nether' WHERE `ID`=1189; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 056 - Twisting Nether' WHERE `ID`=1190; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 057 - Twisting Nether' WHERE `ID`=1191; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 058 - Twisting Nether' WHERE `ID`=1192; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 059 - Twisting Nether' WHERE `ID`=1193; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 060 - Twisting Nether' WHERE `ID`=1194; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 061 - Twisting Nether' WHERE `ID`=1195; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 062 - Twisting Nether' WHERE `ID`=1196; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 063 - Twisting Nether' WHERE `ID`=1197; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 064 - Twisting Nether' WHERE `ID`=1198; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 065 - Twisting Nether' WHERE `ID`=1199; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 066 - Twisting Nether' WHERE `ID`=1200; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 067 - Twisting Nether' WHERE `ID`=1201; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 068 - Twisting Nether' WHERE `ID`=1202; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 069 - Twisting Nether' WHERE `ID`=1203; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 070 - Twisting Nether' WHERE `ID`=1204; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 071 - Twisting Nether' WHERE `ID`=1205; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 072 - Twisting Nether' WHERE `ID`=1206; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 073 - Twisting Nether' WHERE `ID`=1207; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 074 - Twisting Nether' WHERE `ID`=1208; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 075 - Twisting Nether' WHERE `ID`=1209; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 076 - Twisting Nether' WHERE `ID`=1210; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 077 - Twisting Nether' WHERE `ID`=1211; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 078 - Twisting Nether' WHERE `ID`=1212; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 079 - Twisting Nether' WHERE `ID`=1213; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 080 - Twisting Nether' WHERE `ID`=1214; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 081 - Twisting Nether' WHERE `ID`=1215; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 082 - Twisting Nether' WHERE `ID`=1216; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 083 - Twisting Nether' WHERE `ID`=1217; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 084 - Twisting Nether' WHERE `ID`=1218; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 085 - Twisting Nether' WHERE `ID`=1219; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 086 - Twisting Nether' WHERE `ID`=1220; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 087 - Twisting Nether' WHERE `ID`=1221; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 088 - Twisting Nether' WHERE `ID`=1222; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 089 - Twisting Nether' WHERE `ID`=1223; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 090 - Twisting Nether' WHERE `ID`=1224; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 091 - Twisting Nether' WHERE `ID`=1225; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 092 - Twisting Nether' WHERE `ID`=1226; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 093 - Twisting Nether' WHERE `ID`=1227; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 094 - Twisting Nether' WHERE `ID`=1228; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 095 - Twisting Nether' WHERE `ID`=1229; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 096 - Twisting Nether' WHERE `ID`=1230; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 097 - Twisting Nether' WHERE `ID`=1231; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 098 - Twisting Nether' WHERE `ID`=1232; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 099 - Twisting Nether' WHERE `ID`=1233; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 100 - Twisting Nether' WHERE `ID`=1234; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 101 - Twisting Nether' WHERE `ID`=1235; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 102 - Twisting Nether' WHERE `ID`=1236; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 103 - Twisting Nether' WHERE `ID`=1237; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 104 - Twisting Nether' WHERE `ID`=1238; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm - Corpse Catcher 105 - Twisting Nether' WHERE `ID`=1239; +UPDATE `graveyard_zone` SET `Comment`='Hellfire Peninsula, Force Camps (Alliance) - Hellfire Peninsula' WHERE `ID`=1240; +UPDATE `graveyard_zone` SET `Comment`='Blade''s Edge, Evergrove GY' WHERE `ID`=1241; +UPDATE `graveyard_zone` SET `Comment`='Blade''s Edge, North Ridge GY - Blade''s Edge Mountains' WHERE `ID`=1242; +UPDATE `graveyard_zone` SET `Comment`='Blade''s Edge, West Ridge GY - Blade''s Edge Mountains' WHERE `ID`=1243; +UPDATE `graveyard_zone` SET `Comment`='Blade''s Edge, East Ridge GY - Blade''s Edge Mountains' WHERE `ID`=1244; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm, Cosmowrench GY' WHERE `ID`=1247; +UPDATE `graveyard_zone` SET `Comment`='Hellfire Peninsula, Spinebreaker GY - Hellfire Peninsula' WHERE `ID`=1248; +UPDATE `graveyard_zone` SET `Comment`='Tanaris, CoT GY' WHERE `ID`=1249; +UPDATE `graveyard_zone` SET `Comment`='Shadowmoon Valley, Altar GY - Shadowmoon Valley' WHERE `ID`=1250; +UPDATE `graveyard_zone` SET `Comment`='Shadowmoon Valley, Sanctum GY - Shadowmoon Valley' WHERE `ID`=1251; +UPDATE `graveyard_zone` SET `Comment`='Netherstorm, Kirin''Var GY - Netherstorm' WHERE `ID`=1252; +UPDATE `graveyard_zone` SET `Comment`='Blade''s Edge, Toshley GY - Blade''s Edge Mountains' WHERE `ID`=1253; +UPDATE `graveyard_zone` SET `Comment`='Blade''s Edge, Raven Wood GY - Blade''s Edge Mountains' WHERE `ID`=1254; +UPDATE `graveyard_zone` SET `Comment`='Blade''s Edge, NE Ridge GY - Blade''s Edge Mountains' WHERE `ID`=1255; +UPDATE `graveyard_zone` SET `Comment`='Silverpine Forest, South GY - Silverpine Forest' WHERE `ID`=1256; +UPDATE `graveyard_zone` SET `Comment`='Terokkar Forest, Ogre GY - Terokkar Forest' WHERE `ID`=1257; +UPDATE `graveyard_zone` SET `Comment`='Black Temple, Alliance GY - Black Temple' WHERE `ID`=1261; +UPDATE `graveyard_zone` SET `Comment`='Black Temple, Horde GY - Black Temple' WHERE `ID`=1262; +UPDATE `graveyard_zone` SET `Comment`='Dustwallow Marsh, Tabetha''s GY - Dustwallow Marsh' WHERE `ID`=1264; +UPDATE `graveyard_zone` SET `Comment`='Dustwallow Marsh, Mudsprocket GY - Onyxia''s Lair' WHERE `ID`=1265; +UPDATE `graveyard_zone` SET `Comment`='Dustwallow Marsh, Mudsprocket GY - Dustwallow Marsh' WHERE `ID`=1265; +UPDATE `graveyard_zone` SET `Comment`='Howling Fjord, Northwest GY - Howling Fjord' WHERE `ID`=1266; +UPDATE `graveyard_zone` SET `Comment`='Howling Fjord, Tuskarr GY - Howling Fjord' WHERE `ID`=1267; +UPDATE `graveyard_zone` SET `Comment`='Howling Fjord, Island GY - Howling Fjord' WHERE `ID`=1268; +UPDATE `graveyard_zone` SET `Comment`='Howling Fjord, Central GY - Howling Fjord' WHERE `ID`=1269; +UPDATE `graveyard_zone` SET `Comment`='Howling Fjord, North GY - Howling Fjord' WHERE `ID`=1270; +UPDATE `graveyard_zone` SET `Comment`='Howling Fjord, Vengance GY - Howling Fjord' WHERE `ID`=1271; +UPDATE `graveyard_zone` SET `Comment`='Howling Fjord, Southeast GY - Howling Fjord' WHERE `ID`=1272; +UPDATE `graveyard_zone` SET `Comment`='Howling Fjord, South Beach GY - Howling Fjord' WHERE `ID`=1273; +UPDATE `graveyard_zone` SET `Comment`='Howling Fjord, South GY - Howling Fjord' WHERE `ID`=1274; +UPDATE `graveyard_zone` SET `Comment`='Howling Fjord, Valgarde GY - Howling Fjord' WHERE `ID`=1275; +UPDATE `graveyard_zone` SET `Comment`='Howling Fjord, Northeast GY - Howling Fjord' WHERE `ID`=1276; +UPDATE `graveyard_zone` SET `Comment`='Un''Goro Crater, Central GY - Un''Goro Crater' WHERE `ID`=1277; +UPDATE `graveyard_zone` SET `Comment`='Un''Goro Crater, Marshal''s GY - Un''Goro Crater' WHERE `ID`=1278; +UPDATE `graveyard_zone` SET `Comment`='Stonetalon Mountains, Charred Vale GY - Stonetalon Mountains' WHERE `ID`=1279; +UPDATE `graveyard_zone` SET `Comment`='Stonetalon Mountains, Peak GY - Stonetalon Mountains' WHERE `ID`=1280; +UPDATE `graveyard_zone` SET `Comment`='Tanaris, Pirate GY - Tanaris' WHERE `ID`=1281; +UPDATE `graveyard_zone` SET `Comment`='Tanaris, Central GY - Tanaris' WHERE `ID`=1282; +UPDATE `graveyard_zone` SET `Comment`='Winterspring, South GY - Winterspring' WHERE `ID`=1283; +UPDATE `graveyard_zone` SET `Comment`='Winterspring, West GY - Winterspring' WHERE `ID`=1284; +UPDATE `graveyard_zone` SET `Comment`='Western Plaguelands, Central GY - Western Plaguelands' WHERE `ID`=1286; +UPDATE `graveyard_zone` SET `Comment`='Searing Gorge, SE GY - Searing Gorge' WHERE `ID`=1287; +UPDATE `graveyard_zone` SET `Comment`='Badlands, South GY - Badlands' WHERE `ID`=1288; +UPDATE `graveyard_zone` SET `Comment`='The Barrens, South GY - Southern Barrens' WHERE `ID`=1289; +UPDATE `graveyard_zone` SET `Comment`='Borean Tundra, Tuskar GY - Borean Tundra' WHERE `ID`=1290; +UPDATE `graveyard_zone` SET `Comment`='Terokkar Forest, Razorthorn Rise GY - Terokkar Forest' WHERE `ID`=1291; +UPDATE `graveyard_zone` SET `Comment`='Isle of Quel''Danas, Staging Area GY - Isle of Quel''Danas' WHERE `ID`=1292; +UPDATE `graveyard_zone` SET `Comment`='Isle of Quel''Danas, Staging Area GY - Magisters'' Terrace' WHERE `ID`=1293; +UPDATE `graveyard_zone` SET `Comment`='Isle of Quel''Danas, Staging Area GY - Sunwell Plateau' WHERE `ID`=1293; +UPDATE `graveyard_zone` SET `Comment`='Terokkar Forest, Lake Jorune GY - Terokkar Forest' WHERE `ID`=1298; +UPDATE `graveyard_zone` SET `Comment`='Grizzly Hills, Vileprey GY - Grizzly Hills' WHERE `ID`=1300; +UPDATE `graveyard_zone` SET `Comment`='Grizzly Hills, Amberpine GY - Grizzly Hills' WHERE `ID`=1301; +UPDATE `graveyard_zone` SET `Comment`='Grizzly Hills, Westfall GY - Grizzly Hills' WHERE `ID`=1302; +UPDATE `graveyard_zone` SET `Comment`='Grizzly Hills, Eastern GY - Grizzly Hills' WHERE `ID`=1303; +UPDATE `graveyard_zone` SET `Comment`='Grizzly Hills, Northwestern GY - Grizzly Hills' WHERE `ID`=1304; +UPDATE `graveyard_zone` SET `Comment`='Grizzly Hills, Southwestern GY - Grizzly Hills' WHERE `ID`=1305; +UPDATE `graveyard_zone` SET `Comment`='Grizzly Hills, Central GY - Grizzly Hills' WHERE `ID`=1306; +UPDATE `graveyard_zone` SET `Comment`='Dragonblight, Northeastern GY - Dragonblight' WHERE `ID`=1307; +UPDATE `graveyard_zone` SET `Comment`='Dragonblight, Wintergarde GY - Naxxramas' WHERE `ID`=1308; +UPDATE `graveyard_zone` SET `Comment`='Dragonblight, Wintergarde GY - Dragonblight' WHERE `ID`=1308; +UPDATE `graveyard_zone` SET `Comment`='Dragonblight, Forsaken East GY - Naxxramas' WHERE `ID`=1309; +UPDATE `graveyard_zone` SET `Comment`='Dragonblight, Agmar''s Hammer GY - Dragonblight' WHERE `ID`=1310; +UPDATE `graveyard_zone` SET `Comment`='Dragonblight, Star''s Rest GY - Dragonblight' WHERE `ID`=1311; +UPDATE `graveyard_zone` SET `Comment`='Dragonblight, Moa''ki Harbor GY - Dragonblight' WHERE `ID`=1312; +UPDATE `graveyard_zone` SET `Comment`='Dragonblight, Borean Border GY - Dragonblight' WHERE `ID`=1313; +UPDATE `graveyard_zone` SET `Comment`='Dragonblight, Wyrmrest GY - Dragonblight' WHERE `ID`=1314; +UPDATE `graveyard_zone` SET `Comment`='Dragonblight, Wrathgate Horde GY - Dragonblight' WHERE `ID`=1315; +UPDATE `graveyard_zone` SET `Comment`='Dragonblight, Wrathgate Alliance GY - Dragonblight' WHERE `ID`=1316; +UPDATE `graveyard_zone` SET `Comment`='Borean Tundra, Warsong Hold GY - Borean Tundra' WHERE `ID`=1317; +UPDATE `graveyard_zone` SET `Comment`='Borean Tundra, Riplash GY - Borean Tundra' WHERE `ID`=1318; +UPDATE `graveyard_zone` SET `Comment`='Borean Tundra, Coldarra GY' WHERE `ID`=1319; +UPDATE `graveyard_zone` SET `Comment`='Borean Tundra, Amber Ledge GY - Borean Tundra' WHERE `ID`=1320; +UPDATE `graveyard_zone` SET `Comment`='Borean Tundra, Fizzcrank GY - Borean Tundra' WHERE `ID`=1321; +UPDATE `graveyard_zone` SET `Comment`='Borean Tundra, Bor''Gorok GY - Borean Tundra' WHERE `ID`=1322; +UPDATE `graveyard_zone` SET `Comment`='Borean Tundra, Death''s Stand GY - Borean Tundra' WHERE `ID`=1323; +UPDATE `graveyard_zone` SET `Comment`='Borean Tundra, Taunka''le GY - Borean Tundra' WHERE `ID`=1324; +UPDATE `graveyard_zone` SET `Comment`='Borean Tundra, Coast of Echoes GY - Borean Tundra' WHERE `ID`=1325; +UPDATE `graveyard_zone` SET `Comment`='Borean Tundra, Valiance Keep GY - Borean Tundra' WHERE `ID`=1326; +UPDATE `graveyard_zone` SET `Comment`='Wintergrasp, Fortress (West) - Wintergrasp' WHERE `ID`=1328; +UPDATE `graveyard_zone` SET `Comment`='Wintergrasp, Siege Factory (Defense NE) - Wintergrasp' WHERE `ID`=1329; +UPDATE `graveyard_zone` SET `Comment`='Wintergrasp, Siege Factory (Defense NW) - Wintergrasp' WHERE `ID`=1330; +UPDATE `graveyard_zone` SET `Comment`='Wintergrasp, Horde Starting Area - Wintergrasp' WHERE `ID`=1331; +UPDATE `graveyard_zone` SET `Comment`='Wintergrasp, Alliance Starting Area - Wintergrasp' WHERE `ID`=1332; +UPDATE `graveyard_zone` SET `Comment`='Wintergrasp, Siege Factory (SE) - Wintergrasp' WHERE `ID`=1333; +UPDATE `graveyard_zone` SET `Comment`='Wintergrasp, Siege Factory (SW) - Wintergrasp' WHERE `ID`=1334; +UPDATE `graveyard_zone` SET `Comment`='Sholazar Basin, South GY - Sholazar Basin' WHERE `ID`=1336; +UPDATE `graveyard_zone` SET `Comment`='Howling Fjord, Utgarde GY - Utgarde Pinnacle' WHERE `ID`=1337; +UPDATE `graveyard_zone` SET `Comment`='Sholazar Basin, Nesingwary GY - Sholazar Basin' WHERE `ID`=1341; +UPDATE `graveyard_zone` SET `Comment`='Sholazar Basin, Central GY - Sholazar Basin' WHERE `ID`=1342; +UPDATE `graveyard_zone` SET `Comment`='Sholazar Basin, Northwest GY - Sholazar Basin' WHERE `ID`=1343; +UPDATE `graveyard_zone` SET `Comment`='Sholazar Basin, Northeast GY - Sholazar Basin' WHERE `ID`=1344; +UPDATE `graveyard_zone` SET `Comment`='Sholazar Basin, East GY - Sholazar Basin' WHERE `ID`=1345; +UPDATE `graveyard_zone` SET `Comment`='Zul''Drak, Western GY - Zul''Drak' WHERE `ID`=1352; +UPDATE `graveyard_zone` SET `Comment`='Zul''Drak, Northwestern GY - Zul''Drak' WHERE `ID`=1353; +UPDATE `graveyard_zone` SET `Comment`='Zul''Drak, Southwestern GY - Zul''Drak' WHERE `ID`=1354; +UPDATE `graveyard_zone` SET `Comment`='Zul''Drak, Southern GY - Zul''Drak' WHERE `ID`=1355; +UPDATE `graveyard_zone` SET `Comment`='Zul''Drak, Central GY - Zul''Drak' WHERE `ID`=1356; +UPDATE `graveyard_zone` SET `Comment`='Zul''Drak, Southeastern GY - Zul''Drak' WHERE `ID`=1357; +UPDATE `graveyard_zone` SET `Comment`='Zul''Drak, Gun''Drak GY - Zul''Drak' WHERE `ID`=1358; +UPDATE `graveyard_zone` SET `Comment`='Crystalsong Forest, Dalaran GY' WHERE `ID`=1359; +UPDATE `graveyard_zone` SET `Comment`='Ebon Hold GY - Chapter I - Plaguelands: The Scarlet Enclave' WHERE `ID`=1360; +UPDATE `graveyard_zone` SET `Comment`='Eastern Plaguelands, Ebon Hold GY - Eastern Plaguelands' WHERE `ID`=1369; +UPDATE `graveyard_zone` SET `Comment`='Ebon Hold GY - Chapter II/III - Plaguelands: The Scarlet Enclave' WHERE `ID`=1370; +UPDATE `graveyard_zone` SET `Comment`='Ebon Hold GY - Chapter IV - Plaguelands: The Scarlet Enclave' WHERE `ID`=1371; +UPDATE `graveyard_zone` SET `Comment`='Un''Goro Crater, Shaper''s Terrace GY - Un''Goro Crater' WHERE `ID`=1372; +UPDATE `graveyard_zone` SET `Comment`='Howling Fjord, Utgarde 2 GY - Utgarde Keep' WHERE `ID`=1376; +UPDATE `graveyard_zone` SET `Comment`='Sholazar Basin, Stormwright GY - Sholazar Basin' WHERE `ID`=1379; +UPDATE `graveyard_zone` SET `Comment`='Crystalsong Forest, Alliance GY - Crystalsong Forest' WHERE `ID`=1380; +UPDATE `graveyard_zone` SET `Comment`='Icecrown, Argent Vanguard - Icecrown' WHERE `ID`=1381; +UPDATE `graveyard_zone` SET `Comment`='Storm Peaks, Valkyrion GY - The Storm Peaks' WHERE `ID`=1383; +UPDATE `graveyard_zone` SET `Comment`='Storm Peaks, Ulduar GY - The Storm Peaks' WHERE `ID`=1384; +UPDATE `graveyard_zone` SET `Comment`='Storm Peaks, Temple East GY - The Storm Peaks' WHERE `ID`=1385; +UPDATE `graveyard_zone` SET `Comment`='Storm Peaks, Temple West GY - The Storm Peaks' WHERE `ID`=1387; +UPDATE `graveyard_zone` SET `Comment`='Storm Peaks, Frostfield GY - The Storm Peaks' WHERE `ID`=1388; +UPDATE `graveyard_zone` SET `Comment`='Crystalsong Forest, West GY - Crystalsong Forest' WHERE `ID`=1391; +UPDATE `graveyard_zone` SET `Comment`='Crystalsong Forest, Horde GY - Crystalsong Forest' WHERE `ID`=1392; +UPDATE `graveyard_zone` SET `Comment`='Dragonblight, Naxxramas GY - Dragonblight' WHERE `ID`=1393; +UPDATE `graveyard_zone` SET `Comment`='Dragonblight, Icemist GY - Dragonblight' WHERE `ID`=1394; +UPDATE `graveyard_zone` SET `Comment`='Icecrown Glacier, Quarry GY - Icecrown' WHERE `ID`=1395; +UPDATE `graveyard_zone` SET `Comment`='Icecrown Glacier, Vrykul Central GY - Icecrown' WHERE `ID`=1396; +UPDATE `graveyard_zone` SET `Comment`='Icecrown Glacier, Northeast Ice GY - Icecrown' WHERE `ID`=1397; +UPDATE `graveyard_zone` SET `Comment`='Grizzly Hills, Drak''tharon GY - Grizzly Hills' WHERE `ID`=1398; +UPDATE `graveyard_zone` SET `Comment`='Storm Peaks, Temple of the Makers GY - The Storm Peaks' WHERE `ID`=1400; +UPDATE `graveyard_zone` SET `Comment`='Storm Peaks, Snowdrift GY - The Storm Peaks' WHERE `ID`=1401; +UPDATE `graveyard_zone` SET `Comment`='Storm Peaks, Temple of Storms GY - The Storm Peaks' WHERE `ID`=1402; +UPDATE `graveyard_zone` SET `Comment`='Storm Peaks, K3 GY - The Storm Peaks' WHERE `ID`=1403; +UPDATE `graveyard_zone` SET `Comment`='Sholazar Basin, Frenzyheart GY - Sholazar Basin' WHERE `ID`=1404; +UPDATE `graveyard_zone` SET `Comment`='Eastern Plaguelands: Acherus - Eastern Plaguelands' WHERE `ID`=1405; +UPDATE `graveyard_zone` SET `Comment`='Icecrown Glacier, Jotunheim GY - Icecrown' WHERE `ID`=1407; +UPDATE `graveyard_zone` SET `Comment`='Storm Peaks, Foot Steppes GY - The Storm Peaks' WHERE `ID`=1408; +UPDATE `graveyard_zone` SET `Comment`='Undercity - Alliance - Wrath Gate - Tirisfal Glades' WHERE `ID`=1409; +UPDATE `graveyard_zone` SET `Comment`='Alterac Mountains - Central GY - Hillsbrad Foothills' WHERE `ID`=1411; +UPDATE `graveyard_zone` SET `Comment`='Winterspring, Wintersaber GY - Winterspring' WHERE `ID`=1416; +UPDATE `graveyard_zone` SET `Comment`='Winterspring, Crossroad GY - Winterspring' WHERE `ID`=1417; +UPDATE `graveyard_zone` SET `Comment`='Winterspring, Darkwhisper GY - Winterspring' WHERE `ID`=1418; +UPDATE `graveyard_zone` SET `Comment`='Azshara, Southern Azshara GY - Azshara' WHERE `ID`=1419; +UPDATE `graveyard_zone` SET `Comment`='Azshara, Bilgewater Harbor GY - Azshara' WHERE `ID`=1420; +UPDATE `graveyard_zone` SET `Comment`='Desolace, Ghost Walker Post GY - Desolace' WHERE `ID`=1421; +UPDATE `graveyard_zone` SET `Comment`='Desolace, Sar''theris Strand GY - Desolace' WHERE `ID`=1422; +UPDATE `graveyard_zone` SET `Comment`='Desolace, Mannoroc Coven GY - Desolace' WHERE `ID`=1423; +UPDATE `graveyard_zone` SET `Comment`='Desolace, Magram Village GY - Desolace' WHERE `ID`=1424; +UPDATE `graveyard_zone` SET `Comment`='Desolace, Roadside GY - Desolace' WHERE `ID`=1425; +UPDATE `graveyard_zone` SET `Comment`='Ashenvale, Shrine of Aessina GY - Ashenvale' WHERE `ID`=1426; +UPDATE `graveyard_zone` SET `Comment`='Ashenvale, Nightsong GY - Ashenvale' WHERE `ID`=1427; +UPDATE `graveyard_zone` SET `Comment`='Stonetalon Mountains, Windshear Crag GY - Stonetalon Mountains' WHERE `ID`=1428; +UPDATE `graveyard_zone` SET `Comment`='Stonetalon Mountains, Mirkfallon GY - Stonetalon Mountains' WHERE `ID`=1429; +UPDATE `graveyard_zone` SET `Comment`='The Barrens, Forgotten Pools - Northern Barrens' WHERE `ID`=1430; +UPDATE `graveyard_zone` SET `Comment`='The Barrens, North GY - Northern Barrens' WHERE `ID`=1431; +UPDATE `graveyard_zone` SET `Comment`='The Barrens, Raptor Grounds - Southern Barrens' WHERE `ID`=1432; +UPDATE `graveyard_zone` SET `Comment`='The Barrens, Central GY - Southern Barrens' WHERE `ID`=1433; +UPDATE `graveyard_zone` SET `Comment`='The Barrens, East GY - Northern Barrens' WHERE `ID`=1434; +UPDATE `graveyard_zone` SET `Comment`='Mulgore, Southeast GY - Mulgore' WHERE `ID`=1435; +UPDATE `graveyard_zone` SET `Comment`='Mulgore, Red Rocks GY - Mulgore' WHERE `ID`=1436; +UPDATE `graveyard_zone` SET `Comment`='Thousand Needles, Freewind Post GY (MOVED) - Thousand Needles' WHERE `ID`=1437; +UPDATE `graveyard_zone` SET `Comment`='Thousand Needles, Speed Barge GY (MOVED) - Thousand Needles' WHERE `ID`=1438; +UPDATE `graveyard_zone` SET `Comment`='Tanaris, Southwest GY - Tanaris' WHERE `ID`=1439; +UPDATE `graveyard_zone` SET `Comment`='Tanaris, Abyssal Sands GY - Tanaris' WHERE `ID`=1440; +UPDATE `graveyard_zone` SET `Comment`='Feralas, Ruins of Isildien GY - Feralas' WHERE `ID`=1441; +UPDATE `graveyard_zone` SET `Comment`='Feralas, Lower Wilds GY - Feralas' WHERE `ID`=1442; +UPDATE `graveyard_zone` SET `Comment`='Feralas, Twin Colossals GY - Feralas' WHERE `ID`=1443; +UPDATE `graveyard_zone` SET `Comment`='Silithus, Hive''Regal - Silithus' WHERE `ID`=1444; +UPDATE `graveyard_zone` SET `Comment`='Silithus, Twilight Base Camp - Silithus' WHERE `ID`=1445; +UPDATE `graveyard_zone` SET `Comment`='Arathi Highlands, Stromgarde - Arathi Highlands' WHERE `ID`=1446; +UPDATE `graveyard_zone` SET `Comment`='Hillsbrad Foothills, Thoradin''s Wall - Hillsbrad Foothills' WHERE `ID`=1447; +UPDATE `graveyard_zone` SET `Comment`='Eastern Plaguelands, Northdale - Eastern Plaguelands' WHERE `ID`=1448; +UPDATE `graveyard_zone` SET `Comment`='Eastern Plaguelands, Stratholme - Eastern Plaguelands' WHERE `ID`=1449; +UPDATE `graveyard_zone` SET `Comment`='Eastern Plaguelands, West GY - Eastern Plaguelands' WHERE `ID`=1450; +UPDATE `graveyard_zone` SET `Comment`='Western Plaguelands, Hearthglen - Eastern Plaguelands' WHERE `ID`=1451; +UPDATE `graveyard_zone` SET `Comment`='Hillsbrad Foothills, Hillsbrad Fields GY - Hillsbrad Foothills' WHERE `ID`=1452; +UPDATE `graveyard_zone` SET `Comment`='The Hinterlands, Seradane - The Hinterlands' WHERE `ID`=1453; +UPDATE `graveyard_zone` SET `Comment`='The Hinterlands, Shadra''Alor - The Hinterlands' WHERE `ID`=1454; +UPDATE `graveyard_zone` SET `Comment`='Wetlands, Sundown Marsh GY - Wetlands' WHERE `ID`=1455; +UPDATE `graveyard_zone` SET `Comment`='Wetlands, South Road GY - Wetlands' WHERE `ID`=1456; +UPDATE `graveyard_zone` SET `Comment`='Wetlands, Raptor Ridge GY - Wetlands' WHERE `ID`=1457; +UPDATE `graveyard_zone` SET `Comment`='AAA - Arena (Dev Test) - Stranglethorn Vale' WHERE `ID`=1458; +UPDATE `graveyard_zone` SET `Comment`='Stranglethorn Vale, Central GY - Stranglethorn Vale' WHERE `ID`=1459; +UPDATE `graveyard_zone` SET `Comment`='Stranglethorn Vale, Savage Coast GY - Stranglethorn Vale' WHERE `ID`=1460; +UPDATE `graveyard_zone` SET `Comment`='Duskwood, Central GY - Duskwood' WHERE `ID`=1461; +UPDATE `graveyard_zone` SET `Comment`='Westfall, Dagger Hills GY - Westfall' WHERE `ID`=1462; +UPDATE `graveyard_zone` SET `Comment`='Westfall, Longshore - Westfall' WHERE `ID`=1463; +UPDATE `graveyard_zone` SET `Comment`='Blasted Lands, Dark Portal GY - Blasted Lands' WHERE `ID`=1464; +UPDATE `graveyard_zone` SET `Comment`='Swamp of Sorrows, Alliance Hub GY - Swamp of Sorrows' WHERE `ID`=1465; +UPDATE `graveyard_zone` SET `Comment`='Swamp of Sorrows, Splinterspear GY - Swamp of Sorrows' WHERE `ID`=1466; +UPDATE `graveyard_zone` SET `Comment`='Redridge Mountains, Stonewatch - Redridge Mountains' WHERE `ID`=1467; +UPDATE `graveyard_zone` SET `Comment`='Elwynn Forest, Tower of Azora - Elwynn Forest' WHERE `ID`=1468; +UPDATE `graveyard_zone` SET `Comment`='Burning Steppes, Blackrock Mountain - Blackrock Mountain' WHERE `ID`=1469; +UPDATE `graveyard_zone` SET `Comment`='Burning Steppes, East GY - Burning Steppes' WHERE `ID`=1470; +UPDATE `graveyard_zone` SET `Comment`='Dun Morogh, Iceflow Lake - Dun Morogh' WHERE `ID`=1471; +UPDATE `graveyard_zone` SET `Comment`='Dun Morogh, East Road - Dun Morogh' WHERE `ID`=1472; +UPDATE `graveyard_zone` SET `Comment`='Loch Modan, The Loch - Loch Modan' WHERE `ID`=1473; +UPDATE `graveyard_zone` SET `Comment`='Wintergrasp, Fortress Graveyard (Indoors) - Vault of Archavon' WHERE `ID`=1474; +UPDATE `graveyard_zone` SET `Comment`='Icecrown, Argent Tournament GY' WHERE `ID`=1478; +UPDATE `graveyard_zone` SET `Comment`='Icecrown Glacier, Citadel GY' WHERE `ID`=1682; diff --git a/sql/updates/world/3.3.5/2016_05_26_00_world.sql b/sql/updates/world/3.3.5/2016_05_26_00_world.sql new file mode 100644 index 00000000000..39e16aba39e --- /dev/null +++ b/sql/updates/world/3.3.5/2016_05_26_00_world.sql @@ -0,0 +1,19 @@ +-- Localized name for gameobject entry 1638 and 2035 (English name "Deathknell") +DELETE FROM `gameobject_template_locale` WHERE `entry` IN (1638,2035); +INSERT INTO `gameobject_template_locale` (`entry`,`locale`,`name`,`castBarCaption`,`VerifiedBuild`) VALUES +(1638,'deDE','Todesend','',0), +(1638,'esES','Camposanto','',0), +(1638,'esMX','Camposanto','',0), +(1638,'frFR','Le Glas','',0), +(1638,'koKR','죽음의 종소리 마을','',0), +(1638,'ruRU','Похоронный Звон','',0), +(1638,'zhCN','丧钟镇','',0), +(1638,'zhTW','喪鐘鎮','',0), +(2035,'deDE','Todesend','',0), +(2035,'esES','Camposanto','',0), +(2035,'esMX','Camposanto','',0), +(2035,'frFR','Le Glas','',0), +(2035,'koKR','죽음의 종소리 마을','',0), +(2035,'ruRU','Похоронный Звон','',0), +(2035,'zhCN','丧钟镇','',0), +(2035,'zhTW','喪鐘鎮','',0); diff --git a/sql/updates/world/3.3.5/2016_05_26_01_world.sql b/sql/updates/world/3.3.5/2016_05_26_01_world.sql new file mode 100644 index 00000000000..343bc6f0a17 --- /dev/null +++ b/sql/updates/world/3.3.5/2016_05_26_01_world.sql @@ -0,0 +1,8 @@ +-- +DELETE FROM `smart_scripts` WHERE `entryorguid`=18794 AND `id`=34; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(18794,0,34,0,1,0,100,0,0,0,0,0,11,32958,0,0,0,0,0,1,0,0,0,0,0,0,0,"Cabal Ritualist - Out of Combat - Cast 'Crystal Channel'"); + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceGroup`=1 AND `SourceEntry`=32958; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`SourceId`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionTarget`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES +(13,1,32958,0,0,31,0,3,18793,0,0,"","Crystal Channel – Effect 0 - Cast only on Invisible Target 18793."); diff --git a/sql/updates/world/3.3.5/2016_05_26_02_world.sql b/sql/updates/world/3.3.5/2016_05_26_02_world.sql new file mode 100644 index 00000000000..4cacdc73a47 --- /dev/null +++ b/sql/updates/world/3.3.5/2016_05_26_02_world.sql @@ -0,0 +1,2 @@ +-- Fix bounding radius for 'Ice Tomb' +UPDATE `creature_model_info` SET `BoundingRadius`=7.5, `CombatReach`=6 WHERE `DisplayID`=30890; diff --git a/sql/updates/world/3.3.5/2016_05_26_03_world.sql b/sql/updates/world/3.3.5/2016_05_26_03_world.sql new file mode 100644 index 00000000000..f3a419e9bd0 --- /dev/null +++ b/sql/updates/world/3.3.5/2016_05_26_03_world.sql @@ -0,0 +1,21 @@ +-- Pathing for Clam Master K Entry: 25800 'TDB FORMAT' +SET @NPC := 114803; +SET @PATH := @NPC * 10; +UPDATE `creature` SET `spawndist`=0,`MovementType`=2,`position_x`=2342.325,`position_y`=5050.552,`position_z`=-21.01424 WHERE `guid`=@NPC; +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES (@NPC,@PATH,0,0,1,0, ''); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,2342.325,5050.552,-21.01424,0,0,0,0,100,0), -- 06:32:15 +(@PATH,2,2338.003,5044.308,-22.64446,0,0,0,0,100,0), -- 06:32:22 +(@PATH,3,2336.804,5029.821,-26.94789,0,0,0,0,100,0), -- 06:32:27 +(@PATH,4,2341.884,5018.865,-30.1459,0,0,0,0,100,0), -- 06:32:33 +(@PATH,5,2348.352,5002.221,-30.94783,0,0,0,0,100,0), -- 06:32:40 +(@PATH,6,2349.925,4993.154,-32.16956,0,0,0,0,100,0), -- 06:32:45 +(@PATH,7,2354.025,4983.295,-33.4639,0,0,0,0,100,0), -- 06:32:50 +(@PATH,8,2357.896,4977.057,-33.84595,0,0,0,0,100,0), -- 06:32:53 +(@PATH,9,2353.561,4983.914,-33.77616,0,0,0,0,100,0), -- 06:33:00 +(@PATH,10,2349.806,4994.94,-31.05927,0,0,0,0,100,0), -- 06:33:04 +(@PATH,11,2346.473,5009.516,-31.52969,0,0,0,0,100,0), -- 06:33:08 +(@PATH,12,2338.316,5025.714,-28.18582,0,0,0,0,100,0), -- 06:33:13 +(@PATH,13,2334.683,5038.239,-23.58451,0,0,0,0,100,0); -- 06:33:20 diff --git a/sql/updates/world/3.3.5/2016_05_26_04_world.sql b/sql/updates/world/3.3.5/2016_05_26_04_world.sql new file mode 100644 index 00000000000..00ae15af434 --- /dev/null +++ b/sql/updates/world/3.3.5/2016_05_26_04_world.sql @@ -0,0 +1,27 @@ +-- Pathing for Houndmaster Grebmar Entry: 9319 'TDB FORMAT' +SET @NPC := 46284; +SET @PATH := @NPC * 10; +UPDATE `creature` SET `spawndist`=0,`MovementType`=2,`position_x`=594.4585,`position_y`=-178.3237,`position_z`=-84.23994 WHERE `guid`=@NPC; +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES (@NPC,@PATH,0,0,1,0, ''); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,594.4585,-178.3237,-84.23994,0,0,0,0,100,0), +(@PATH,2,598.2085,-180.3237,-84.23994,0,0,0,0,100,0), +(@PATH,3,601.2085,-182.3237,-84.23994,0,0,0,0,100,0), +(@PATH,4,605.1209,-184.6363,-84.23941,0,0,0,0,100,0), +(@PATH,5,608.8709,-188.1363,-84.23941,0,0,0,0,100,0), +(@PATH,6,612.06,-191.0042,-84.23634,0,0,0,0,100,0), +(@PATH,7,611.81,-184.0042,-84.23634,0,0,0,0,100,0), +(@PATH,8,611.5181,-178.7817,-84.23982,0,0,0,0,100,0), +(@PATH,9,606.7681,-173.7817,-84.23982,0,0,0,0,100,0), +(@PATH,10,601.315,-167.8244,-84.23912,0,0,0,0,100,0), +(@PATH,11,594.565,-168.8244,-84.23912,0,0,0,0,100,0), +(@PATH,12,585.8881,-169.7204,-84.24162,0,0,0,0,100,0), +(@PATH,13,582.8881,-176.2204,-84.24162,0,0,0,0,100,0), +(@PATH,14,579.5485,-182.8368,-84.24379,0,0,0,0,100,0), +(@PATH,15,583.2985,-189.3368,-84.24379,0,0,0,0,100,0), +(@PATH,16,586.8497,-196.4224,-84.24238,0,0,0,0,100,0), +(@PATH,17,587.5997,-187.1724,-84.24238,0,0,0,0,100,0), +(@PATH,18,591.6155,-181.6407,-84.24092,0,0,0,0,100,0), +(@PATH,19,594.4585,-178.3237,-84.23994,0,0,0,0,100,0); diff --git a/sql/updates/world/3.3.5/2016_05_26_05_world.sql b/sql/updates/world/3.3.5/2016_05_26_05_world.sql new file mode 100644 index 00000000000..192ea0893d3 --- /dev/null +++ b/sql/updates/world/3.3.5/2016_05_26_05_world.sql @@ -0,0 +1,3 @@ +-- DB/Creature: Add flag guard Deathguard Elite +-- creature is a guard (Will ignore feign death and vanish) +UPDATE `creature_template` SET `flags_extra`=32768 WHERE `entry`=7980; diff --git a/sql/updates/world/3.3.5/2016_05_26_06_world_335.sql b/sql/updates/world/3.3.5/2016_05_26_06_world_335.sql new file mode 100644 index 00000000000..0b8903f527d --- /dev/null +++ b/sql/updates/world/3.3.5/2016_05_26_06_world_335.sql @@ -0,0 +1,5 @@ +-- Anvilrage Overseer SAI (3.3.5 Only) +UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry`=8889; +DELETE FROM `smart_scripts` WHERE `entryorguid`=8889 AND `source_type`=0; +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(8889, 0, 0, 0, 0, 0, 100, 2, 4000, 6000, 7000, 9000, 11, 15580, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 'Anvilrage Overseer - In Combat - Cast \'Strike\' (Normal Dungeon)'); diff --git a/sql/updates/world/3.3.5/2016_05_26_07_world.sql b/sql/updates/world/3.3.5/2016_05_26_07_world.sql new file mode 100644 index 00000000000..0749f080581 --- /dev/null +++ b/sql/updates/world/3.3.5/2016_05_26_07_world.sql @@ -0,0 +1,5 @@ +-- DB/Creature: Add missing Ornery Plainstrider SAI +UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry`=3245; +DELETE FROM `smart_scripts` WHERE `entryorguid`=3245 AND `source_type`=0; +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(3245, 0, 0, 0, 2, 0, 100, 1, 0, 40, 0, 0, 11, 3019, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Ornery Plainstrider - Between 0-40% Health - Cast \'Frenzy\' (No Repeat)'); diff --git a/sql/updates/world/3.3.5/2016_05_26_08_world.sql b/sql/updates/world/3.3.5/2016_05_26_08_world.sql new file mode 100644 index 00000000000..af1d7a3d515 --- /dev/null +++ b/sql/updates/world/3.3.5/2016_05_26_08_world.sql @@ -0,0 +1 @@ +UPDATE `quest_offer_reward` SET `RewardText`= "I can't believe it! It was the gnome all along... I should have known!" WHERE `id` = 9531; diff --git a/sql/updates/world/3.3.5/2016_05_26_09_world.sql b/sql/updates/world/3.3.5/2016_05_26_09_world.sql new file mode 100644 index 00000000000..0ad751a01d4 --- /dev/null +++ b/sql/updates/world/3.3.5/2016_05_26_09_world.sql @@ -0,0 +1,14 @@ +-- Mebok Mizzyrix, NPC entry 3446 +SET @ENTRY := 3446; + +DELETE FROM `creature_text` WHERE `entry`= @ENTRY; +INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`language`,`probability`,`emote`,`duration`,`sound`,`BroadcastTextId`,`TextRange`,`comment`) VALUES +(@ENTRY,0,0,"Now let's try it...", 12,0,100, 7,0,0,2078,0,'Mebok Mizzyrix on Quest 865 rewarded'), +(@ENTRY,1,0,"Ugh! That's terrible!",12,0,100,33,0,0,2079,0,'Mebok Mizzyrix on Quest 865 rewarded'); + +UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry`= @ENTRY; + +DELETE FROM `smart_scripts` WHERE `source_type`= 0 AND `entryorguid`= @ENTRY; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@ENTRY,0,0,1,20,0,100,0,865,0,0,0,1,0,4000,0,0,0,0,1,0,0,0,0,0,0,0,'Mebok Mizzyrix - on Quest 865 Rewarded - Say Line 0'), +(@ENTRY,0,1,0,61,0,100,0, 0,0,0,0,1,1,4000,0,0,0,0,1,0,0,0,0,0,0,0,'Mebok Mizzyrix - on Quest 865 Rewarded - Say Line 1'); diff --git a/sql/updates/world/3.3.5/2016_05_28_00_world.sql b/sql/updates/world/3.3.5/2016_05_28_00_world.sql new file mode 100644 index 00000000000..602f7834cd8 --- /dev/null +++ b/sql/updates/world/3.3.5/2016_05_28_00_world.sql @@ -0,0 +1 @@ +UPDATE `creature_addon` SET `auras`=55701 WHERE `guid`=100071; diff --git a/sql/updates/world/3.3.5/2016_05_28_01_world.sql b/sql/updates/world/3.3.5/2016_05_28_01_world.sql new file mode 100644 index 00000000000..0ce802fd363 --- /dev/null +++ b/sql/updates/world/3.3.5/2016_05_28_01_world.sql @@ -0,0 +1,4 @@ +DELETE FROM `spell_script_names` WHERE `ScriptName`='spell_ioc_seaforium_blast_credit'; +INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES +(66676, 'spell_ioc_seaforium_blast_credit'), +(66672, 'spell_ioc_seaforium_blast_credit'); diff --git a/sql/updates/world/3.3.5/2016_05_28_02_world_335.sql b/sql/updates/world/3.3.5/2016_05_28_02_world_335.sql new file mode 100644 index 00000000000..b0db2e7c4e9 --- /dev/null +++ b/sql/updates/world/3.3.5/2016_05_28_02_world_335.sql @@ -0,0 +1,240 @@ +UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry` IN(19671,19672,19673); +DELETE FROM `smart_scripts` WHERE `entryorguid`IN(19671,19672,19673,19666) AND `source_type`=0; +DELETE FROM `smart_scripts` WHERE `entryorguid`IN(1966600,1967200,1967100,1967101,1967102,1967103,1967104,1967105,1967106,1967107,1967108) AND `source_type`=9; + +DELETE FROM `smart_scripts` WHERE `entryorguid`=18311 AND `source_type`=0 AND `id`=5; +DELETE FROM `smart_scripts` WHERE `entryorguid`=18312 AND `source_type`=0 AND `id`=6; +DELETE FROM `smart_scripts` WHERE `entryorguid`=18313 AND `source_type`=0 AND `id`=16; +DELETE FROM `smart_scripts` WHERE `entryorguid`=18315 AND `source_type`=0 AND `id`=5; +DELETE FROM `smart_scripts` WHERE `entryorguid`=19307 AND `source_type`=0 AND `id`=4; + +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(18311, 0, 5, 0, 54, 0, 100, 0, 0, 0, 0, 0, 49, 0, 0, 0, 0, 0, 0, 19, 19671, 0, 0, 0, 0, 0, 0, 'Ethereal Crypt Raider - On Just Summoned - Start Attack'), +(18312, 0, 6, 0, 54, 0, 100, 0, 0, 0, 0, 0, 49, 0, 0, 0, 0, 0, 0, 19, 19671, 0, 0, 0, 0, 0, 0, 'Ethereal Spellbinder - On Just Summoned - Start Attack'), +(18313, 0, 16, 0, 54, 0, 100, 0, 0, 0, 0, 0, 49, 0, 0, 0, 0, 0, 0, 19, 19671, 0, 0, 0, 0, 0, 0, 'Ethereal Sorcerer - On Just Summoned - Start Attack'), +(18315, 0, 5, 0, 54, 0, 100, 0, 0, 0, 0, 0, 49, 0, 0, 0, 0, 0, 0, 19, 19671, 0, 0, 0, 0, 0, 0, 'Ethereal Theurgist - On Just Summoned - Start Attack'), +(19307, 0, 4, 0, 54, 0, 100, 0, 0, 0, 0, 0, 49, 0, 0, 0, 0, 0, 0, 19, 19671, 0, 0, 0, 0, 0, 0, 'Nexus Terror - On Just Summoned - Start Attack'), +(19672, 0, 0, 1, 54, 0, 100, 0, 0, 0, 0, 0, 80, 1967200, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Consortium Laborer - On Just Summoned - Run Script'), +(19673, 0, 0, 1, 54, 0, 100, 0, 0, 0, 0, 0, 80, 1967200, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Consortium Engineer - On Just Summoned - Run Script'), +(19672, 0, 1, 0, 61, 0, 100, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Consortium Laborer - On Just Summoned - Set Emote State'), +(19673, 0, 1, 0, 61, 0, 100, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Consortium Engineer - On Just Summoned - Set Emote State'), +(19666, 0, 1, 0, 54, 0, 100, 0, 0, 0, 0, 0, 80, 1966600, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Shadow Lord Xiraxis - On Just Summoned - Run Script'), +(19666, 0, 2, 0, 6, 0, 100, 0, 0, 0, 0, 0, 45, 1, 1, 0, 0, 0, 0, 19, 19671, 0, 0, 0, 0, 0, 0, 'Shadow Lord Xiraxis - On Death - Set Data'), +(19671, 0, 0, 0, 11, 0, 100, 0, 0, 0, 0, 0, 80, 1967100, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - On Just Summoned - Run Script'), +(19671, 0, 1, 2, 19, 0, 100, 1, 10218, 0, 0, 0, 64, 1, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - On Quest Accept Ancient Spirit - Store Targetlist'), +(19671, 0, 2, 0, 61, 0, 100, 0, 10218, 0, 0, 0, 80, 1967101, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - On Quest Accept Ancient Spirit - Store Targetlist'), +(19671, 0, 3, 0, 40, 0, 100, 0, 1, 1967101, 0, 0, 1, 4, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - On Reached WP2 (Path 2) - Say Line 4'), +(19671, 0, 4, 0, 40, 0, 100, 0, 2, 1967101, 0, 0, 80, 1967102, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - On Reached WP4 (Path 2) - Run Script 3'), +(19671, 0, 5, 0, 40, 0, 100, 0, 9, 1967101, 0, 0, 80, 1967103, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - On Reached WP11 (Path 2) - Run Script 4'), +(19671, 0, 6, 7, 40, 0, 100, 0, 16, 1967101, 0, 0, 1, 8, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - On Reached WP18 (Path 2) - Say Line 8'), +(19671, 0, 7, 0, 61, 0, 100, 0, 0, 0, 0, 0, 54, 7000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - On Reached WP18 (Path 2) - Pause WP'), +(19671, 0, 8, 20, 40, 0, 100, 0, 17, 1967101, 0, 0, 1, 9, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - On Reached WP19 (Path 2) - Say Line 9'), +(19671, 0, 9, 0, 40, 0, 100, 0, 20, 1967101, 0, 0, 80, 1967104, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - On Reached WP22 (Path 2) - Run Script 5'), +(19671, 0, 10, 0, 40, 0, 100, 0, 31, 1967101, 0, 0, 80, 1967108, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - On Reached WP29 (Path 2) - Run Script 9'), +(19671, 0, 13, 0, 40, 0, 100, 0, 36, 1967101, 0, 0, 80, 1967105, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - On Reached WP34 (Path 2) - Run Script 6'), +(19671, 0, 14, 0, 40, 0, 100, 0, 43, 1967101, 0, 0, 80, 1967106, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - On Reached WP41 (Path 2) - Run Script 7'), +(19671, 0, 15, 0, 6, 0, 100, 0, 0, 0, 0, 0, 6, 10218, 0, 0, 0, 0, 0, 12, 1, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - On Death - Fail Quest'), +(19671, 0, 16, 0, 38, 0, 100, 0, 1, 1, 0, 0, 80, 1967107, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - On Data Set - Run Script 8'), +(19671, 0, 17, 0, 0, 1, 100, 0, 2000, 3000, 3000, 5000, 11, 13901, 64, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - IC (Phase 1) - Cast Arcane Bolt'), +(19671, 0, 18, 0, 9, 1, 100, 0, 0, 10, 15000, 23000, 11, 22938, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - On Range (Phase 1) - Cast Arcane Explosion'), +(19671, 0, 19, 0, 4, 1, 100, 0, 0, 0, 0, 0, 11, 33839, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - On Agro (Phase 1) - Cast Vir aani Concentration'), +(19671, 0, 20, 0, 61, 0, 100, 0, 0, 0, 0, 0, 59, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Link - Turn run on'), +(19671, 0, 22, 0, 40, 0, 100, 0, 5, 1967101, 0, 0, 59, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - On Reached WP5 Turn run on'), +(19671, 0, 23, 0, 40, 0, 100, 0, 12, 1967101, 0, 0, 59, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - On reached WP12 - Turn run off'), +(19671, 0, 24, 0, 40, 0, 100, 0, 15, 1967101, 0, 0, 59, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - On reached WP15 - Turn run off'), +(19671, 0, 25, 0, 40, 0, 100, 0, 4, 1967101, 0, 0, 81, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - On Reached WP4 - Set NPC Flags'), +(19671, 0, 26, 0, 25, 0, 100, 0, 0, 0, 0, 0, 22, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - On Reset - Set Phase 1'), +(1966600, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Shadow Lord Xiraxis - Script - Say Line 0'), +(1966600, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 18, 768, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Shadow Lord Xiraxis - Script - Set Unit Flags'), +(1966600, 9, 2, 0, 0, 0, 100, 0, 0, 0, 0, 0, 53, 1, 19666, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Shadow Lord Xiraxis - Script - Start WP'), +(1966600, 9, 3, 0, 0, 0, 100, 0, 12000, 12000, 0, 0, 1, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Shadow Lord Xiraxis - Script - Say Line 1'), +(1966600, 9, 4, 0, 0, 0, 100, 0, 7000, 7000, 0, 0, 1, 14, 0, 0, 0, 0, 0, 19, 19671, 0, 0, 0, 0, 0, 0, 'Shadow Lord Xiraxis - Script - Say Line 14 on Cryo-Engineer Sha heen'), +(1966600, 9, 5, 0, 0, 0, 100, 0, 7000, 7000, 0, 0, 1, 3, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Shadow Lord Xiraxis - Script - Say Line 2'), +(1966600, 9, 6, 0, 0, 0, 100, 0, 0, 0, 0, 0, 19, 768, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Shadow Lord Xiraxis - Script - Set Unit Flags'), +(1966600, 9, 7, 0, 0, 0, 100, 0, 0, 0, 0, 0, 2, 16, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Shadow Lord Xiraxis - Script - Set Hostile'), +(1966600, 9, 8, 0, 0, 0, 100, 0, 0, 0, 0, 0, 8, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Shadow Lord Xiraxis - Script - Set Aggressive'), +(1966600, 9, 9, 0, 0, 0, 100, 0, 0, 0, 0, 0, 49, 0, 0, 0, 0, 0, 0, 19, 19671, 0, 0, 0, 0, 0, 0, 'Shadow Lord Xiraxis - Script - Start Attack'), +(1967200, 9, 0, 0, 0, 0, 100, 0, 500, 500, 0, 0, 11, 12980, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Consortium Laborer - Script - Cast Simple Teleport'), +(1967100, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 22, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script - Set Phase 2'), +(1967100, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 81, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script - Rempve NPC Flags'), +(1967100, 9, 2, 0, 0, 0, 100, 0, 0, 0, 0, 0, 11, 33839, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script - Cast Vir aani Concentration'), +(1967100, 9, 3, 0, 0, 0, 100, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script - Say Line 0'), +(1967100, 9, 4, 0, 0, 0, 100, 0, 5000, 5000, 0, 0, 1, 1, 0, 0, 0, 0, 0, 21, 100, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script - Say Line 1'), +(1967100, 9, 5, 0, 0, 0, 100, 0, 5000, 5000, 0, 0, 53, 0, 1967100, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script - Start WP'), +(1967100, 9, 6, 0, 0, 0, 100, 0, 5000, 5000, 0, 0, 1, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script - Say Line 1'), +(1967100, 9, 7, 0, 0, 0, 100, 0, 0, 0, 0, 0, 17, 234, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script - Set Emote State'), +(1967100, 9, 8, 0, 0, 0, 100, 0, 4000, 4000, 0, 0, 17, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script - Set Emote State'), +(1967100, 9, 9, 0, 0, 0, 100, 0, 0, 0, 0, 0, 81, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script - Set NPC Flags'), +(1967100, 9, 10, 0, 0, 0, 100, 0, 0, 0, 0, 0, 107, 4, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script - Summon Group 4'), +(1967100, 9, 11, 0, 0, 0, 100, 0, 0, 0, 0, 0, 20, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script - Disable Auto Attack'), +(1967100, 9, 12, 0, 0, 0, 100, 0, 0, 0, 0, 0, 22, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script - Set Phase 1'), +(1967101, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 1, 3, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script 2 - Say Line 3'), +(1967101, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 2, 495, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script 2 - Set Faction'), +(1967101, 9, 2, 0, 0, 0, 100, 0, 5000, 5000, 0, 0, 53, 0, 1967101, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script 2 - Start WP'), +(1967102, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 22, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script 3 - Set Phase 2'), +(1967102, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script 3 - Disable Combat Movement'), +(1967102, 9, 2, 0, 0, 0, 100, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script 3 - Set Passive'), +(1967102, 9, 3, 0, 0, 0, 100, 0, 0, 0, 0, 0, 54, 10000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script 3 - Pause WP'), +(1967102, 9, 4, 0, 0, 0, 100, 0, 0, 0, 0, 0, 17, 233, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script 3 - Set Emotestate'), +(1967102, 9, 5, 0, 0, 0, 100, 0, 10000, 10000, 0, 0, 17, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script 3 - Set Emotestate'), +(1967102, 9, 6, 0, 0, 0, 100, 0, 0, 0, 0, 0, 21, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script 3 - Enable Combat Movement'), +(1967102, 9, 7, 0, 0, 0, 100, 0, 0, 0, 0, 0, 22, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script 3 - Set Phase 1'), +(1967102, 9, 8, 0, 0, 0, 100, 0, 0, 0, 0, 0, 1, 5, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script 3 - Say Line 5'), +(1967102, 9, 9, 0, 0, 0, 100, 0, 0, 0, 0, 0, 8, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script 3 - Set Defensive'), +(1967102, 9, 10, 0, 0, 0, 100, 0, 0, 0, 0, 0, 59, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script 3 - Turn Run Off'), +(1967103, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 22, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script 4 - Set Phase 2'), +(1967103, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script 4 - Disable Combat Movemet'), +(1967103, 9, 2, 0, 0, 0, 100, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script 4 - Set Passive'), +(1967103, 9, 3, 0, 0, 0, 100, 0, 0, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0.2617994, 'Cryo-Engineer Sha heen - Script 4 - Set Orientation'), +(1967103, 9, 4, 0, 0, 0, 100, 0, 0, 0, 0, 0, 54, 10000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script 4 - Pause WP'), +(1967103, 9, 5, 0, 0, 0, 100, 0, 0, 0, 0, 0, 17, 233, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script 4 - Set Emotestate'), +(1967103, 9, 6, 0, 0, 0, 100, 0, 0, 0, 0, 0, 1, 6, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script 4 - Say Line 6'), +(1967103, 9, 7, 0, 0, 0, 100, 0, 0, 0, 0, 0, 107, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script 4 - Summon Group 0'), +(1967103, 9, 8, 0, 0, 0, 100, 0, 10000, 10000, 0, 0, 1, 7, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script 4 - Say Line 6'), +(1967103, 9, 9, 0, 0, 0, 100, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script 4 - Set Emotestate'), +(1967103, 9, 10, 0, 0, 0, 100, 0, 0, 0, 0, 0, 22, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script 4 - Set Phase 1'), +(1967103, 9, 11, 0, 0, 0, 100, 0, 0, 0, 0, 0, 8, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script 4 - Set Defensive'), +(1967103, 9, 12, 0, 0, 0, 100, 0, 0, 0, 0, 0, 21, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script 4 - Enable Combat Movemet'), +(1967103, 9, 13, 0, 0, 0, 100, 0, 0, 0, 0, 0, 59, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script 4 - Set Run Off'), +(1967104, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 22, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script 5 - Set Phase 2'), +(1967104, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script 5 - Set Passive'), +(1967104, 9, 2, 0, 0, 0, 100, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script 5 - Disable Combat Movement'), +(1967104, 9, 3, 0, 0, 0, 100, 0, 0, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0.1396263, 'Cryo-Engineer Sha heen - Script 5 - Set Orientation'), +(1967104, 9, 4, 0, 0, 0, 100, 0, 0, 0, 0, 0, 54, 10000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script 5 - Pause WP'), +(1967104, 9, 5, 0, 0, 0, 100, 0, 0, 0, 0, 0, 17, 233, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script 5 - Set Emotestate'), +(1967104, 9, 6, 0, 0, 0, 100, 0, 0, 0, 0, 0, 107, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script 4 - Summon Group 1'), +(1967104, 9, 7, 0, 0, 0, 100, 0, 10000, 10000, 0, 0, 17, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script 5 - Set Emotestate'), +(1967104, 9, 8, 0, 0, 0, 100, 0, 0, 0, 0, 0, 21, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script 5 - Enable Combat Movement'), +(1967104, 9, 9, 0, 0, 0, 100, 0, 0, 0, 0, 0, 22, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script 5 - Set Phase 1'), +(1967104, 9, 10, 0, 0, 0, 100, 0, 0, 0, 0, 0, 8, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script 5 - Set Defensive'), +(1967104, 9, 11, 0, 0, 0, 100, 0, 0, 0, 0, 0, 59, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script 5 - Turn run off'), +(1967105, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 22, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script 6 - Set Phase 2'), +(1967105, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script 6 - Set Passive'), +(1967105, 9, 2, 0, 0, 0, 100, 0, 0, 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script 6 - Disable Combat Movement'), +(1967105, 9, 3, 0, 0, 0, 100, 0, 0, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 6.091199, 'Cryo-Engineer Sha heen - Script 6 - Set Orientation'), +(1967105, 9, 4, 0, 0, 0, 100, 0, 0, 0, 0, 0, 54, 30000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script 6 - Pause WP'), +(1967105, 9, 5, 0, 0, 0, 100, 0, 0, 0, 0, 0, 17, 233, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script 6 - Set Emotestate'), +(1967105, 9, 6, 0, 0, 0, 100, 0, 0, 0, 0, 0, 1, 11, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script 5 - Say Line 11'), +(1967105, 9, 7, 0, 0, 0, 100, 0, 10000, 10000, 0, 0, 17, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script 6 - Set Emotestate'), +(1967105, 9, 8, 0, 0, 0, 100, 0, 0, 0, 0, 0, 8, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script 6 - Set Defensive'), +(1967105, 9, 9, 0, 0, 0, 100, 0, 0, 0, 0, 0, 22, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script 6 - Set Phase 1'), +(1967105, 9, 10, 0, 0, 0, 100, 0, 0, 0, 0, 0, 21, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script 6 - Enable Combat Movement'), +(1967105, 9, 11, 0, 0, 0, 100, 0, 10000, 10000, 0, 0, 1, 12, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script 6 - Say Line 12'), +(1967105, 9, 12, 0, 0, 0, 100, 0, 10000, 10000, 0, 0, 1, 13, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script 6 - Say Line 13'), +(1967105, 9, 13, 0, 0, 0, 100, 0, 0, 0, 0, 0, 59, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script 5 - Say Line 11'), +(1967106, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 54, 10000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script 7 - Pause WP'), +(1967106, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 107, 3, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script 7 - Summon Group 3'), +(1967106, 9, 2, 0, 0, 0, 100, 0, 0, 0, 0, 0, 101, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script 7 - Summon Group 3'), +(1967107, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 15, 10218, 0, 0, 0, 0, 0, 12, 1, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script 8 - Complete Quest'), +(1967107, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 1, 15, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script 8 - Say Line 15'), +(1967107, 9, 2, 0, 0, 0, 100, 0, 7000, 7000, 0, 0, 1, 16, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script 8 - Say Line 16'), +(1967107, 9, 3, 0, 0, 0, 100, 0, 0, 0, 0, 0, 41, 15000, 0, 0, 0, 0, 0, 9, 19672, 0, 100, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script 8 - Despawn'), +(1967107, 9, 4, 0, 0, 0, 100, 0, 0, 0, 0, 0, 41, 15000, 0, 0, 0, 0, 0, 9, 19673, 0, 100, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script 8 - Despawn'), +(1967107, 9, 5, 0, 0, 0, 100, 0, 0, 0, 0, 0, 41, 15000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script 8 - Despawn'), +(1967108, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 1, 10, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script 9 - Say Line 10'), +(1967108, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 107, 5, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script 9 - Summon Group 5'), +(1967108, 9, 2, 0, 0, 0, 100, 0, 8000, 8000, 0, 0, 107, 2, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script 9 - SUmmon Group 2'), +(1967108, 9, 3, 0, 0, 0, 100, 0, 0, 0, 0, 0, 59, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Cryo-Engineer Sha heen - Script 9 - Turn Run On'); + + + + + +DELETE FROM `creature_text` WHERE `entry`=19666 AND `groupid`>0 AND `id`=0; + +DELETE FROM `creature_text` WHERE `entry`=19671; +INSERT INTO `creature_text` (`entry`, `groupid`, `id`, `text`, `type`, `language`, `probability`, `emote`, `duration`, `sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES +(19671, 0, 0, '%s checks to make sure his body is intact.', 16, 0, 100, 0, 0, 0, 17228, 0, 'Cryo-Engineer Sha heen'), +(19671, 1, 0, 'You made it! Well done, $r. Now if you''ll excuse me, I have to get the rest of our crew inside.', 12, 0, 100, 1, 0, 0, 17229, 0, 'Cryo-Engineer Sha heen'), +(19671, 2, 0, '%s expertly manipulates the control panel.', 16, 0, 100, 0, 0, 0, 17230, 0, 'Cryo-Engineer Sha heen'), +(19671, 3, 0, 'Let''s not waste any time! Take anything that isn''t nailed down to the floor and teleport directly to Stormspire! Chop chop!', 12, 0, 100, 1, 0, 0, 17231, 0, 'Cryo-Engineer Sha heen'), +(19671, 4, 0, 'This should''t take very long. Just watch my back as I empty these nether collectors.', 12, 0, 100, 1, 0, 0, 17246, 0, 'Cryo-Engineer Sha heen'), +(19671, 5, 0, 'Fantastic! Let''s move on, shall we?', 12, 0, 100, 1, 0, 0, 17248, 0, 'Cryo-Engineer Sha heen'), +(19671, 6, 0, 'Looking at these energy levels, Shaffar was set to make a killing!', 12, 0, 100, 1, 0, 0, 17249, 0, 'Cryo-Engineer Sha heen'), +(19671, 7, 0, 'That should do it...', 12, 0, 100, 1, 0, 0, 17251, 0, 'Cryo-Engineer Sha heen'), +(19671, 8, 0, 'Hrm, now where is the next collector?', 12, 0, 100, 1, 0, 0, 17252, 0, 'Cryo-Engineer Sha heen'), +(19671, 9, 0, 'Ah, there it is. Follow me, fleshling.', 12, 0, 100, 1, 0, 0, 17254, 0, 'Cryo-Engineer Sha heen'), +(19671, 10, 0, 'What do we have here? I thought you said the area was secure? This is now the third attack? If we make it out of here, I will definitely be deducting this from your reward. Now don''t just stand there, destroy them so I can get to that collector.', 12, 0, 100, 1, 0, 0, 17256, 0, 'Cryo-Engineer Sha heen'), +(19671, 11, 0, 'We''re close to the exit. I''ll let you rest for about thirty seconds, but then we''re out of here.', 12, 0, 100, 1, 0, 0, 17258, 0, 'Cryo-Engineer Sha heen'), +(19671, 12, 0, 'Are you ready to go?', 12, 0, 100, 1, 0, 0, 17260, 0, 'Cryo-Engineer Sha heen'), +(19671, 13, 0, 'Ok break time is OVER. Let''s go!', 12, 0, 100, 1, 0, 0, 17261, 0, 'Cryo-Engineer Sha heen'), +(19671, 14, 0, 'Oh really? And what might that be?', 12, 0, 100, 1, 0, 0, 17263, 0, 'Cryo-Engineer Sha heen'), +(19671, 15, 0, 'He was right, you know. I''ll have to take that tag-line for my own… It''s not like he''ll have a use for it anymore!', 12, 0, 100, 1, 0, 0, 17264, 0, 'Cryo-Engineer Sha heen'), +(19671, 16, 0, 'Thanks and good luck!', 12, 0, 100, 1, 0, 0, 17265, 0, 'Cryo-Engineer Sha heen'), +(19666, 1, 0, 'Bravo! Bravo! Good show… I couldn''t convince you to work for me, could I? No, I suppose the needless slaughter of my employees might negatively impact your employment application.', 14, 0, 100, 0, 0, 0, 17241, 0, 'Shadow Lord Xiraxis'), +(19666, 2, 0, 'Your plan was a good one, Sha''heen, and you would have gotten away with it if not for one thing...', 12, 0, 100, 327, 0, 0, 17243, 0, 'Shadow Lord Xiraxis'), +(19666, 3, 0, 'Never underestimate the other ethereal''s greed!', 12, 0, 100, 1, 0, 0, 17244, 0, 'Shadow Lord Xiraxis'); + +DELETE FROM `waypoints` WHERE `entry` IN(1967100,1967101,19666); +INSERT INTO `waypoints` (`entry`, `pointid`, `position_x`, `position_y`, `position_z`, `point_comment`) VALUES +(19666, 1, -68.40214, -19.7878, -0.9529961, 'Shadow Lord Xiraxis'), +(19666, 2, -67.83204, -48.33409, -0.9552881, 'Shadow Lord Xiraxis'), +(19666, 3, -67.78506, -75.71738, -0.9389226, 'Shadow Lord Xiraxis'), +(1967100, 1, -354.443, -65.6078, -0.9741728, 'Cryo-Engineer Sha heen'), +(1967101, 1, -366.7985 ,-72.95073 ,-0.1383943, 'Cryo-Engineer Sha heen'), +(1967101, 2, -370.5689 ,-73.03973 ,0.7014256, 'Cryo-Engineer Sha heen'), +(1967101, 3, -363.5802 ,-72.44846 ,-0.9587624, 'Cryo-Engineer Sha heen'), +(1967101, 4, -371.8158 ,-86.79798 ,-0.958762, 'Cryo-Engineer Sha heen'), +(1967101, 5, -372.8067 ,-115.3902 ,-0.9587386, 'Cryo-Engineer Sha heen'), +(1967101, 6, -373.5266 ,-149.3968 ,-0.9787918, 'Cryo-Engineer Sha heen'), +(1967101, 7, -382.3674 ,-163.1939 ,-0.9493812, 'Cryo-Engineer Sha heen'), +(1967101, 8, -378.7728 ,-164.4431 ,-0.1216383, 'Cryo-Engineer Sha heen'), +(1967101, 9, -375.3421 ,-164.1911 ,0.7157794, 'Cryo-Engineer Sha heen'), +(1967101, 10, -377.8079 ,-164.3831 ,0.09416915, 'Cryo-Engineer Sha heen'), +(1967101, 11, -381.8036 ,-167.0499 ,-0.9587629, 'Cryo-Engineer Sha heen'), +(1967101, 12, -374.2704 ,-195.67 ,-0.9876157, 'Cryo-Engineer Sha heen'), +(1967101, 13, -371.0522 ,-221.1154 ,-0.957548, 'Cryo-Engineer Sha heen'), +(1967101, 14, -357.3525 ,-224.1118 ,-0.9591594, 'Cryo-Engineer Sha heen'), +(1967101, 15, -327.2074 ,-223.1011 ,-0.958185, 'Cryo-Engineer Sha heen'), +(1967101, 16, -317.373 ,-220.9346 ,-0.953047, 'Cryo-Engineer Sha heen'), +(1967101, 17, -302.139 ,-201.6109 ,-0.9018583, 'Cryo-Engineer Sha heen'), +(1967101, 18, -291.9838 ,-190.2706 ,-0.9321695, 'Cryo-Engineer Sha heen'), +(1967101, 19, -272.2044 ,-165.1142 ,-1.962067, 'Cryo-Engineer Sha heen'), +(1967101, 20, -260.8738 ,-158.3423 ,-1.20301, 'Cryo-Engineer Sha heen'), +(1967101, 21, -260.8686 ,-160.7864 ,-1.202524, 'Cryo-Engineer Sha heen'), +(1967101, 22, -246.7021 ,-160.2355 ,-0.9534798, 'Cryo-Engineer Sha heen'), +(1967101, 23, -238.4669 ,-174.3582 ,-0.953746, 'Cryo-Engineer Sha heen'), +(1967101, 24, -237.8523 ,-188.0232 ,-0.9510807, 'Cryo-Engineer Sha heen'), +(1967101, 25, -218.7323 ,-207.1752 ,0.04777823, 'Cryo-Engineer Sha heen'), +(1967101, 26, -207.835, -211.8027, 1.176572, 'Cryo-Engineer Sha heen'), +(1967101, 27, -195.085, -217.8027, 0.4265722, 'Cryo-Engineer Sha heen'), +(1967101, 28, -190.835, -219.5527, -0.5734278, 'Cryo-Engineer Sha heen'), +(1967101, 29, -183.5801 ,-223.2924 ,-0.9551997, 'Cryo-Engineer Sha heen'), +(1967101, 30, -147.253 ,-222.2017 ,-0.7159179, 'Cryo-Engineer Sha heen'), +(1967101, 31, -114.5249 ,-221.926 ,0.4013355, 'Cryo-Engineer Sha heen'), +(1967101, 32, -89.60782 ,-222.852 ,-0.5187308, 'Cryo-Engineer Sha heen'), +(1967101, 33, -67.58874 ,-223.6537 ,-0.405379, 'Cryo-Engineer Sha heen'), +(1967101, 34, -56.8648 ,-223.1615 ,0.02639319, 'Cryo-Engineer Sha heen'), +(1967101, 35, -20.5673 ,-224.0332 ,0.5167194, 'Cryo-Engineer Sha heen'), +(1967101, 36, -12.58579 ,-222.5067 ,1.786049, 'Cryo-Engineer Sha heen'), +(1967101, 37, -29.4036 ,-223.2606 ,0.01665334, 'Cryo-Engineer Sha heen'), +(1967101, 38, -53.08645 ,-219.6514 ,0.2137061, 'Cryo-Engineer Sha heen'), +(1967101, 39, -64.90977 ,-210.4424 ,-0.292502, 'Cryo-Engineer Sha heen'), +(1967101, 40, -66.85043 ,-179.138 ,-1.307152, 'Cryo-Engineer Sha heen'), +(1967101, 41, -67.13032 ,-133.7884 ,-1.034937, 'Cryo-Engineer Sha heen'), +(1967101, 42, -67.16659 ,-112.9431 ,-0.7426757, 'Cryo-Engineer Sha heen'), +(1967101, 43, -67.0159 ,-87.2571 ,-1.276771, 'Cryo-Engineer Sha heen'); + +DELETE FROM `creature_summon_groups` WHERE `summonerId`=19671; +INSERT INTO `creature_summon_groups` (`summonerId`, `summonerType`, `groupId`, `entry`, `position_x`, `position_y`, `position_z`, `orientation`, `summonType`, `summonTime`) VALUES +(19671, 0, 0, 18312, -370.7318, -134.3002, -0.9618373, 4.572175, 6, 60000), +(19671, 0, 0, 18315, -374.4721, -194.6065, -0.9929181, 1.529337, 6, 60000), +(19671, 0, 0, 18312, -369.9984, -194.276, -0.9705924, 1.623082, 6, 60000), +(19671, 0, 0, 18315, -375.2323, -133.8772, -0.968161, 4.922849, 6, 60000), +(19671, 0, 1, 18311, -238.7594, -186.9294, -0.9510754, 1.999699, 6, 60000), +(19671, 0, 1, 18313, -225.0942, -172.4903, -1.055191, 2.76561, 6, 60000), +(19671, 0, 1, 18313, -288.748, -178.6396, -0.5875124, 0.6407801, 6, 60000), +(19671, 0, 1, 18313, -283.9628, -188.2815, -0.3590364, 0.9258388, 6, 60000), +(19671, 0, 2, 19307, -13.30131, -220.9802, 0.8455964, 3.126897, 6, 60000), +(19671, 0, 3, 19666, -36.36667, 1.317166, -0.9543327, 3.285605, 6, 60000), +(19671, 0, 4, 19673, -386.8928, -60.84314, -0.8754397, 3.368485, 6, 60000), +(19671, 0, 4, 19672, -386.847, -72.83556, -0.8754347, 2.635447, 6, 60000), +(19671, 0, 4, 19673, -375.7296, -88.8795, -0.8754307, 3.385939, 6, 60000), +(19671, 0, 4, 19672, -360.1015, -67.55888, -0.8754327, 0.2094395, 6, 60000), +(19671, 0, 4, 19673, -358.8426, -74.0751, -0.8726627, 0.6806784, 6, 60000), +(19671, 0, 4, 19672, -370.8748, -82.77579, -0.8754287, 0.08726646, 6, 60000), +(19671, 0, 4, 19673, -374.6943, -63.50459, -0.8754317, 0.5759587, 6, 60000), +(19671, 0, 4, 19672, -358.8426, -74.0751, -0.8726627, 0.6806784, 6, 60000), +(19671, 0, 4, 19673, -375.8055, -86.87415, -0.9587618, 1.608575, 6, 60000), +(19671, 0, 4, 19673, -386.8928, -60.84314, -0.8754397, 3.368485, 6, 60000), +(19671, 0, 5, 19307, -47.63387, -223.8948, -0.1993168, 3.440399, 6, 60000); diff --git a/sql/updates/world/3.3.5/2016_05_28_03_world.sql b/sql/updates/world/3.3.5/2016_05_28_03_world.sql new file mode 100644 index 00000000000..69ee8803260 --- /dev/null +++ b/sql/updates/world/3.3.5/2016_05_28_03_world.sql @@ -0,0 +1,25 @@ +UPDATE `creature_template` SET `InhabitType`=4 WHERE `entry`=22139; +UPDATE `smart_scripts` SET `target_param1`=22139, `target_param2`=100, `action_param2`=64 WHERE `entryorguid`=22138 AND `source_type`=0 AND `id`=0; +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceGroup`=1 AND `SourceEntry`=38469 AND `ElseGroup`=0; +DELETE FROM `gameobject` WHERE `id`=184750; +UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry` IN (22137); +DELETE FROM `smart_scripts` WHERE `entryorguid` IN (22137) AND `source_type`=0; +DELETE FROM `smart_scripts` WHERE `entryorguid` IN (22138) AND `source_type`=0 AND id IN(1,2); + +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(22137, 0, 0, 0, 25, 0, 100, 0, 0, 0, 0, 0, 75, 38457, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,0,'Summoned Old God - On reset - Add Transparency'), +(22137, 0, 1, 0, 1, 8, 100, 0, 0, 0, 240000, 240000, 50, 184750, 240, 0, 0, 0, 0, 8, 0, 0, 0, -4161.259277, 1985.773804, 59.094448, 6.210211,'Summoned Old God - OOC (Phase 4) - spawn spell focus'), +(22137, 0, 2, 0, 38, 0, 100, 0, 1, 1, 0, 0, 23, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,'Summoned Old God - On Data Set 1 1 - Increment Phase'), +(22137, 0, 3, 0, 38, 0, 100, 0, 2, 2, 0, 0, 22, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,'Summoned Old God - On Data Set 2 2 - Set Phase 0'), +(22137, 0, 4, 0, 11, 0, 100, 0, 0, 0, 0, 0, 48, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,'Summoned Old God - On Spawn Set Active'), +(22137, 0, 5, 6, 8, 0, 100, 0, 38482, 0, 0, 0, 33, 22137, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0,'Summoned Old God - On Spellhit - Give Kill Credit'), +(22137, 0, 6, 7, 61, 0, 0, 0, 0, 0, 0, 0, 11, 37281, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,'Summoned Old God - On Spellhit - Cast Infernal Oversouls Wrath'), +(22137, 0, 7, 8, 61, 0, 0, 0, 0, 0, 0, 0, 41, 1000, 0, 0, 0, 0, 0, 19, 22146, 0, 0, 0, 0, 0, 0,'Summoned Old God - On Spellhit - Despawn Summoning Voidstorm'), +(22138, 0, 1, 0, 6, 0, 100, 0, 0, 0, 0, 0, 45, 1, 1, 0, 0, 0, 0, 19, 22137, 100, 0, 0, 0, 0,0,'Dark Conclave Ritualist - On Death - Set Data'), +(22138, 0, 2, 0, 11, 0, 100, 0, 0, 0, 0, 0, 45, 2, 2, 0, 0, 0, 0, 19, 22137, 100, 0, 0, 0, 0,0,'Dark Conclave Ritualist - On Respawn - Set Data'); + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceGroup`=1 AND `SourceEntry`=37281 AND `SourceId`=0 AND `ElseGroup`IN(2,3); + +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES +(13, 1, 37281, 0, 2, 31, 0, 3, 22137, 0, 0, 0, 0, '', 'Infernal Oversouls Wrath targets Summoned Old God'), +(13, 1, 37281, 0, 3, 31, 0, 3, 22146, 0, 0, 0, 0, '', 'Infernal Oversouls Wrath targets Summoning Voidstorm'); diff --git a/sql/updates/world/3.3.5/2016_05_30_00_world.sql b/sql/updates/world/3.3.5/2016_05_30_00_world.sql new file mode 100644 index 00000000000..b6fdc5f3b89 --- /dev/null +++ b/sql/updates/world/3.3.5/2016_05_30_00_world.sql @@ -0,0 +1,2 @@ +-- +UPDATE `quest_template_addon` SET `ExclusiveGroup` = 11211 WHERE `ID` IN (11211,11214,11215); diff --git a/sql/updates/world/3.3.5/2016_05_30_01_world.sql b/sql/updates/world/3.3.5/2016_05_30_01_world.sql new file mode 100644 index 00000000000..a18ffe23ed5 --- /dev/null +++ b/sql/updates/world/3.3.5/2016_05_30_01_world.sql @@ -0,0 +1,2 @@ +-- +UPDATE `quest_template_addon` SET `PrevQuestID`=0 WHERE `ID`=11261; diff --git a/sql/updates/world/3.3.5/2016_05_30_02_world.sql b/sql/updates/world/3.3.5/2016_05_30_02_world.sql new file mode 100644 index 00000000000..2742f9c8ca9 --- /dev/null +++ b/sql/updates/world/3.3.5/2016_05_30_02_world.sql @@ -0,0 +1,2 @@ +-- +DELETE FROM `quest_template_addon` WHERE `MaxLevel` = 0 AND `AllowableClasses` = 0 AND `SourceSpellID` = 0 AND `PrevQuestID` = 0 AND `NextQuestID` = 0 AND `ExclusiveGroup` = 0 AND `RewardMailTemplateID` = 0 AND `RewardMailDelay` = 0 AND `RequiredSkillID` = 0 AND `RequiredSkillPoints` = 0 AND `RequiredMinRepFaction` = 0 AND `RequiredMaxRepFaction` = 0 AND `RequiredMinRepValue` = 0 AND `RequiredMaxRepValue` = 0 AND `ProvidedItemCount` = 0 AND `SpecialFlags` = 0; diff --git a/sql/updates/world/3.3.5/2016_05_30_03_world.sql b/sql/updates/world/3.3.5/2016_05_30_03_world.sql new file mode 100644 index 00000000000..eeaa7bf6d7b --- /dev/null +++ b/sql/updates/world/3.3.5/2016_05_30_03_world.sql @@ -0,0 +1,7 @@ +-- +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry`=50232; +INSERT INTO `conditions` VALUES +(13, 1, 50232, 0, 1, 31, 0, 3, 28236, 0, 0, 0, 0, "", "Searing Wrath target can be Azure Ring Captain"), +(13, 1, 50232, 0, 2, 31, 0, 3, 27638, 0, 0, 0, 0, "", "Searing Wrath target can be Azure Ring Guardian"), +(13, 1, 50232, 0, 3, 31, 0, 3, 28276, 0, 0, 0, 0, "", "Searing Wrath target can be Greater Lay Whelp"), +(13, 1, 50232, 0, 4, 31, 0, 3, 27656, 0, 0, 0, 0, "", "Searing Wrath target can be Eregos"); diff --git a/sql/updates/world/3.3.5/2016_05_30_04_world.sql b/sql/updates/world/3.3.5/2016_05_30_04_world.sql new file mode 100644 index 00000000000..0fc9244c100 --- /dev/null +++ b/sql/updates/world/3.3.5/2016_05_30_04_world.sql @@ -0,0 +1,2 @@ +-- Change the Text <Name> to $N +UPDATE `quest_request_items` SET `CompletionText`= "Back so soon? In case I didn\'t make myself clear we need you to kill 10 Stonesplinter Shaman and 10 Stonesplinter Bonesnappers, $N. Now go get\'em, Trogg-Slayer!" WHERE `id` = 263; diff --git a/sql/updates/world/3.3.5/2016_05_30_05_world.sql b/sql/updates/world/3.3.5/2016_05_30_05_world.sql new file mode 100644 index 00000000000..7209b3d8745 --- /dev/null +++ b/sql/updates/world/3.3.5/2016_05_30_05_world.sql @@ -0,0 +1,3 @@ +-- +UPDATE `quest_template_addon` SET `SpecialFlags` = 1 WHERE `Id` = 13845; +DELETE FROM `conditions` WHERE `SourceEntry` = 46004 AND `SourceTypeOrReferenceId` = 10; diff --git a/sql/updates/world/3.3.5/2016_05_30_06_world.sql b/sql/updates/world/3.3.5/2016_05_30_06_world.sql new file mode 100644 index 00000000000..5c81fcd5419 --- /dev/null +++ b/sql/updates/world/3.3.5/2016_05_30_06_world.sql @@ -0,0 +1,12 @@ +-- +DELETE FROM `gameobject_queststarter` WHERE `quest` IN (4722,4723,4725,4727,4728,4730,4731,4732,4733); +INSERT INTO `gameobject_queststarter` VALUES +(176190, 4722), +(175233, 4723), +(176197, 4725), +(176196, 4727), +(175226, 4728), +(175227, 4730), +(176198, 4731), +(176191, 4732), +(175230, 4733); diff --git a/sql/updates/world/3.3.5/2016_05_30_07_world.sql b/sql/updates/world/3.3.5/2016_05_30_07_world.sql new file mode 100644 index 00000000000..c8130b023af --- /dev/null +++ b/sql/updates/world/3.3.5/2016_05_30_07_world.sql @@ -0,0 +1,2 @@ +-- +UPDATE `achievement_criteria_data` SET `value1`=8 WHERE `criteria_id`=4958 AND `type`=8; diff --git a/sql/updates/world/3.3.5/2016_05_30_08_world.sql b/sql/updates/world/3.3.5/2016_05_30_08_world.sql new file mode 100644 index 00000000000..134617b0380 --- /dev/null +++ b/sql/updates/world/3.3.5/2016_05_30_08_world.sql @@ -0,0 +1,4 @@ +-- +DELETE FROM `smart_scripts` WHERE `entryorguid`=17071 AND `source_type`=0; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(17071,0,0,0,20,0,100,0,9312,0,0,0,80,1707100,2,0,0,0,0,1,0,0,0,0,0,0,0,"Technician Zhanaa - On Quest 'The Emitter' Finished - Run Script"); diff --git a/sql/updates/world/3.3.5/2016_05_30_09_world.sql b/sql/updates/world/3.3.5/2016_05_30_09_world.sql new file mode 100644 index 00000000000..3ec588d0982 --- /dev/null +++ b/sql/updates/world/3.3.5/2016_05_30_09_world.sql @@ -0,0 +1,5 @@ +UPDATE `quest_template_addon` SET `SpecialFlags`=2 WHERE `ID`=1144; +UPDATE `creature_template` SET `flags_extra`=64 WHERE `entry` IN(28111,28112,28078,28079,23667, 23668, 32669,28844,28843,24199,24198,23564); +UPDATE `reference_loot_template` SET `GroupId`=2 WHERE `Entry`=34203 AND `Item`=43959; +UPDATE `smart_scripts` SET `target_type`=12, `target_param1`=1 WHERE `entryorguid`=2735500 AND `source_type`=9 AND `id`=5 AND `link`=0; +UPDATE `gameobject` SET `position_x`=5445.057129, `position_y`=4908.831543, `position_z`=-189.508224 WHERE `guid`=99748; diff --git a/sql/updates/world/3.3.5/2016_05_30_10_world.sql b/sql/updates/world/3.3.5/2016_05_30_10_world.sql new file mode 100644 index 00000000000..b8dbe0b94a6 --- /dev/null +++ b/sql/updates/world/3.3.5/2016_05_30_10_world.sql @@ -0,0 +1,26 @@ +DELETE FROM `gameobject_loot_template` WHERE `Entry`=26782; +INSERT INTO `gameobject_loot_template` (`Entry`, `Item`, `Reference`, `Chance`, `QuestRequired`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES +(26782, 44724, 0, 100, 0, 1, 1, 1, 1, NULL), -- Everfrost Chip +(26782, 44725, 0, 19, 0, 1, 2, 1, 1, NULL), -- Everfrost Chip (Quest Starter) +(26782, 44729, 0, 81, 0, 1, 2, 1, 1, NULL); -- Everfrost Powder + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=4 AND `SourceGroup`=26782; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES +(4, 26782, 44724, 0, 1, 8, 0, 13420, 0, 0, 0, 0, 0, '', NULL), -- Everfrost Chip only drops if player is rewarded for ever frost, +(4, 26782, 44729, 0, 0, 9, 0, 13420, 0, 0, 1, 0, 0, '', NULL), -- Everfrost powder only drops if player has not taken or completed Everfrost, +(4, 26782, 44729, 0, 0, 8, 0, 13420, 0, 0, 1, 0, 0, '', NULL), -- Everfrost powder only drops if player has not taken or completed Everfrost, +(4, 26782, 44725, 0, 0, 9, 0, 13420, 0, 0, 1, 0, 0, '', NULL), -- Everfrost Chip (Quest Starter) only drops if player has not taken or completed Everfrost, +(4, 26782, 44725, 0, 0, 8, 0, 13420, 0, 0, 1, 0, 0, '', NULL), -- Everfrost Chip (Quest Starter) only drops if player has not taken or completed Everfrost, +(4, 26782, 44725, 0, 0, 5, 0, 1119, 8, 0, 0, 0, 0, '', NULL); -- Everfrost Chip (Quest Starter) only drops if player is friendly with Sons of Hodir, + +UPDATE `quest_template_addon` SET `SpecialFlags`=1 WHERE `ID`=13421; + +DELETE FROM `creature_questender` WHERE `quest`=13421; +INSERT INTO `creature_questender` (`id`, `quest`) VALUES +(32594, 13421); + +DELETE FROM `creature_queststarter` WHERE `quest`=13421; +INSERT INTO `creature_queststarter` (`id`, `quest`) VALUES +(32594, 13421); + +UPDATE `quest_template_addon` SET `PrevQuestID`=13420 WHERE `ID`=13421; diff --git a/sql/updates/world/3.3.5/2016_05_31_00_world.sql b/sql/updates/world/3.3.5/2016_05_31_00_world.sql new file mode 100644 index 00000000000..29a29413167 --- /dev/null +++ b/sql/updates/world/3.3.5/2016_05_31_00_world.sql @@ -0,0 +1,6 @@ +-- +UPDATE `creature` SET `position_x`= -3739.09, `position_y`= 5405.21, `position_z`=-3.33350, `orientation`=2.70103, `MovementType`=0, `spawndist`=0 WHERE `guid`=78837 AND `id`=22464; +UPDATE `creature` SET `position_x`= -3743.46, `position_y`= 5403.87, `position_z`=-3.33635, `orientation`=1.16950, `MovementType`=0, `spawndist`=0 WHERE `guid`=78838 AND `id`=22464; +UPDATE `creature` SET `position_x`= -3746.42, `position_y`= 5405.33, `position_z`=-3.33737, `orientation`=0.39587, `MovementType`=0, `spawndist`=0 WHERE `guid`=78839 AND `id`=22464; +UPDATE `creature` SET `position_x`= -3750.65, `position_y`= 5408.94, `position_z`=-3.33391, `orientation`=2.54786, `MovementType`=0, `spawndist`=0 WHERE `guid`=78840 AND `id`=22464; +UPDATE `creature` SET `position_x`= -3741.11, `position_y`= 5403.61, `position_z`=-3.33493, `orientation`=1.9117 WHERE `guid`=78818 AND `id`=22458; diff --git a/sql/updates/world/3.3.5/2016_05_31_01_world_335.sql b/sql/updates/world/3.3.5/2016_05_31_01_world_335.sql new file mode 100644 index 00000000000..2d92a9fc537 --- /dev/null +++ b/sql/updates/world/3.3.5/2016_05_31_01_world_335.sql @@ -0,0 +1,9 @@ +-- +DELETE FROM `conditions` WHERE `SourceEntry` IN (6545, 6546, 6547) AND `SourceTypeOrReferenceId` IN (19, 20); +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES +(19, 0, 6545, 0, 0, 9, 0, 6543, 0, 0, 0, 0, 0, "", "Quest 'Warsong Runner Update' - Can accept if player has quest 'The Warsong Reports' in quest log"), +(20, 0, 6545, 0, 0, 9, 0, 6543, 0, 0, 0, 0, 0, "", "Quest 'Warsong Runner Update' - Can accept if player has quest 'The Warsong Reports' in quest log"), +(19, 0, 6546, 0, 0, 9, 0, 6543, 0, 0, 0, 0, 0, "", "Quest 'Warsong Outrider Update' - Can accept if player has quest 'The Warsong Reports' in quest log"), +(20, 0, 6546, 0, 0, 9, 0, 6543, 0, 0, 0, 0, 0, "", "Quest 'Warsong Outrider Update' - Can accept if player has quest 'The Warsong Reports' in quest log"), +(19, 0, 6547, 0, 0, 9, 0, 6543, 0, 0, 0, 0, 0, "", "Quest 'Warsong Scout Update' - Can accept if player has quest 'The Warsong Reports' in quest log"), +(20, 0, 6547, 0, 0, 9, 0, 6543, 0, 0, 0, 0, 0, "", "Quest 'Warsong Scout Update' - Can accept if player has quest 'The Warsong Reports' in quest log"); diff --git a/sql/updates/world/3.3.5/2016_05_31_02_world.sql b/sql/updates/world/3.3.5/2016_05_31_02_world.sql new file mode 100644 index 00000000000..09674385ab4 --- /dev/null +++ b/sql/updates/world/3.3.5/2016_05_31_02_world.sql @@ -0,0 +1,19 @@ +-- +UPDATE `creature` SET `spawndist`=0, `MovementType`=0, `unit_flags`=537133824 WHERE `guid` IN (103024, 103025, 103026, 103027, 103028); + +DELETE FROM `creature_addon` WHERE `guid` IN (103024, 103025, 103026, 103027, 103028); +INSERT INTO `creature_addon` (`guid`, `mount`, `bytes1`, `bytes2`, `auras`) VALUES +(103024, 0, 0x0, 0x1, '29266'), -- 25680 - 29266 - 29266 +(103025, 0, 0x0, 0x1, '29266'), -- 25680 - 29266 - 29266 +(103026, 0, 0x0, 0x1, '29266'), -- 25680 - 29266 - 29266 +(103027, 0, 0x0, 0x1, '29266'), -- 25680 - 29266 - 29266 +(103028, 0, 0x0, 0x1, '29266'); -- 25680 - 29266 - 29266 + +UPDATE `creature` SET `spawndist`=0, `MovementType`=0 WHERE `id`=29546; + +DELETE FROM `creature_template_addon` WHERE `entry` IN (24196, 29546); +INSERT INTO `creature_template_addon` (`entry`, `mount`, `bytes1`, `bytes2`, `auras`) VALUES +(24196, 0, 0x0, 0x1, '29266'), -- 24196 - 29266 +(29546, 0, 0x0, 0x1, '29266'); -- 29546 - 29266 + +DELETE FROM `creature_addon` WHERE `guid`=105491; diff --git a/sql/updates/world/3.3.5/2016_05_31_03_world.sql b/sql/updates/world/3.3.5/2016_05_31_03_world.sql new file mode 100644 index 00000000000..60c07d15735 --- /dev/null +++ b/sql/updates/world/3.3.5/2016_05_31_03_world.sql @@ -0,0 +1,3 @@ +-- +UPDATE `conditions` SET `ConditionValue1`=11248, `Comment`='Winterskorn mobs drop item 33314 only if Quest 11248 has been rewarded' WHERE `SourceTypeOrReferenceId`=1 AND `SourceEntry`=33314; +UPDATE `conditions` SET `ConditionValue1`=11256, `Comment`='Winterskorn mobs drop item 33345 only if Quest 11256 has been rewarded' WHERE `SourceTypeOrReferenceId`=1 AND `SourceEntry`=33345; diff --git a/sql/updates/world/3.3.5/2016_05_31_04_world.sql b/sql/updates/world/3.3.5/2016_05_31_04_world.sql new file mode 100644 index 00000000000..d3ddfcfa05c --- /dev/null +++ b/sql/updates/world/3.3.5/2016_05_31_04_world.sql @@ -0,0 +1,15 @@ +-- +DELETE FROM `areatrigger_scripts` WHERE `entry` IN (5187, 5190); +INSERT INTO `areatrigger_scripts` VALUES +(5187, "SmartTrigger"), +(5190, "SmartTrigger"); + +DELETE FROM `smart_scripts` WHERE `entryorguid` IN (5187, 5190) AND `source_type`=2; +INSERT INTO `smart_scripts` VALUES +(5187, 2, 0, 0, 46, 0, 100, 0, 0, 0, 0, 0, 62, 571, 0, 0, 0, 0, 0, 7, 0, 0, 0, 6150.7563, -1071.3817, 402.7154, 2.1916, "Areatrigger - On Trigger - Teleport"), +(5190, 2, 0, 0, 46, 0, 100, 0, 0, 0, 0, 0, 62, 571, 0, 0, 0, 0, 0, 7, 0, 0, 0, 6314.1860, -1758.2946, 457.0714, 1.6787, "Areatrigger - On Trigger - Teleport"); + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=22 AND `SourceId`=2 AND SourceEntry IN (5187, 5190); +INSERT INTO `conditions` VALUES +(22, 1, 5187, 2, 0, 8, 0, 12821, 0, 0, 0, 0, 0, "", "Event requires quest rewarded"), +(22, 1, 5190, 2, 0, 8, 0, 12821, 0, 0, 0, 0, 0, "", "Event requires quest rewarded"); diff --git a/sql/updates/world/3.3.5/2016_05_31_05_world.sql b/sql/updates/world/3.3.5/2016_05_31_05_world.sql new file mode 100644 index 00000000000..18bbf61baa4 --- /dev/null +++ b/sql/updates/world/3.3.5/2016_05_31_05_world.sql @@ -0,0 +1,12 @@ +-- +UPDATE `quest_template_addon` SET `PrevQuestID`=0 WHERE `Id`=12836; + +DELETE FROM `conditions` WHERE `SourceEntry`=12828 AND `SourceTypeOrReferenceId` IN (19, 20); +INSERT INTO `conditions` VALUES +(19, 0, 12828, 0, 0, 8, 0, 12827, 0, 0, 0, 0, 0, "", "Show mark for quest 'Ample Inspiration' only if quest 'Reclaimed Rations' is rewarded"), +(20, 0, 12828, 0, 0, 8, 0, 12827, 0, 0, 0, 0, 0, "", "Can accept quest 'Ample Inspiration' only if quest 'Reclaimed Rations' is rewarded"); + +DELETE FROM `quest_template_addon` WHERE `ID` IN (12862, 13060); +INSERT INTO `quest_template_addon` (`ID`, `PrevQuestId`) VALUES +(12862, 12824), +(13060, 12824); diff --git a/sql/updates/world/3.3.5/2016_05_31_06_world.sql b/sql/updates/world/3.3.5/2016_05_31_06_world.sql new file mode 100644 index 00000000000..46d8b875c82 --- /dev/null +++ b/sql/updates/world/3.3.5/2016_05_31_06_world.sql @@ -0,0 +1,10 @@ +-- +-- remove mis-spawned Mistbat (entry: 16353) +DELETE FROM `creature` WHERE `guid`=57016; + +-- remove one too many spawned Elder Springpaw (entry: 15651) +DELETE FROM `creature` WHERE `guid`=55946; + +-- set random movement and spawn distance to the common value for that creature +UPDATE `creature` SET `spawndist`=5, `MovementType`=1 WHERE `guid`=55942; +UPDATE `creature` SET `spawndist`=5, `MovementType`=1 WHERE `guid`=55945; diff --git a/sql/updates/world/3.3.5/2016_05_31_07_world.sql b/sql/updates/world/3.3.5/2016_05_31_07_world.sql new file mode 100644 index 00000000000..7ed017ff1cd --- /dev/null +++ b/sql/updates/world/3.3.5/2016_05_31_07_world.sql @@ -0,0 +1,2 @@ +-- +UPDATE `creature_loot_template` SET `MinCount`=1, `MaxCount`=1 WHERE `Item`=11509; diff --git a/sql/updates/world/3.3.5/2016_05_31_08_world.sql b/sql/updates/world/3.3.5/2016_05_31_08_world.sql new file mode 100644 index 00000000000..2cf3fbcdfc4 --- /dev/null +++ b/sql/updates/world/3.3.5/2016_05_31_08_world.sql @@ -0,0 +1,13 @@ +-- +DELETE FROM `conditions` WHERE `SourceEntry`=23359 AND `SourceTypeOrReferenceId`=17; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`SourceId`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionTarget`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`, `ErrorType`, `ErrorTextId`,`ScriptName`,`Comment`) VALUES +(17, 0, 23359, 0, 0, 31, 1, 3, 5357, 0, 0, 0, 0, "", "Transmogrify! target can be Land Walker"), +(17, 0, 23359, 0, 0, 36, 1, 0, 0, 0, 0, 0, 0, "", "Transmogrify! target must be alive"), +(17, 0, 23359, 0, 1, 31, 1, 3, 5358, 0, 0, 0, 0, "", "Transmogrify! target can be Cliff Giant"), +(17, 0, 23359, 0, 1, 36, 1, 0, 0, 0, 0, 0, 0, "", "Transmogrify! target must be alive"), +(17, 0, 23359, 0, 2, 31, 1, 3, 5359, 0, 0, 0, 0, "", "Transmogrify! target can be Shore Strider"), +(17, 0, 23359, 0, 2, 36, 1, 0, 0, 0, 0, 0, 0, "", "Transmogrify! target must be alive"), +(17, 0, 23359, 0, 3, 31, 1, 3, 5360, 0, 0, 0, 0, "", "Transmogrify! target can be Deep Strider"), +(17, 0, 23359, 0, 3, 36, 1, 0, 0, 0, 0, 0, 0, "", "Transmogrify! target must be alive"), +(17, 0, 23359, 0, 4, 31, 1, 3, 5361, 0, 0, 0, 0, "", "Transmogrify! target can be Wave Strider"), +(17, 0, 23359, 0, 4, 36, 1, 0, 0, 0, 0, 0, 0, "", "Transmogrify! target must be alive"); diff --git a/sql/updates/world/3.3.5/2016_05_31_09_world.sql b/sql/updates/world/3.3.5/2016_05_31_09_world.sql new file mode 100644 index 00000000000..73d62a92772 --- /dev/null +++ b/sql/updates/world/3.3.5/2016_05_31_09_world.sql @@ -0,0 +1,3 @@ +-- +UPDATE `creature_template` SET `speed_run`=0.42857 WHERE `entry` IN (16027); +UPDATE `smart_scripts` SET `action_param1`=22 WHERE `entryorguid`=16027 AND `source_type`=0 AND `id`=3 AND `link`=4; diff --git a/sql/updates/world/3.3.5/2016_05_31_10_world.sql b/sql/updates/world/3.3.5/2016_05_31_10_world.sql new file mode 100644 index 00000000000..e7536b3a51a --- /dev/null +++ b/sql/updates/world/3.3.5/2016_05_31_10_world.sql @@ -0,0 +1,2 @@ +-- +DELETE FROM `creature_loot_template` WHERE `Item`=31245; diff --git a/sql/updates/world/3.3.5/2016_05_31_11_world.sql b/sql/updates/world/3.3.5/2016_05_31_11_world.sql new file mode 100644 index 00000000000..e5d35f5eb42 --- /dev/null +++ b/sql/updates/world/3.3.5/2016_05_31_11_world.sql @@ -0,0 +1,2 @@ +-- +UPDATE `reference_loot_template` SET `Item`=49667, `Chance`=10 WHERE `Item`=48679; diff --git a/sql/updates/world/3.3.5/2016_05_31_12_world_335.sql b/sql/updates/world/3.3.5/2016_05_31_12_world_335.sql new file mode 100644 index 00000000000..b20c38b36ba --- /dev/null +++ b/sql/updates/world/3.3.5/2016_05_31_12_world_335.sql @@ -0,0 +1,2 @@ +-- +UPDATE `quest_template_addon` SET `PrevQuestID`=155 WHERE `ID`=214; diff --git a/sql/updates/world/3.3.5/2016_05_31_13_world.sql b/sql/updates/world/3.3.5/2016_05_31_13_world.sql new file mode 100644 index 00000000000..6dd3d984c1c --- /dev/null +++ b/sql/updates/world/3.3.5/2016_05_31_13_world.sql @@ -0,0 +1,23 @@ +-- +UPDATE `quest_template_addon` SET `ExclusiveGroup`=8747 WHERE `Id` IN (8747, 8752, 8757); + +UPDATE `quest_template_addon` SET `PrevQuestId`=0, `SpecialFlags`=1 WHERE `Id` IN (8764, 8765, 8766); + +DELETE FROM `conditions` WHERE `SourceEntry` IN (8764, 8765, 8766); +INSERT INTO `conditions` VALUES +(19, 0, 8764, 0, 0, 2, 0, 21200, 1, 1, 0, 0, 0, "", "Quest 8764 is available only if player has item 21200 in bags or bank"), +(20, 0, 8764, 0, 0, 2, 0, 21200, 1, 1, 0, 0, 0, "", "Show question mark for quest 8764 only if player has item 21200 in bags or bank"), + +(19, 0, 8765, 0, 0, 2, 0, 21210, 1, 1, 0, 0, 0, "", "Quest 8765 is available only if player has item 21210 in bags or bank"), +(20, 0, 8765, 0, 0, 2, 0, 21210, 1, 1, 0, 0, 0, "", "Show question mark for quest 8765 only if player has item 21210 in bags or bank"), + +(19, 0, 8766, 0, 0, 2, 0, 21205, 1, 1, 0, 0, 0, "", "Quest 8766 is available only if player has item 21205 in bags or bank"), +(20, 0, 8766, 0, 0, 2, 0, 21205, 1, 1, 0, 0, 0, "", "Show question mark for quest 8766 only if player has item 21205 in bags or bank"); + +DELETE FROM `quest_offer_reward` WHERE `ID` IN (8747, 8752, 8757); +INSERT INTO `quest_offer_reward` (`ID`,`Emote1`,`Emote2`,`Emote3`,`Emote4`,`EmoteDelay1`,`EmoteDelay2`,`EmoteDelay3`,`EmoteDelay4`,`RewardText`,`VerifiedBuild`) VALUES +(8747,1,0,0,0,0,0,0,0,(SELECT `CompletionText` FROM `quest_request_items` WHERE `ID`=8747),12340), +(8752,1,0,0,0,0,0,0,0,(SELECT `CompletionText` FROM `quest_request_items` WHERE `ID`=8752),12340), +(8757,1,0,0,0,0,0,0,0,(SELECT `CompletionText` FROM `quest_request_items` WHERE `ID`=8757),12340); + +UPDATE `quest_request_items` SET `CompletionText` = "Never have I seen such tenacity! The Bronze Flight grants you one final enchantment. The Timeless One himself has requested it so!$B$BHand me your signet ring so that I may make the necessary adjustments." WHERE `ID` IN (8751, 8756, 8761); diff --git a/sql/updates/world/3.3.5/2016_05_31_14_world_335.sql b/sql/updates/world/3.3.5/2016_05_31_14_world_335.sql new file mode 100644 index 00000000000..496a9645bda --- /dev/null +++ b/sql/updates/world/3.3.5/2016_05_31_14_world_335.sql @@ -0,0 +1,2 @@ +-- +UPDATE `creature_template` SET `unit_flags`=33536 WHERE `entry`=24117; diff --git a/sql/updates/world/3.3.5/2016_06_01_00_world.sql b/sql/updates/world/3.3.5/2016_06_01_00_world.sql new file mode 100644 index 00000000000..5f4e7dbb01c --- /dev/null +++ b/sql/updates/world/3.3.5/2016_06_01_00_world.sql @@ -0,0 +1,2 @@ +-- +UPDATE `quest_template` SET `AllowableRaces`=1024 WHERE `ID`=9429; diff --git a/sql/updates/world/3.3.5/2016_06_01_01_world.sql b/sql/updates/world/3.3.5/2016_06_01_01_world.sql new file mode 100644 index 00000000000..80ecabe34aa --- /dev/null +++ b/sql/updates/world/3.3.5/2016_06_01_01_world.sql @@ -0,0 +1,5 @@ +-- +UPDATE `creature` SET `position_x`=3154.581, `position_y`=-3126.18, `position_z`=293.5911, `orientation`=4.430199 WHERE `guid`=76311; +UPDATE `creature` SET `position_x`=3128.622, `position_y`=-3119.604, `position_z`=293.4113, `orientation`=4.738929 WHERE `guid`=76312; +UPDATE `creature` SET `position_x`=3175.281, `position_y`=-3134.764, `position_z`=293.4368, `orientation`=4.244924 WHERE `guid`=76313; +UPDATE `smart_scripts` SET `action_param1`=34 WHERE `entryorguid`=16027 AND `source_type`=0 AND `id`=3 AND `link`=4; diff --git a/sql/updates/world/3.3.5/2016_06_01_02_world.sql b/sql/updates/world/3.3.5/2016_06_01_02_world.sql new file mode 100644 index 00000000000..e2c27b15339 --- /dev/null +++ b/sql/updates/world/3.3.5/2016_06_01_02_world.sql @@ -0,0 +1,2 @@ +-- +UPDATE `quest_template_addon` SET `PrevQuestID`=985 WHERE `ID`=986; diff --git a/sql/updates/world/3.3.5/2016_06_01_03_world.sql b/sql/updates/world/3.3.5/2016_06_01_03_world.sql new file mode 100644 index 00000000000..54beb26b15c --- /dev/null +++ b/sql/updates/world/3.3.5/2016_06_01_03_world.sql @@ -0,0 +1,2 @@ +-- +UPDATE `quest_template_addon` SET `AllowableClasses`=256 WHERE `ID`=397; diff --git a/sql/updates/world/3.3.5/2016_06_01_04_world.sql b/sql/updates/world/3.3.5/2016_06_01_04_world.sql new file mode 100644 index 00000000000..1de1716102b --- /dev/null +++ b/sql/updates/world/3.3.5/2016_06_01_04_world.sql @@ -0,0 +1,2 @@ +-- +UPDATE `quest_template` SET `AllowableRaces`=512 WHERE `ID`=9425; diff --git a/sql/updates/world/3.3.5/2016_06_01_05_world.sql b/sql/updates/world/3.3.5/2016_06_01_05_world.sql new file mode 100644 index 00000000000..3d7a32ac308 --- /dev/null +++ b/sql/updates/world/3.3.5/2016_06_01_05_world.sql @@ -0,0 +1,2 @@ +-- +UPDATE `item_loot_template` SET `Chance`=100 WHERE `Entry`=24336; diff --git a/sql/updates/world/3.3.5/2016_06_01_06_world.sql b/sql/updates/world/3.3.5/2016_06_01_06_world.sql new file mode 100644 index 00000000000..9344147e067 --- /dev/null +++ b/sql/updates/world/3.3.5/2016_06_01_06_world.sql @@ -0,0 +1,2 @@ +-- +UPDATE `quest_template` SET `AllowableRaces`=0 WHERE `ID`=1486; diff --git a/sql/updates/world/3.3.5/2016_06_01_07_world.sql b/sql/updates/world/3.3.5/2016_06_01_07_world.sql new file mode 100644 index 00000000000..9c159c54cb6 --- /dev/null +++ b/sql/updates/world/3.3.5/2016_06_01_07_world.sql @@ -0,0 +1,4 @@ +-- +DELETE FROM `creature_queststarter` WHERE `quest`=249; +INSERT INTO `creature_queststarter` (`id`, `quest`) VALUES +(313, 249); diff --git a/sql/updates/world/3.3.5/2016_06_01_08_world.sql b/sql/updates/world/3.3.5/2016_06_01_08_world.sql new file mode 100644 index 00000000000..356c0561bf2 --- /dev/null +++ b/sql/updates/world/3.3.5/2016_06_01_08_world.sql @@ -0,0 +1,2 @@ +-- +UPDATE `creature_loot_template` SET `Chance`=100 WHERE `Item`=29795; diff --git a/sql/updates/world/3.3.5/2016_06_01_09_world.sql b/sql/updates/world/3.3.5/2016_06_01_09_world.sql new file mode 100644 index 00000000000..5cf06521a19 --- /dev/null +++ b/sql/updates/world/3.3.5/2016_06_01_09_world.sql @@ -0,0 +1,4 @@ +-- +DELETE FROM `quest_template_addon` WHERE `ID`=768; +INSERT INTO `quest_template_addon` (`ID`, `RequiredSkillID`, `RequiredSkillPoints`) VALUES +(768, 393, 1); diff --git a/sql/updates/world/3.3.5/2016_06_01_10_world.sql b/sql/updates/world/3.3.5/2016_06_01_10_world.sql new file mode 100644 index 00000000000..abc358431e3 --- /dev/null +++ b/sql/updates/world/3.3.5/2016_06_01_10_world.sql @@ -0,0 +1,2 @@ +-- +UPDATE `quest_template_addon` SET `SpecialFlags`=`SpecialFlags`|1 WHERE `ID` IN (961, 3375, 3382, 3483); diff --git a/sql/updates/world/3.3.5/2016_06_01_11_world.sql b/sql/updates/world/3.3.5/2016_06_01_11_world.sql new file mode 100644 index 00000000000..dc0b7b05a33 --- /dev/null +++ b/sql/updates/world/3.3.5/2016_06_01_11_world.sql @@ -0,0 +1,81 @@ +-- +DELETE FROM `conditions` WHERE `SourceEntry`=254 AND `SourceTypeOrReferenceId`=20 AND `ConditionTypeOrReference` IN (8, 28); +INSERT INTO `conditions` VALUES +(20, 0, 254, 0, 0, 8, 0, 253, 0, 0, 1, 0, 0, "", "Show question mark for quest 'Digging Through the Dirt' only if quest 'Bride of the Embalmer' is not rewarded"), +(20, 0, 254, 0, 0, 28, 0, 253, 0, 0, 1, 0, 0, "", "Show question mark for quest 'Digging Through the Dirt' only if quest 'Bride of the Embalmer' is not completed"); + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId` IN (19, 20) AND `SourceEntry` IN (349, 410, 431, 593, 779, 795, 813, 926, 961, 1191, 1462, 1463, 1464, 1714, 1789, 1790, 4041, 6581, 7645, 8508, 8732, 9483, 10850, 10919); +INSERT INTO `conditions` VALUES +(19, 0, 349, 0, 0, 9, 0, 348, 0, 0, 0, 0, 0, "", "Show quest 'Stranglethorn Fever' only if quest 'Stranglethorn Fever' is accepted but not completed"), +(20, 0, 349, 0, 0, 9, 0, 348, 0, 0, 0, 0, 0, "", "Show question mark for quest 'Stranglethorn Fever' only if quest 'Stranglethorn Fever' is accepted but not completed"), + +(19, 0, 410, 0, 0, 9, 0, 409, 0, 0, 0, 0, 0, "", "Show quest 'The Dormant Shade' only if quest 'Proving Allegiance' is accepted but not completed"), +(20, 0, 410, 0, 0, 9, 0, 409, 0, 0, 0, 0, 0, "", "Show question mark for quest 'The Dormant Shade' only if quest 'Proving Allegiance' is accepted but not completed"), + +(19, 0, 431, 0, 0, 9, 0, 409, 0, 0, 0, 0, 0, "", "Show quest 'Candles of Beckoning' only if quest 'Proving Allegiance' is accepted but not completed"), +(20, 0, 431, 0, 0, 9, 0, 409, 0, 0, 0, 0, 0, "", "Show question mark for quest 'Candles of Beckoning' only if quest 'Proving Allegiance' is accepted but not completed"), + +(19, 0, 593, 0, 0, 9, 0, 592, 0, 0, 0, 0, 0, "", "Show quest 'Filling the Soul Gem' only if quest 'Saving Yenniku' is accepted but not completed"), +(20, 0, 593, 0, 0, 9, 0, 592, 0, 0, 0, 0, 0, "", "Show question mark for quest 'Filling the Soul Gem' only if quest 'Saving Yenniku' is accepted but not completed"), + +(19, 0, 779, 0, 0, 9, 0, 717, 0, 0, 0, 0, 0, "", "Show quest 'Seal of the Earth' only if quest 'Tremors of the Earth' is accepted but not completed"), +(20, 0, 779, 0, 0, 9, 0, 717, 0, 0, 0, 0, 0, "", "Show question mark for quest 'Seal of the Earth' only if quest 'Tremors of the Earth' is accepted but not completed"), + +(19, 0, 795, 0, 0, 9, 0, 793, 0, 0, 0, 0, 0, "", "Show quest 'Seal of the Earth' only if quest 'Broken Alliances' is accepted but not completed"), +(20, 0, 795, 0, 0, 9, 0, 793, 0, 0, 0, 0, 0, "", "Show question mark for quest 'Seal of the Earth' only if quest 'Broken Alliances' is accepted but not completed"), + +(19, 0, 813, 0, 0, 9, 0, 812, 0, 0, 0, 0, 0, "", "Show quest 'Finding the Antidote' only if quest 'Need for a Cure' is accepted"), +(20, 0, 813, 0, 0, 9, 0, 812, 0, 0, 0, 0, 0, "", "Show question mark for quest 'Finding the Antidote' only if quest 'Need for a Cure' is accepted but not completed"), + +(19, 0, 926, 0, 0, 9, 0, 924, 0, 0, 0, 0, 0, "", "Show quest 'Flawed Power Stone' only if quest 'The Demon Seed' is accepted but not completed"), +(20, 0, 926, 0, 0, 9, 0, 924, 0, 0, 0, 0, 0, "", "Show question mark for quest 'Flawed Power Stone' only if quest 'The Demon Seed' is accepted but not completed"), + +(19, 0, 961, 0, 0, 9, 0, 944, 0, 0, 0, 0, 0, "", "Show quest 'Onu is Meditating' only if quest 'The Demon Seed' is accepted but not completed OR"), +(20, 0, 961, 0, 0, 9, 0, 944, 0, 0, 0, 0, 0, "", "Show question mark for quest 'Onu is Meditating' only if quest 'The Demon Seed' is accepted but not completed OR"), +(19, 0, 961, 0, 1, 9, 0, 949, 0, 0, 0, 0, 0, "", "Show quest 'Onu is Meditating' only if quest 'The Twilight Camp' is accepted but not completed"), +(20, 0, 961, 0, 1, 9, 0, 949, 0, 0, 0, 0, 0, "", "Show question mark for quest 'Onu is Meditating' only if quest 'The Twilight Camp' is accepted but not completed"), + +(19, 0, 1191, 0, 0, 9, 0, 1190, 0, 0, 0, 0, 0, "", "Show quest 'Zamek's Distraction' only if quest 'Keeping Pace' is accepted but not completed"), +(20, 0, 1191, 0, 0, 9, 0, 1190, 0, 0, 0, 0, 0, "", "Show question mark for quest 'Zamek's Distraction' only if quest 'Keeping Pace' is accepted but not completed"), + +(19, 0, 1462, 0, 0, 28, 0, 1520, 0, 0, 0, 0, 0, "", "Show quest 'Earth Sapta' only if quest 'Call of Earth' is completed"), +(20, 0, 1462, 0, 0, 28, 0, 1520, 0, 0, 0, 0, 0, "", "Show question mark for quest 'Earth Sapta' only if quest 'Call of Earth' is completed"), + +(19, 0, 1463, 0, 0, 28, 0, 1517, 0, 0, 0, 0, 0, "", "Show quest 'Earth Sapta' only if quest 'Call of Earth' is ompleted"), +(20, 0, 1463, 0, 0, 28, 0, 1517, 0, 0, 0, 0, 0, "", "Show question mark for quest 'Earth Sapta' only if quest 'Call of Earth' is completed"), + +(19, 0, 1464, 0, 0, 9, 0, 1526, 0, 0, 0, 0, 0, "", "Show quest 'Fire Sapta' only if quest 'Call of Fire' is accepted but not completed"), +(20, 0, 1464, 0, 0, 9, 0, 1526, 0, 0, 0, 0, 0, "", "Show question mark for quest 'Fire Sapta' only if quest 'Call of Fire' is accepted but not completed"), + +(19, 0, 1714, 0, 0, 9, 0, 1712, 0, 0, 0, 0, 0, "", "Show quest 'Essence of the Exile' only if quest 'Cyclonian' is accepted but not completed"), +(20, 0, 1714, 0, 0, 9, 0, 1712, 0, 0, 0, 0, 0, "", "Show question mark for quest 'Essence of the Exile' only if quest 'Cyclonian' is accepted but not completed"), + +(19, 0, 1789, 0, 0, 9, 0, 1783, 0, 0, 0, 0, 0, "", "Show quest 'The Symbol of Life' only if quest 'The Tome of Divinity' is accepted but not completed"), +(20, 0, 1789, 0, 0, 9, 0, 1783, 0, 0, 0, 0, 0, "", "Show question mark for quest 'The Symbol of Life' only if quest 'The Tome of Divinity' is accepted but not completed"), + +(19, 0, 1790, 0, 0, 9, 0, 1786, 0, 0, 0, 0, 0, "", "Show quest 'The Symbol of Life' only if quest 'The Tome of Divinity' is accepted but not completed"), +(20, 0, 1790, 0, 0, 9, 0, 1786, 0, 0, 0, 0, 0, "", "Show question mark for quest 'The Symbol of Life' only if quest 'The Tome of Divinity' is accepted but not completed"), + +(19, 0, 4041, 0, 0, 9, 0, 3909, 0, 0, 0, 0, 0, "", "Show quest 'The Videre Elixir' only if quest 'The Videre Elixir' is accepted but not completed"), +(20, 0, 4041, 0, 0, 9, 0, 3909, 0, 0, 0, 0, 0, "", "Show question mark for quest 'The Videre Elixir' only if quest 'The Videre Elixir' is accepted but not completed"), + +(19, 0, 6581, 0, 0, 9, 0, 6571, 0, 0, 0, 0, 0, "", "Show quest 'Warsong Saw Blades' only if quest 'Warsong Supplies' is accepted but not completed"), +(20, 0, 6581, 0, 0, 9, 0, 6571, 0, 0, 0, 0, 0, "", "Show question mark for quest 'Warsong Saw Blades' only if quest 'Warsong Supplies' is accepted but not completed"), + +(19, 0, 7645, 0, 0, 9, 0, 7643, 0, 0, 0, 0, 0, "", "Show quest 'Manna-Enriched Horse Feed' only if quest 'Ancient Equine Spirit' is accepted but not completed"), +(20, 0, 7645, 0, 0, 9, 0, 7643, 0, 0, 0, 0, 0, "", "Show question mark for quest 'Manna-Enriched Horse Feed' only if quest 'Ancient Equine Spirit' is accepted but not completed"), + +(19, 0, 8508, 0, 0, 9, 0, 8507, 0, 0, 0, 0, 0, "", "Show quest 'Field Duty Papers' only if quest 'Field Duty' is accepted but not completed"), +(20, 0, 8508, 0, 0, 9, 0, 8507, 0, 0, 0, 0, 0, "", "Show question mark for quest 'Field Duty Papers' only if quest 'Field Duty' is accepted but not completed"), + +(19, 0, 8732, 0, 0, 9, 0, 8731, 0, 0, 0, 0, 0, "", "Show quest 'Field Duty Papers' only if quest 'Field Duty' is accepted but not completed"), +(20, 0, 8732, 0, 0, 9, 0, 8731, 0, 0, 0, 0, 0, "", "Show question mark for quest 'Field Duty Papers' only if quest 'Field Duty' is accepted but not completed"), + +(19, 0, 9483, 0, 0, 9, 0, 9472, 0, 0, 0, 0, 0, "", "Show quest 'Life's Finer Pleasures' only if quest 'Arelion's Mistress' is accepted but not completed"), +(20, 0, 9483, 0, 0, 9, 0, 9472, 0, 0, 0, 0, 0, "", "Show question mark for quest 'Life's Finer Pleasures' only if quest 'Arelion's Mistress' is accepted but not completed"), + +(19, 0, 10850, 0, 0, 9, 0, 10855, 0, 0, 0, 0, 0, "", "Show quest 'Nether Gas In a Fel Fire Engine' only if quest 'Fel Reavers, No Thanks!' is accepted but not completed"), +(20, 0, 10850, 0, 0, 9, 0, 10855, 0, 0, 0, 0, 0, "", "Show question mark for quest 'Nether Gas In a Fel Fire Engine' only if quest 'Fel Reavers, No Thanks!' is accepted but not completed"), + +(19, 0, 10919, 0, 0, 9, 0, 10916, 0, 0, 0, 0, 0, "", "Show quest 'Fei Fei's Treat' only if quest 'Digging for Prayer Beads' is accepted but not completed"), +(20, 0, 10919, 0, 0, 9, 0, 10916, 0, 0, 0, 0, 0, "", "Show question mark for quest 'Fei Fei's Treat' only if quest 'Digging for Prayer Beads' is accepted but not completed"); diff --git a/sql/updates/world/3.3.5/2016_06_01_12_world.sql b/sql/updates/world/3.3.5/2016_06_01_12_world.sql new file mode 100644 index 00000000000..f6fb906bb70 --- /dev/null +++ b/sql/updates/world/3.3.5/2016_06_01_12_world.sql @@ -0,0 +1,4 @@ +-- +UPDATE `conditions` SET `SourceEntry`=49667 WHERE `SourceEntry`=48679 AND `SourceTypeOrReferenceId`=10 AND `SourceGroup`=10016; +UPDATE `smart_scripts` SET `link`=0 WHERE `entryorguid`=22137 AND `source_type`=0 AND `id`=7; +UPDATE `creature_text` SET `emote`=0 WHERE `entry`=19666 AND `groupid`=2 AND `id`=0; diff --git a/src/common/Configuration/Config.cpp b/src/common/Configuration/Config.cpp index ddaab7dee61..888aa6ecef3 100644 --- a/src/common/Configuration/Config.cpp +++ b/src/common/Configuration/Config.cpp @@ -25,11 +25,13 @@ using namespace boost::property_tree; -bool ConfigMgr::LoadInitial(std::string const& file, std::string& error) +bool ConfigMgr::LoadInitial(std::string const& file, std::vector<std::string> args, + std::string& error) { std::lock_guard<std::mutex> lock(_configLock); _filename = file; + _args = args; try { @@ -65,7 +67,7 @@ ConfigMgr* ConfigMgr::instance() bool ConfigMgr::Reload(std::string& error) { - return LoadInitial(_filename, error); + return LoadInitial(_filename, std::move(_args), error); } template<class T> diff --git a/src/common/Configuration/Config.h b/src/common/Configuration/Config.h index 10113cd88d3..573bc7b4a15 100644 --- a/src/common/Configuration/Config.h +++ b/src/common/Configuration/Config.h @@ -23,6 +23,7 @@ #include <string> #include <list> +#include <vector> #include <mutex> #include <boost/property_tree/ptree.hpp> @@ -35,7 +36,8 @@ class TC_COMMON_API ConfigMgr public: /// Method used only for loading main configuration files (authserver.conf and worldserver.conf) - bool LoadInitial(std::string const& file, std::string& error); + bool LoadInitial(std::string const& file, std::vector<std::string> args, + std::string& error); static ConfigMgr* instance(); @@ -47,10 +49,12 @@ public: float GetFloatDefault(std::string const& name, float def) const; std::string const& GetFilename(); + std::vector<std::string> const& GetArguments() const { return _args; } std::list<std::string> GetKeysByString(std::string const& name); private: std::string _filename; + std::vector<std::string> _args; boost::property_tree::ptree _config; std::mutex _configLock; diff --git a/src/common/Cryptography/SHA1.cpp b/src/common/Cryptography/SHA1.cpp index a01bd7844ee..aed4a069827 100644 --- a/src/common/Cryptography/SHA1.cpp +++ b/src/common/Cryptography/SHA1.cpp @@ -18,6 +18,7 @@ #include "SHA1.h" #include "BigNumber.h" +#include "Util.h" #include <cstring> #include <stdarg.h> @@ -67,3 +68,10 @@ void SHA1Hash::Finalize(void) SHA1_Final(mDigest, &mC); } +std::string CalculateSHA1Hash(std::string const& content) +{ + unsigned char digest[SHA_DIGEST_LENGTH]; + SHA1((unsigned char*)content.c_str(), content.length(), (unsigned char*)&digest); + + return ByteArrayToHexStr(digest, SHA_DIGEST_LENGTH); +} diff --git a/src/common/Cryptography/SHA1.h b/src/common/Cryptography/SHA1.h index 970ab5c0cb9..37ac2cc0166 100644 --- a/src/common/Cryptography/SHA1.h +++ b/src/common/Cryptography/SHA1.h @@ -46,5 +46,8 @@ class TC_COMMON_API SHA1Hash SHA_CTX mC; uint8 mDigest[SHA_DIGEST_LENGTH]; }; -#endif +/// Returns the SHA1 hash of the given content as hex string. +TC_COMMON_API std::string CalculateSHA1Hash(std::string const& content); + +#endif diff --git a/src/common/Utilities/Containers.h b/src/common/Utilities/Containers.h index 7c889068011..5edb245fd87 100644 --- a/src/common/Utilities/Containers.h +++ b/src/common/Utilities/Containers.h @@ -31,9 +31,9 @@ namespace Trinity namespace Containers { template<class T> - void RandomResizeList(std::list<T> &list, uint32 size) + void RandomResizeList(std::list<T>& list, uint32 size) { - size_t list_size = list.size(); + uint32 list_size = uint32(list.size()); while (list_size > size) { @@ -56,7 +56,7 @@ namespace Trinity if (size) RandomResizeList(listCopy, size); - list = listCopy; + list = std::move(listCopy); } /* @@ -68,7 +68,7 @@ namespace Trinity typename C::value_type const& SelectRandomContainerElement(C const& container) { typename C::const_iterator it = container.begin(); - std::advance(it, urand(0, container.size() - 1)); + std::advance(it, urand(0, uint32(container.size()) - 1)); return *it; } @@ -118,6 +118,19 @@ namespace Trinity } /** + * @fn void Trinity::Containers::RandomShuffle(C& container) + * + * @brief Reorder the elements of the container randomly. + * + * @param container Container to reorder + */ + template <class C> + void RandomShuffle(C& container) + { + std::shuffle(container.begin(), container.end(), SFMTEngine::Instance()); + } + + /** * @fn bool Trinity::Containers::Intersects(Iterator first1, Iterator last1, Iterator first2, Iterator last2) * * @brief Checks if two SORTED containers have a common element @@ -157,7 +170,6 @@ namespace Trinity ++itr; } } - } //! namespace Containers } diff --git a/src/common/Utilities/StartProcess.cpp b/src/common/Utilities/StartProcess.cpp index c47c02bbe87..f35c6de3b5c 100644 --- a/src/common/Utilities/StartProcess.cpp +++ b/src/common/Utilities/StartProcess.cpp @@ -78,7 +78,7 @@ static int CreateChildProcess(T waiter, std::string const& executable, if (!secure) { - TC_LOG_TRACE(logger.c_str(), "Starting process \"%s\" with arguments: \"%s\".", + TC_LOG_TRACE(logger, "Starting process \"%s\" with arguments: \"%s\".", executable.c_str(), boost::algorithm::join(args, " ").c_str()); } @@ -92,6 +92,7 @@ static int CreateChildProcess(T waiter, std::string const& executable, // With binding stdin return execute(run_exe(boost::filesystem::absolute(executable)), set_args(args), + inherit_env(), bind_stdin(*inputSource), bind_stdout(file_descriptor_sink(outPipe.sink, close_handle)), bind_stderr(file_descriptor_sink(errPipe.sink, close_handle))); @@ -101,6 +102,7 @@ static int CreateChildProcess(T waiter, std::string const& executable, // Without binding stdin return execute(run_exe(boost::filesystem::absolute(executable)), set_args(args), + inherit_env(), bind_stdout(file_descriptor_sink(outPipe.sink, close_handle)), bind_stderr(file_descriptor_sink(errPipe.sink, close_handle))); } @@ -111,12 +113,12 @@ static int CreateChildProcess(T waiter, std::string const& executable, auto outInfo = MakeTCLogSink([&](std::string msg) { - TC_LOG_INFO(logger.c_str(), "%s", msg.c_str()); + TC_LOG_INFO(logger, "%s", msg.c_str()); }); auto outError = MakeTCLogSink([&](std::string msg) { - TC_LOG_ERROR(logger.c_str(), "%s", msg.c_str()); + TC_LOG_ERROR(logger, "%s", msg.c_str()); }); copy(outFd, outInfo); @@ -128,7 +130,7 @@ static int CreateChildProcess(T waiter, std::string const& executable, if (!secure) { - TC_LOG_TRACE(logger.c_str(), ">> Process \"%s\" finished with return value %i.", + TC_LOG_TRACE(logger, ">> Process \"%s\" finished with return value %i.", executable.c_str(), result); } @@ -237,7 +239,7 @@ public: } }; -TC_COMMON_API std::shared_ptr<AsyncProcessResult> +std::shared_ptr<AsyncProcessResult> StartAsyncProcess(std::string executable, std::vector<std::string> args, std::string logger, std::string input_file, bool secure) { diff --git a/src/common/Utilities/Timer.h b/src/common/Utilities/Timer.h index cdce08caaf0..f66bb90c98e 100644 --- a/src/common/Utilities/Timer.h +++ b/src/common/Utilities/Timer.h @@ -25,9 +25,9 @@ inline uint32 getMSTime() { using namespace std::chrono; - static const system_clock::time_point ApplicationStartTime = system_clock::now(); + static const steady_clock::time_point ApplicationStartTime = steady_clock::now(); - return uint32(duration_cast<milliseconds>(system_clock::now() - ApplicationStartTime).count()); + return uint32(duration_cast<milliseconds>(steady_clock::now() - ApplicationStartTime).count()); } inline uint32 getMSTimeDiff(uint32 oldMSTime, uint32 newMSTime) diff --git a/src/server/authserver/Main.cpp b/src/server/authserver/Main.cpp index a53187ad737..1392900fb9a 100644 --- a/src/server/authserver/Main.cpp +++ b/src/server/authserver/Main.cpp @@ -36,12 +36,14 @@ #include "GitRevision.h" #include "Util.h" #include <iostream> +#include <boost/filesystem/path.hpp> #include <boost/program_options.hpp> #include <openssl/opensslv.h> #include <openssl/crypto.h> using boost::asio::ip::tcp; using namespace boost::program_options; +namespace fs = boost::filesystem; #ifndef _TRINITY_REALM_CONFIG # define _TRINITY_REALM_CONFIG "authserver.conf" @@ -69,7 +71,7 @@ void StopDB(); void SignalHandler(const boost::system::error_code& error, int signalNumber); void KeepDatabaseAliveHandler(const boost::system::error_code& error); void BanExpiryHandler(boost::system::error_code const& error); -variables_map GetConsoleArguments(int argc, char** argv, std::string& configFile, std::string& configService); +variables_map GetConsoleArguments(int argc, char** argv, fs::path& configFile, std::string& configService); boost::asio::io_service* _ioService; boost::asio::deadline_timer* _dbPingTimer; @@ -81,7 +83,7 @@ int main(int argc, char** argv) { signal(SIGABRT, &Trinity::AbortHandler); - std::string configFile = _TRINITY_REALM_CONFIG; + auto configFile = fs::absolute(_TRINITY_REALM_CONFIG); std::string configService; auto vm = GetConsoleArguments(argc, argv, configFile, configService); // exit if help or version is enabled @@ -98,7 +100,9 @@ int main(int argc, char** argv) #endif std::string configError; - if (!sConfigMgr->LoadInitial(configFile, configError)) + if (!sConfigMgr->LoadInitial(configFile.generic_string(), + std::vector<std::string>(argv, argv + argc), + configError)) { printf("Error in config file: %s\n", configError.c_str()); return 1; @@ -109,7 +113,7 @@ int main(int argc, char** argv) TC_LOG_INFO("server.authserver", "%s (authserver)", GitRevision::GetFullVersion()); TC_LOG_INFO("server.authserver", "<Ctrl-C> to stop.\n"); - TC_LOG_INFO("server.authserver", "Using configuration file %s.", configFile.c_str()); + TC_LOG_INFO("server.authserver", "Using configuration file %s.", sConfigMgr->GetFilename().c_str()); TC_LOG_INFO("server.authserver", "Using SSL version: %s (library: %s)", OPENSSL_VERSION_TEXT, SSLeay_version(SSLEAY_VERSION)); TC_LOG_INFO("server.authserver", "Using Boost version: %i.%i.%i", BOOST_VERSION / 100000, BOOST_VERSION / 100 % 1000, BOOST_VERSION % 100); @@ -286,13 +290,14 @@ void ServiceStatusWatcher(boost::system::error_code const& error) } #endif -variables_map GetConsoleArguments(int argc, char** argv, std::string& configFile, std::string& configService) +variables_map GetConsoleArguments(int argc, char** argv, fs::path& configFile, std::string& configService) { options_description all("Allowed options"); all.add_options() ("help,h", "print usage message") ("version,v", "print version build info") - ("config,c", value<std::string>(&configFile)->default_value(_TRINITY_REALM_CONFIG), "use <arg> as configuration file") + ("config,c", value<fs::path>(&configFile)->default_value(fs::absolute(_TRINITY_REALM_CONFIG)), + "use <arg> as configuration file") ; #if PLATFORM == PLATFORM_WINDOWS options_description win("Windows platform specific options"); diff --git a/src/server/authserver/Server/AuthSession.cpp b/src/server/authserver/Server/AuthSession.cpp index f044e0cea94..43c327ffda1 100644 --- a/src/server/authserver/Server/AuthSession.cpp +++ b/src/server/authserver/Server/AuthSession.cpp @@ -820,41 +820,6 @@ bool AuthSession::HandleReconnectProof() } } -tcp::endpoint const GetAddressForClient(Realm const& realm, ip::address const& clientAddr) -{ - ip::address realmIp; - - // Attempt to send best address for client - if (clientAddr.is_loopback()) - { - // Try guessing if realm is also connected locally - if (realm.LocalAddress.is_loopback() || realm.ExternalAddress.is_loopback()) - realmIp = clientAddr; - else - { - // Assume that user connecting from the machine that authserver is located on - // has all realms available in his local network - realmIp = realm.LocalAddress; - } - } - else - { - if (clientAddr.is_v4() && - (clientAddr.to_v4().to_ulong() & realm.LocalSubnetMask.to_v4().to_ulong()) == - (realm.LocalAddress.to_v4().to_ulong() & realm.LocalSubnetMask.to_v4().to_ulong())) - { - realmIp = realm.LocalAddress; - } - else - realmIp = realm.ExternalAddress; - } - - tcp::endpoint endpoint(realmIp, realm.Port); - - // Return external IP - return endpoint; -} - bool AuthSession::HandleRealmList() { TC_LOG_DEBUG("server.authserver", "Entering _HandleRealmList"); diff --git a/src/server/authserver/Server/AuthSession.h b/src/server/authserver/Server/AuthSession.h index 1babb7407a9..027011629eb 100644 --- a/src/server/authserver/Server/AuthSession.h +++ b/src/server/authserver/Server/AuthSession.h @@ -23,7 +23,7 @@ #include "ByteBuffer.h" #include "Socket.h" #include "BigNumber.h" -#include "Callback.h" +#include "QueryCallback.h" #include <memory> #include <boost/asio/ip/tcp.hpp> diff --git a/src/server/authserver/authserver.conf.dist b/src/server/authserver/authserver.conf.dist index db60e3b3ece..1d3b48839a8 100644 --- a/src/server/authserver/authserver.conf.dist +++ b/src/server/authserver/authserver.conf.dist @@ -179,6 +179,7 @@ LoginDatabaseInfo = "127.0.0.1;3306;trinity;trinity;auth" # LoginDatabase.WorkerThreads # Description: The amount of worker threads spawned to handle asynchronous (delayed) MySQL # statements. Each worker thread is mirrored with its own connection to the +# MySQL server and their own thread on the MySQL server. # Default: 1 LoginDatabase.WorkerThreads = 1 diff --git a/src/server/database/Database/DatabaseWorkerPool.h b/src/server/database/Database/DatabaseWorkerPool.h index d883366237f..ffdde91c0a6 100644 --- a/src/server/database/Database/DatabaseWorkerPool.h +++ b/src/server/database/Database/DatabaseWorkerPool.h @@ -19,7 +19,7 @@ #define _DATABASEWORKERPOOL_H #include "Common.h" -#include "Callback.h" +#include "QueryCallback.h" #include "MySQLConnection.h" #include "Transaction.h" #include "DatabaseWorker.h" @@ -120,7 +120,7 @@ class DatabaseWorkerPool //! This method should only be used for queries that are only executed once, e.g during startup. void DirectExecute(const char* sql) { - if (!sql) + if (Trinity::IsFormatEmptyOrNull(sql)) return; T* connection = GetFreeConnection(); @@ -175,7 +175,7 @@ class DatabaseWorkerPool template<typename Format, typename... Args> QueryResult PQuery(Format&& sql, Args&&... args) { - if (!sql) + if (Trinity::IsFormatEmptyOrNull(sql)) return QueryResult(nullptr); return Query(Trinity::StringFormat(std::forward<Format>(sql), std::forward<Args>(args)...).c_str()); diff --git a/src/server/database/Database/Implementation/WorldDatabase.cpp b/src/server/database/Database/Implementation/WorldDatabase.cpp index 7a183d5bf78..83720c1a996 100644 --- a/src/server/database/Database/Implementation/WorldDatabase.cpp +++ b/src/server/database/Database/Implementation/WorldDatabase.cpp @@ -30,8 +30,8 @@ void WorldDatabaseConnection::DoPrepareStatements() PrepareStatement(WORLD_SEL_SMARTAI_WP, "SELECT entry, pointid, position_x, position_y, position_z FROM waypoints ORDER BY entry, pointid", CONNECTION_SYNCH); PrepareStatement(WORLD_DEL_GAMEOBJECT, "DELETE FROM gameobject WHERE guid = ?", CONNECTION_ASYNC); PrepareStatement(WORLD_DEL_EVENT_GAMEOBJECT, "DELETE FROM game_event_gameobject WHERE guid = ?", CONNECTION_ASYNC); - PrepareStatement(WORLD_INS_GRAVEYARD_ZONE, "INSERT INTO game_graveyard_zone (id, ghost_zone, faction) VALUES (?, ?, ?)", CONNECTION_ASYNC); - PrepareStatement(WORLD_DEL_GRAVEYARD_ZONE, "DELETE FROM game_graveyard_zone WHERE id = ? AND ghost_zone = ? AND faction = ?", CONNECTION_ASYNC); + PrepareStatement(WORLD_INS_GRAVEYARD_ZONE, "INSERT INTO graveyard_zone (ID, GhostZone, Faction) VALUES (?, ?, ?)", CONNECTION_ASYNC); + PrepareStatement(WORLD_DEL_GRAVEYARD_ZONE, "DELETE FROM graveyard_zone WHERE ID = ? AND GhostZone = ? AND Faction = ?", CONNECTION_ASYNC); PrepareStatement(WORLD_INS_GAME_TELE, "INSERT INTO game_tele (id, position_x, position_y, position_z, orientation, map, name) VALUES (?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC); PrepareStatement(WORLD_DEL_GAME_TELE, "DELETE FROM game_tele WHERE name = ?", CONNECTION_ASYNC); PrepareStatement(WORLD_INS_NPC_VENDOR, "INSERT INTO npc_vendor (entry, item, maxcount, incrtime, extendedcost) VALUES(?, ?, ?, ?, ?)", CONNECTION_ASYNC); diff --git a/src/common/Threading/Callback.h b/src/server/database/Database/QueryCallback.h index f7eab57ddda..5f6ae74da4f 100644 --- a/src/common/Threading/Callback.h +++ b/src/server/database/Database/QueryCallback.h @@ -15,8 +15,8 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef _CALLBACK_H -#define _CALLBACK_H +#ifndef _QUERY_CALLBACK_H +#define _QUERY_CALLBACK_H #include <future> #include "QueryResult.h" @@ -206,4 +206,4 @@ class QueryCallback_2 QueryCallback_2& operator=(QueryCallback_2 const& right) = delete; }; -#endif +#endif // _QUERY_CALLBACK_H diff --git a/src/server/database/Updater/DBUpdater.cpp b/src/server/database/Updater/DBUpdater.cpp index 3be81e85715..85213a7f709 100644 --- a/src/server/database/Updater/DBUpdater.cpp +++ b/src/server/database/Updater/DBUpdater.cpp @@ -55,7 +55,7 @@ bool DBUpdaterUtil::CheckExecutable() } } - TC_LOG_FATAL("sql.updates", "Didn't find executeable mysql binary at \'%s\' or in path, correct the path in the *.conf (\"Updates.MySqlCLIPath\").", + TC_LOG_FATAL("sql.updates", "Didn't find any executable MySQL binary at \'%s\' or in path, correct the path in the *.conf (\"MySQLExecutable\").", absolute(exe).generic_string().c_str()); return false; @@ -178,7 +178,7 @@ bool DBUpdater<T>::Create(DatabaseWorkerPool<T>& pool) // Path of temp file static Path const temp("create_table.sql"); - // Create temporary query to use external mysql cli + // Create temporary query to use external MySQL CLi std::ofstream file(temp.generic_string()); if (!file.is_open()) { @@ -197,7 +197,7 @@ bool DBUpdater<T>::Create(DatabaseWorkerPool<T>& pool) } catch (UpdateException&) { - TC_LOG_FATAL("sql.updates", "Failed to create database %s! Has the user `CREATE` priviliges?", pool.GetConnectionInfo()->database.c_str()); + TC_LOG_FATAL("sql.updates", "Failed to create database %s! Does the user (named in *.conf) have `CREATE` privileges on the MySQL server?", pool.GetConnectionInfo()->database.c_str()); boost::filesystem::remove(temp); return false; } @@ -280,7 +280,7 @@ bool DBUpdater<T>::Populate(DatabaseWorkerPool<T>& pool) { case LOCATION_REPOSITORY: { - TC_LOG_ERROR("sql.updates", ">> Base file \"%s\" is missing, try to clone the source again.", + TC_LOG_ERROR("sql.updates", ">> Base file \"%s\" is missing. Try fixing it by cloning the source again.", base.generic_string().c_str()); break; @@ -288,7 +288,7 @@ bool DBUpdater<T>::Populate(DatabaseWorkerPool<T>& pool) case LOCATION_DOWNLOAD: { TC_LOG_ERROR("sql.updates", ">> File \"%s\" is missing, download it from \"https://github.com/TrinityCore/TrinityCore/releases\"" \ - " and place it in your server directory.", base.filename().generic_string().c_str()); + " and place it in your worldserver directory.", base.filename().generic_string().c_str()); break; } } @@ -355,7 +355,7 @@ void DBUpdater<T>::ApplyFile(DatabaseWorkerPool<T>& pool, std::string const& hos if (!std::isdigit(port_or_socket[0])) { - // We can't check here if host == "." because is named localhost if socket option is enabled + // We can't check if host == "." here, because it is named localhost if socket option is enabled args.push_back("-P0"); args.push_back("--protocol=SOCKET"); args.push_back("-S" + port_or_socket); @@ -383,7 +383,7 @@ void DBUpdater<T>::ApplyFile(DatabaseWorkerPool<T>& pool, std::string const& hos if (ret != EXIT_SUCCESS) { TC_LOG_FATAL("sql.updates", "Applying of file \'%s\' to database \'%s\' failed!" \ - " If you are an user pull the latest revision from the repository. If you are a developer fix your sql query.", + " If you are a user, pull the latest revision from the repository. If you are a developer, fix your sql query.", path.generic_string().c_str(), pool.GetConnectionInfo()->database.c_str()); throw UpdateException("update failed"); diff --git a/src/server/database/Updater/UpdateFetcher.cpp b/src/server/database/Updater/UpdateFetcher.cpp index 6f67867c52b..7dc0a307ca2 100644 --- a/src/server/database/Updater/UpdateFetcher.cpp +++ b/src/server/database/Updater/UpdateFetcher.cpp @@ -18,6 +18,7 @@ #include "UpdateFetcher.h" #include "Log.h" #include "Util.h" +#include "SHA1.h" #include <fstream> #include <chrono> @@ -25,7 +26,6 @@ #include <sstream> #include <exception> #include <unordered_map> -#include <openssl/sha.h> using namespace boost::filesystem; @@ -209,9 +209,8 @@ UpdateResult UpdateFetcher::Update(bool const redundancyChecks, } } - // Calculate hash - std::string const hash = - CalculateHash(ReadSQLUpdate(availableQuery.first)); + // Calculate a Sha1 hash based on query content. + std::string const hash = CalculateSHA1Hash(ReadSQLUpdate(availableQuery.first)); UpdateMode mode = MODE_APPLY; @@ -334,15 +333,6 @@ UpdateResult UpdateFetcher::Update(bool const redundancyChecks, return UpdateResult(importedUpdates, countRecentUpdates, countArchivedUpdates); } -std::string UpdateFetcher::CalculateHash(std::string const& query) const -{ - // Calculate a Sha1 hash based on query content. - unsigned char digest[SHA_DIGEST_LENGTH]; - SHA1((unsigned char*)query.c_str(), query.length(), (unsigned char*)&digest); - - return ByteArrayToHexStr(digest, SHA_DIGEST_LENGTH); -} - uint32 UpdateFetcher::Apply(Path const& path) const { using Time = std::chrono::high_resolution_clock; diff --git a/src/server/database/Updater/UpdateFetcher.h b/src/server/database/Updater/UpdateFetcher.h index a17658818ce..cabc3c2fce3 100644 --- a/src/server/database/Updater/UpdateFetcher.h +++ b/src/server/database/Updater/UpdateFetcher.h @@ -112,7 +112,6 @@ private: AppliedFileStorage ReceiveAppliedFiles() const; std::string ReadSQLUpdate(Path const& file) const; - std::string CalculateHash(std::string const& query) const; uint32 Apply(Path const& path) const; diff --git a/src/server/game/AI/CoreAI/CombatAI.cpp b/src/server/game/AI/CoreAI/CombatAI.cpp index 716ac13c666..4d0247d9fb5 100644 --- a/src/server/game/AI/CoreAI/CombatAI.cpp +++ b/src/server/game/AI/CoreAI/CombatAI.cpp @@ -50,7 +50,7 @@ void AggressorAI::UpdateAI(uint32 /*diff*/) void CombatAI::InitializeAI() { - for (uint32 i = 0; i < CREATURE_MAX_SPELLS; ++i) + for (uint32 i = 0; i < MAX_CREATURE_SPELLS; ++i) if (me->m_spells[i] && sSpellMgr->GetSpellInfo(me->m_spells[i])) spells.push_back(me->m_spells[i]); diff --git a/src/server/game/AI/CoreAI/PassiveAI.cpp b/src/server/game/AI/CoreAI/PassiveAI.cpp index aafde3c1d9a..3ed2f927645 100644 --- a/src/server/game/AI/CoreAI/PassiveAI.cpp +++ b/src/server/game/AI/CoreAI/PassiveAI.cpp @@ -58,6 +58,12 @@ void PossessedAI::KilledUnit(Unit* victim) victim->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); } +void PossessedAI::OnCharmed(bool /*apply*/) +{ + me->NeedChangeAI = true; + me->IsAIEnabled = false; +} + void CritterAI::DamageTaken(Unit* /*done_by*/, uint32&) { if (!me->HasUnitState(UNIT_STATE_FLEEING)) diff --git a/src/server/game/AI/CoreAI/PassiveAI.h b/src/server/game/AI/CoreAI/PassiveAI.h index 5a6dba7046d..9ca9e75bd9f 100644 --- a/src/server/game/AI/CoreAI/PassiveAI.h +++ b/src/server/game/AI/CoreAI/PassiveAI.h @@ -46,6 +46,8 @@ class TC_GAME_API PossessedAI : public CreatureAI void JustDied(Unit*) override; void KilledUnit(Unit* victim) override; + void OnCharmed(bool /*apply*/) override; + static int Permissible(const Creature*) { return PERMIT_BASE_IDLE; } }; diff --git a/src/server/game/AI/CoreAI/PetAI.cpp b/src/server/game/AI/CoreAI/PetAI.cpp index 68554722db6..2abe20f0ae6 100644 --- a/src/server/game/AI/CoreAI/PetAI.cpp +++ b/src/server/game/AI/CoreAI/PetAI.cpp @@ -588,6 +588,12 @@ void PetAI::ReceiveEmote(Player* player, uint32 emote) } } +void PetAI::OnCharmed(bool /*apply*/) +{ + me->NeedChangeAI = true; + me->IsAIEnabled = false; +} + void PetAI::ClearCharmInfoFlags() { // Quick access to set all flags to FALSE diff --git a/src/server/game/AI/CoreAI/PetAI.h b/src/server/game/AI/CoreAI/PetAI.h index 3ad34047b01..93ee6c41ece 100644 --- a/src/server/game/AI/CoreAI/PetAI.h +++ b/src/server/game/AI/CoreAI/PetAI.h @@ -49,6 +49,8 @@ class TC_GAME_API PetAI : public CreatureAI void MoveInLineOfSight_Safe(Unit* /*who*/) { } // CreatureAI interferes with returning pets void EnterEvadeMode(EvadeReason /*why*/) override { } // For fleeing, pets don't use this type of Evade mechanic + void OnCharmed(bool /*apply*/) override; + private: bool _isVisible(Unit*) const; bool _needToStop(void); diff --git a/src/server/game/AI/CoreAI/UnitAI.h b/src/server/game/AI/CoreAI/UnitAI.h index 344ccc06249..20a986c0483 100644 --- a/src/server/game/AI/CoreAI/UnitAI.h +++ b/src/server/game/AI/CoreAI/UnitAI.h @@ -242,6 +242,7 @@ class TC_GAME_API UnitAI void DoAddAuraToAllHostilePlayers(uint32 spellid); void DoCast(uint32 spellId); void DoCast(Unit* victim, uint32 spellId, bool triggered = false); + void DoCastSelf(uint32 spellId, bool triggered = false) { DoCast(me, spellId, triggered); } void DoCastToAllHostilePlayers(uint32 spellid, bool triggered = false); void DoCastVictim(uint32 spellId, bool triggered = false); void DoCastAOE(uint32 spellId, bool triggered = false); diff --git a/src/server/game/AI/CreatureAI.cpp b/src/server/game/AI/CreatureAI.cpp index 5b76b583d24..15bbff2793f 100644 --- a/src/server/game/AI/CreatureAI.cpp +++ b/src/server/game/AI/CreatureAI.cpp @@ -29,11 +29,13 @@ #include "Language.h" //Disable CreatureAI when charmed -void CreatureAI::OnCharmed(bool /*apply*/) +void CreatureAI::OnCharmed(bool apply) { - //me->IsAIEnabled = !apply;*/ - me->NeedChangeAI = true; - me->IsAIEnabled = false; + if (apply) + { + me->NeedChangeAI = true; + me->IsAIEnabled = false; + } } AISpellInfoType* UnitAI::AISpellInfo; @@ -44,7 +46,7 @@ void CreatureAI::Talk(uint8 id, WorldObject const* whisperTarget /*= nullptr*/) sCreatureTextMgr->SendChat(me, id, whisperTarget); } -void CreatureAI::DoZoneInCombat(Creature* creature /*= NULL*/, float maxRangeToNearestTarget /* = 50.0f*/) +void CreatureAI::DoZoneInCombat(Creature* creature /*= nullptr*/, float maxRangeToNearestTarget /* = 250.0f*/) { if (!creature) creature = me; @@ -257,17 +259,16 @@ bool CreatureAI::_EnterEvadeMode(EvadeReason /*why*/) if (!me->IsAlive()) return false; - // don't remove vehicle auras, passengers aren't supposed to drop off the vehicle - // don't remove clone caster on evade (to be verified) - me->RemoveAllAurasExceptType(SPELL_AURA_CONTROL_VEHICLE, SPELL_AURA_CLONE_CASTER); + me->RemoveAurasOnEvade(); // sometimes bosses stuck in combat? me->DeleteThreatList(); me->CombatStop(true); me->LoadCreaturesAddon(); - me->SetLootRecipient(NULL); + me->SetLootRecipient(nullptr); me->ResetPlayerDamageReq(); me->SetLastDamagedTime(0); + me->SetCannotReachTarget(false); if (me->IsInEvadeMode()) return false; @@ -275,11 +276,11 @@ bool CreatureAI::_EnterEvadeMode(EvadeReason /*why*/) return true; } -#define BOUNDARY_VISUALIZE_CREATURE 15425 -#define BOUNDARY_VISUALIZE_CREATURE_SCALE 0.25f -#define BOUNDARY_VISUALIZE_STEP_SIZE 1 -#define BOUNDARY_VISUALIZE_FAILSAFE_LIMIT 750 -#define BOUNDARY_VISUALIZE_SPAWN_HEIGHT 5 +static const uint32 BOUNDARY_VISUALIZE_CREATURE = 15425; +static const float BOUNDARY_VISUALIZE_CREATURE_SCALE = 0.25f; +static const int8 BOUNDARY_VISUALIZE_STEP_SIZE = 1; +static const int32 BOUNDARY_VISUALIZE_FAILSAFE_LIMIT = 750; +static const float BOUNDARY_VISUALIZE_SPAWN_HEIGHT = 5.0f; int32 CreatureAI::VisualizeBoundary(uint32 duration, Unit* owner, bool fill) const { typedef std::pair<int32, int32> coordinate; @@ -295,13 +296,13 @@ int32 CreatureAI::VisualizeBoundary(uint32 duration, Unit* owner, bool fill) con std::unordered_set<coordinate> outOfBounds; Position startPosition = owner->GetPosition(); - if (!CheckBoundary(&startPosition)) // fall back to creature position - { + if (!CheckBoundary(&startPosition)) + { // fall back to creature position startPosition = me->GetPosition(); if (!CheckBoundary(&startPosition)) - { + { // fall back to creature home position startPosition = me->GetHomePosition(); - if (!CheckBoundary(&startPosition)) // fall back to creature home position + if (!CheckBoundary(&startPosition)) return LANG_CREATURE_NO_INTERIOR_POINT_FOUND; } } diff --git a/src/server/game/AI/CreatureAI.h b/src/server/game/AI/CreatureAI.h index f175050e107..f8fa6ba532b 100644 --- a/src/server/game/AI/CreatureAI.h +++ b/src/server/game/AI/CreatureAI.h @@ -87,6 +87,7 @@ class TC_GAME_API CreatureAI : public UnitAI { EVADE_REASON_NO_HOSTILES, // the creature's threat list is empty EVADE_REASON_BOUNDARY, // the creature has moved outside its evade boundary + EVADE_REASON_NO_PATH, // the creature was unable to reach its target for over 5 seconds EVADE_REASON_SEQUENCE_BREAK, // this is a boss and the pre-requisite encounters for engaging it are not defeated yet EVADE_REASON_OTHER }; @@ -111,7 +112,7 @@ class TC_GAME_API CreatureAI : public UnitAI // Called for reaction at stopping attack at no attackers or targets virtual void EnterEvadeMode(EvadeReason why = EVADE_REASON_OTHER); - // Called for reaction at enter to combat if not in combat yet (enemy can be NULL) + // Called for reaction at enter to combat if not in combat yet (enemy can be nullptr) virtual void EnterCombat(Unit* /*victim*/) { } // Called when the creature is killed @@ -148,7 +149,7 @@ class TC_GAME_API CreatureAI : public UnitAI // Called at reaching home after evade virtual void JustReachedHome() { } - void DoZoneInCombat(Creature* creature = NULL, float maxRangeToNearestTarget = 50.0f); + void DoZoneInCombat(Creature* creature = nullptr, float maxRangeToNearestTarget = 250.0f); // Called at text emote receive from player virtual void ReceiveEmote(Player* /*player*/, uint32 /*emoteId*/) { } diff --git a/src/server/game/AI/PlayerAI/PlayerAI.cpp b/src/server/game/AI/PlayerAI/PlayerAI.cpp index 680ecfb9414..68cb268ac6c 100644 --- a/src/server/game/AI/PlayerAI/PlayerAI.cpp +++ b/src/server/game/AI/PlayerAI/PlayerAI.cpp @@ -19,6 +19,51 @@ #include "SpellAuras.h" #include "SpellAuraEffects.h" +static const uint8 NUM_TALENT_TREES = 3; +static const uint8 NUM_SPEC_ICONICS = 3; + +enum Specs +{ + SPEC_WARRIOR_ARMS = 0, + SPEC_WARRIOR_FURY = 1, + SPEC_WARRIOR_PROTECTION = 2, + + SPEC_PALADIN_HOLY = 0, + SPEC_PALADIN_PROTECTION = 1, + SPEC_PALADIN_RETRIBUTION = 2, + + SPEC_HUNTER_BEAST_MASTERY = 0, + SPEC_HUNTER_MARKSMANSHIP = 1, + SPEC_HUNTER_SURVIVAL = 2, + + SPEC_ROGUE_ASSASSINATION = 0, + SPEC_ROGUE_COMBAT = 1, + SPEC_ROGUE_SUBLETY = 2, + + SPEC_PRIEST_DISCIPLINE = 0, + SPEC_PRIEST_HOLY = 1, + SPEC_PRIEST_SHADOW = 2, + + SPEC_DEATH_KNIGHT_BLOOD = 0, + SPEC_DEATH_KNIGHT_FROST = 1, + SPEC_DEATH_KNIGHT_UNHOLY = 2, + + SPEC_SHAMAN_ELEMENTAL = 0, + SPEC_SHAMAN_ENHANCEMENT = 1, + SPEC_SHAMAN_RESTORATION = 2, + + SPEC_MAGE_ARCANE = 0, + SPEC_MAGE_FIRE = 1, + SPEC_MAGE_FROST = 2, + + SPEC_WARLOCK_AFFLICTION = 0, + SPEC_WARLOCK_DEMONOLOGY = 1, + SPEC_WARLOCK_DESTRUCTION = 2, + + SPEC_DRUID_BALANCE = 0, + SPEC_DRUID_FERAL = 1, + SPEC_DRUID_RESTORATION = 2 +}; enum Spells { /* Generic */ @@ -27,29 +72,449 @@ enum Spells SPELL_THROW = 2764, SPELL_SHOOT_WAND = 5019, - /* Paladin */ - PASSIVE_ILLUMINATION = 20215, + /* Warrior - Generic */ + SPELL_BATTLE_STANCE = 2457, + SPELL_BERSERKER_STANCE = 2458, + SPELL_DEFENSIVE_STANCE = 71, + SPELL_CHARGE = 11578, + SPELL_INTERCEPT = 20252, + SPELL_ENRAGED_REGEN = 55694, + SPELL_INTIMIDATING_SHOUT= 5246, + SPELL_PUMMEL = 6552, + SPELL_SHIELD_BASH = 72, + SPELL_BLOODRAGE = 2687, + + /* Warrior - Arms */ + SPELL_SWEEPING_STRIKES = 12328, + SPELL_MORTAL_STRIKE = 12294, + SPELL_BLADESTORM = 46924, + SPELL_REND = 47465, + SPELL_RETALIATION = 20230, + SPELL_SHATTERING_THROW = 64382, + SPELL_THUNDER_CLAP = 47502, + + /* Warrior - Fury */ + SPELL_DEATH_WISH = 12292, + SPELL_BLOODTHIRST = 23881, + PASSIVE_TITANS_GRIP = 46917, + SPELL_DEMO_SHOUT = 47437, + SPELL_EXECUTE = 47471, + SPELL_HEROIC_FURY = 60970, + SPELL_RECKLESSNESS = 1719, + SPELL_PIERCING_HOWL = 12323, + + /* Warrior - Protection */ + SPELL_VIGILANCE = 50720, + SPELL_DEVASTATE = 20243, + SPELL_SHOCKWAVE = 46968, + SPELL_CONCUSSION_BLOW = 12809, + SPELL_DISARM = 676, + SPELL_LAST_STAND = 12975, + SPELL_SHIELD_BLOCK = 2565, + SPELL_SHIELD_SLAM = 47488, + SPELL_SHIELD_WALL = 871, + SPELL_SPELL_REFLECTION = 23920, + + /* Paladin - Generic */ + SPELL_AURA_MASTERY = 31821, + SPELL_LAY_ON_HANDS = 48788, + SPELL_BLESSING_OF_MIGHT = 48932, + SPELL_AVENGING_WRATH = 31884, + SPELL_DIVINE_PROTECTION = 498, + SPELL_DIVINE_SHIELD = 642, + SPELL_HAMMER_OF_JUSTICE = 10308, + SPELL_HAND_OF_FREEDOM = 1044, + SPELL_HAND_OF_PROTECTION = 10278, + SPELL_HAND_OF_SACRIFICE = 6940, + + /* Paladin - Holy*/ + PASSIVE_ILLUMINATION = 20215, + SPELL_HOLY_SHOCK = 20473, + SPELL_BEACON_OF_LIGHT = 53563, + SPELL_CONSECRATION = 48819, + SPELL_FLASH_OF_LIGHT = 48785, + SPELL_HOLY_LIGHT = 48782, + SPELL_DIVINE_FAVOR = 20216, + SPELL_DIVINE_ILLUMINATION = 31842, + + /* Paladin - Protection */ + SPELL_BLESS_OF_SANC = 20911, + SPELL_HOLY_SHIELD = 20925, + SPELL_AVENGERS_SHIELD = 48827, + SPELL_DIVINE_SACRIFICE = 64205, + SPELL_HAMMER_OF_RIGHTEOUS = 53595, + SPELL_RIGHTEOUS_FURY = 25780, + SPELL_SHIELD_OF_RIGHTEOUS = 61411, + + /* Paladin - Retribution */ + SPELL_SEAL_OF_COMMAND = 20375, + SPELL_CRUSADER_STRIKE = 35395, + SPELL_DIVINE_STORM = 53385, + SPELL_JUDGEMENT = 20271, + SPELL_HAMMER_OF_WRATH = 48806, + + /* Hunter - Generic */ + SPELL_DETERRENCE = 19263, + SPELL_EXPLOSIVE_TRAP = 49067, + SPELL_FREEZING_ARROW = 60192, + SPELL_RAPID_FIRE = 3045, + SPELL_KILL_SHOT = 61006, + SPELL_MULTI_SHOT = 49048, + SPELL_VIPER_STING = 3034, + + /* Hunter - Beast Mastery */ + SPELL_BESTIAL_WRATH = 19574, + PASSIVE_BEAST_WITHIN = 34692, + PASSIVE_BEAST_MASTERY = 53270, + + /* Hunter - Marksmanship */ + SPELL_AIMED_SHOT = 19434, + PASSIVE_TRUESHOT_AURA = 19506, + SPELL_CHIMERA_SHOT = 53209, + SPELL_ARCANE_SHOT = 49045, + SPELL_STEADY_SHOT = 49052, + SPELL_READINESS = 23989, + SPELL_SILENCING_SHOT = 34490, - /* Priest */ - SPELL_SOUL_WARDING = 63574, - SPELL_SPIRIT_REDEMPTION = 20711, - SPELL_SHADOWFORM = 15473, + /* Hunter - Survival */ + PASSIVE_LOCK_AND_LOAD = 56344, + SPELL_WYVERN_STING = 19386, + SPELL_EXPLOSIVE_SHOT = 53301, + SPELL_BLACK_ARROW = 3674, - /* Shaman */ - SPELL_TIDAL_FORCE = 582, - SPELL_MANA_TIDE_TOTEM = 590, - SPELL_SHA_NATURE_SWIFT = 591, + /* Rogue - Generic */ + SPELL_DISMANTLE = 51722, + SPELL_EVASION = 26669, + SPELL_KICK = 1766, + SPELL_VANISH = 26889, + SPELL_BLIND = 2094, + SPELL_CLOAK_OF_SHADOWS = 31224, + + /* Rogue - Assassination */ + SPELL_COLD_BLOOD = 14177, + SPELL_MUTILATE = 1329, + SPELL_HUNGER_FOR_BLOOD = 51662, + SPELL_ENVENOM = 57993, + + /* Rogue - Combat */ + SPELL_SINISTER_STRIKE = 48637, + SPELL_BLADE_FLURRY = 13877, + SPELL_ADRENALINE_RUSH = 13750, + SPELL_KILLING_SPREE = 51690, + SPELL_EVISCERATE = 48668, + + /* Rogue - Sublety */ + SPELL_HEMORRHAGE = 16511, + SPELL_PREMEDITATION = 14183, + SPELL_SHADOW_DANCE = 51713, + SPELL_PREPARATION = 14185, + SPELL_SHADOWSTEP = 36554, + + /* Priest - Generic */ + SPELL_FEAR_WARD = 6346, + SPELL_POWER_WORD_FORT = 48161, + SPELL_DIVINE_SPIRIT = 48073, + SPELL_SHADOW_PROTECTION = 48169, + SPELL_DIVINE_HYMN = 64843, + SPELL_HYMN_OF_HOPE = 64901, + SPELL_SHADOW_WORD_DEATH = 48158, + SPELL_PSYCHIC_SCREAM = 10890, + + /* Priest - Discipline */ + PASSIVE_SOUL_WARDING = 63574, + SPELL_POWER_INFUSION = 10060, + SPELL_PENANCE = 47540, + SPELL_PAIN_SUPPRESSION = 33206, + SPELL_INNER_FOCUS = 14751, + SPELL_POWER_WORD_SHIELD = 48066, + + /* Priest - Holy */ + PASSIVE_SPIRIT_REDEMPTION = 20711, + SPELL_DESPERATE_PRAYER = 19236, + SPELL_GUARDIAN_SPIRIT = 47788, + SPELL_FLASH_HEAL = 48071, + SPELL_RENEW = 48068, + + /* Priest - Shadow */ + SPELL_VAMPIRIC_EMBRACE = 15286, + SPELL_SHADOWFORM = 15473, + SPELL_VAMPIRIC_TOUCH = 34914, + SPELL_MIND_FLAY = 15407, + SPELL_MIND_BLAST = 48127, + SPELL_SHADOW_WORD_PAIN = 48125, + SPELL_DEVOURING_PLAGUE = 48300, + SPELL_DISPERSION = 47585, + + /* Death Knight - Generic */ + SPELL_DEATH_GRIP = 49576, + SPELL_STRANGULATE = 47476, + SPELL_EMPOWER_RUNE_WEAP = 47568, + SPELL_ICEBORN_FORTITUDE = 48792, + SPELL_ANTI_MAGIC_SHELL = 48707, + SPELL_DEATH_COIL_DK = 49895, + SPELL_MIND_FREEZE = 47528, + SPELL_ICY_TOUCH = 49909, + AURA_FROST_FEVER = 55095, + SPELL_PLAGUE_STRIKE = 49921, + AURA_BLOOD_PLAGUE = 55078, + SPELL_PESTILENCE = 50842, + + /* Death Knight - Blood */ + SPELL_RUNE_TAP = 48982, + SPELL_HYSTERIA = 49016, + SPELL_HEART_STRIKE = 55050, + SPELL_DEATH_STRIKE = 49924, + SPELL_BLOOD_STRIKE = 49930, + SPELL_MARK_OF_BLOOD = 49005, + SPELL_VAMPIRIC_BLOOD = 55233, + + /* Death Knight - Frost */ + PASSIVE_ICY_TALONS = 50887, + SPELL_FROST_STRIKE = 49143, + SPELL_HOWLING_BLAST = 49184, + SPELL_UNBREAKABLE_ARMOR = 51271, + SPELL_OBLITERATE = 51425, + SPELL_DEATHCHILL = 49796, + + /* Death Knight - Unholy */ + PASSIVE_UNHOLY_BLIGHT = 49194, + PASSIVE_MASTER_OF_GHOUL = 52143, + SPELL_SCOURGE_STRIKE = 55090, + SPELL_DEATH_AND_DECAY = 49938, + SPELL_ANTI_MAGIC_ZONE = 51052, + SPELL_SUMMON_GARGOYLE = 49206, + + /* Shaman - Generic */ + SPELL_HEROISM = 32182, + SPELL_BLOODLUST = 2825, + SPELL_GROUNDING_TOTEM = 8177, + + /* Shaman - Elemental*/ + PASSIVE_ELEMENTAL_FOCUS = 16164, + SPELL_TOTEM_OF_WRATH = 30706, + SPELL_THUNDERSTORM = 51490, + SPELL_LIGHTNING_BOLT = 49238, + SPELL_EARTH_SHOCK = 49231, + SPELL_FLAME_SHOCK = 49233, + SPELL_LAVA_BURST = 60043, + SPELL_CHAIN_LIGHTNING = 49271, + SPELL_ELEMENTAL_MASTERY = 16166, + + /* Shaman - Enhancement */ + PASSIVE_SPIRIT_WEAPONS = 16268, + SPELL_LAVA_LASH = 60103, + SPELL_FERAL_SPIRIT = 51533, + AURA_MAELSTROM_WEAPON = 53817, SPELL_STORMSTRIKE = 17364, + SPELL_SHAMANISTIC_RAGE = 30823, + + /* Shaman - Restoration*/ + SPELL_SHA_NATURE_SWIFT = 591, + SPELL_MANA_TIDE_TOTEM = 590, + SPELL_EARTH_SHIELD = 49284, + SPELL_RIPTIDE = 61295, + SPELL_HEALING_WAVE = 49273, + SPELL_LESSER_HEAL_WAVE = 49276, + SPELL_TIDAL_FORCE = 55198, + + /* Mage - Generic */ + SPELL_DAMPEN_MAGIC = 43015, + SPELL_EVOCATION = 12051, + SPELL_MANA_SHIELD = 43020, + SPELL_MIRROR_IMAGE = 55342, + SPELL_SPELLSTEAL = 30449, + SPELL_COUNTERSPELL = 2139, + SPELL_ICE_BLOCK = 45438, + + /* Mage - Arcane */ + SPELL_FOCUS_MAGIC = 54646, + SPELL_ARCANE_POWER = 12042, + SPELL_ARCANE_BARRAGE = 44425, + SPELL_ARCANE_BLAST = 42897, + AURA_ARCANE_BLAST = 36032, + SPELL_ARCANE_MISSILES = 42846, + SPELL_PRESENCE_OF_MIND = 12043, + + /* Mage - Fire */ + SPELL_PYROBLAST = 11366, + SPELL_COMBUSTION = 11129, + SPELL_LIVING_BOMB = 44457, + SPELL_FIREBALL = 42833, + SPELL_FIRE_BLAST = 42873, + SPELL_DRAGONS_BREATH = 31661, + SPELL_BLAST_WAVE = 11113, + + /* Mage - Frost */ + SPELL_ICY_VEINS = 12472, + SPELL_ICE_BARRIER = 11426, + SPELL_DEEP_FREEZE = 44572, + SPELL_FROST_NOVA = 42917, + SPELL_FROSTBOLT = 42842, + SPELL_COLD_SNAP = 11958, + SPELL_ICE_LANCE = 42914, + + /* Warlock - Generic */ + SPELL_FEAR = 6215, + SPELL_HOWL_OF_TERROR = 17928, + SPELL_CORRUPTION = 47813, + SPELL_DEATH_COIL_W = 47860, + SPELL_SHADOW_BOLT = 47809, + SPELL_INCINERATE = 47838, + SPELL_IMMOLATE = 47811, + SPELL_SEED_OF_CORRUPTION = 47836, + + /* Warlock - Affliction */ + PASSIVE_SIPHON_LIFE = 63108, + SPELL_UNSTABLE_AFFLICTION = 30108, + SPELL_HAUNT = 48181, + SPELL_CURSE_OF_AGONY = 47864, + SPELL_DRAIN_SOUL = 47855, - /* Druid */ - SPELL_MOONKIN_FORM = 24858, - SPELL_SWIFTMEND = 18562, - SPELL_DRU_NATURE_SWIFT = 17116, - SPELL_TREE_OF_LIFE = 33891 + /* Warlock - Demonology */ + SPELL_SOUL_LINK = 19028, + SPELL_DEMONIC_EMPOWERMENT = 47193, + SPELL_METAMORPHOSIS = 59672, + SPELL_IMMOLATION_AURA = 50589, + SPELL_DEMON_CHARGE = 54785, + AURA_DECIMATION = 63167, + AURA_MOLTEN_CORE = 71165, + SPELL_SOUL_FIRE = 47825, + + /* Warlock - Destruction */ + SPELL_SHADOWBURN = 17877, + SPELL_CONFLAGRATE = 17962, + SPELL_CHAOS_BOLT = 50796, + SPELL_SHADOWFURY = 47847, + + /* Druid - Generic */ + SPELL_BARKSKIN = 22812, + SPELL_INNERVATE = 29166, + + /* Druid - Balance */ + SPELL_INSECT_SWARM = 5570, + SPELL_MOONKIN_FORM = 24858, + SPELL_STARFALL = 48505, + SPELL_TYPHOON = 61384, + AURA_ECLIPSE_LUNAR = 48518, + SPELL_MOONFIRE = 48463, + SPELL_STARFIRE = 48465, + SPELL_WRATH = 48461, + + /* Druid - Feral */ + SPELL_CAT_FORM = 768, + SPELL_SURVIVAL_INSTINCTS = 61336, + SPELL_MANGLE = 33917, + SPELL_BERSERK = 50334, + SPELL_MANGLE_CAT = 48566, + SPELL_FERAL_CHARGE_CAT = 49376, + SPELL_RAKE = 48574, + SPELL_RIP = 49800, + SPELL_SAVAGE_ROAR = 52610, + SPELL_TIGER_FURY = 50213, + SPELL_CLAW = 48570, + SPELL_DASH = 33357, + SPELL_MAIM = 49802, + + /* Druid - Restoration */ + SPELL_SWIFTMEND = 18562, + SPELL_TREE_OF_LIFE = 33891, + SPELL_WILD_GROWTH = 48438, + SPELL_NATURE_SWIFTNESS = 17116, + SPELL_TRANQUILITY = 48447, + SPELL_NOURISH = 50464, + SPELL_HEALING_TOUCH = 48378, + SPELL_REJUVENATION = 48441, + SPELL_REGROWTH = 48443, + SPELL_LIFEBLOOM = 48451 }; +// As it turns out, finding out "how many points does the player have in spec X" is actually really expensive to do frequently +// So instead, we just check for a handful of spells that, realistically, no spec is gonna go without (and "has spell" is cheap!) +// Can players deliberately trick this check? Yes. +// Is it worth doing? No. +// Close enough. +static const uint32 SPEC_ICONICS[MAX_CLASSES][NUM_TALENT_TREES][NUM_SPEC_ICONICS] = { + { // CLASS_NONE + {0,0,0}, + {0,0,0}, + {0,0,0} + }, + { // CLASS_WARRIOR + {SPELL_BLADESTORM, SPELL_MORTAL_STRIKE, SPELL_SWEEPING_STRIKES}, // Arms + {PASSIVE_TITANS_GRIP, SPELL_BLOODTHIRST, SPELL_DEATH_WISH}, // Fury + {SPELL_SHOCKWAVE, SPELL_DEVASTATE, SPELL_VIGILANCE} // Protection + }, + { // CLASS_PALADIN + {SPELL_BEACON_OF_LIGHT, SPELL_HOLY_SHOCK, PASSIVE_ILLUMINATION}, // Holy + {SPELL_HAMMER_OF_RIGHTEOUS, SPELL_HOLY_SHIELD, SPELL_BLESS_OF_SANC}, // Protection + {SPELL_DIVINE_STORM, SPELL_CRUSADER_STRIKE, SPELL_SEAL_OF_COMMAND} // Retribution + }, + { // CLASS_HUNTER + {PASSIVE_BEAST_MASTERY, PASSIVE_BEAST_WITHIN, SPELL_BESTIAL_WRATH}, // Beast Mastery + {SPELL_CHIMERA_SHOT, PASSIVE_TRUESHOT_AURA, SPELL_AIMED_SHOT}, // Marksmanship + {SPELL_EXPLOSIVE_SHOT, SPELL_WYVERN_STING, PASSIVE_LOCK_AND_LOAD} // Survival + }, + { // CLASS_ROGUE + {SPELL_HUNGER_FOR_BLOOD, SPELL_MUTILATE, SPELL_COLD_BLOOD}, // Assassination + {SPELL_KILLING_SPREE, SPELL_ADRENALINE_RUSH, SPELL_BLADE_FLURRY}, // Combat + {SPELL_SHADOW_DANCE, SPELL_PREMEDITATION, SPELL_HEMORRHAGE} // Sublety + }, + { // CLASS_PRIEST + {SPELL_PENANCE, SPELL_POWER_INFUSION, PASSIVE_SOUL_WARDING}, // Discipline + {SPELL_GUARDIAN_SPIRIT, PASSIVE_SPIRIT_REDEMPTION, SPELL_DESPERATE_PRAYER}, // Holy + {SPELL_VAMPIRIC_TOUCH, SPELL_SHADOWFORM, SPELL_VAMPIRIC_EMBRACE} // Shadow + }, + { // CLASS_DEATH_KNIGHT + {SPELL_HEART_STRIKE, SPELL_HYSTERIA, SPELL_RUNE_TAP}, // Blood + {SPELL_HOWLING_BLAST, SPELL_FROST_STRIKE, PASSIVE_ICY_TALONS}, // Frost + {SPELL_SCOURGE_STRIKE, PASSIVE_MASTER_OF_GHOUL, PASSIVE_UNHOLY_BLIGHT} // Unholy + }, + { // CLASS_SHAMAN + {SPELL_THUNDERSTORM, SPELL_TOTEM_OF_WRATH, PASSIVE_ELEMENTAL_FOCUS}, // Elemental + {SPELL_FERAL_SPIRIT, SPELL_LAVA_LASH, PASSIVE_SPIRIT_WEAPONS}, // Enhancement + {SPELL_RIPTIDE, SPELL_MANA_TIDE_TOTEM, SPELL_SHA_NATURE_SWIFT} // Restoration + }, + { // CLASS_MAGE + {SPELL_ARCANE_BARRAGE, SPELL_ARCANE_POWER, SPELL_FOCUS_MAGIC}, // Arcane + {SPELL_LIVING_BOMB, SPELL_COMBUSTION, SPELL_PYROBLAST}, // Fire + {SPELL_DEEP_FREEZE, SPELL_ICE_BARRIER, SPELL_ICY_VEINS} // Frost + }, + { // CLASS_WARLOCK + {SPELL_HAUNT, SPELL_UNSTABLE_AFFLICTION, PASSIVE_SIPHON_LIFE}, // Affliction + {SPELL_METAMORPHOSIS, SPELL_DEMONIC_EMPOWERMENT, SPELL_SOUL_LINK}, // Demonology + {SPELL_CHAOS_BOLT, SPELL_CONFLAGRATE, SPELL_SHADOWBURN} // Destruction + }, + { // CLASS_UNK + {0,0,0}, + {0,0,0}, + {0,0,0} + }, + { // CLASS_DRUID + {SPELL_STARFALL, SPELL_MOONKIN_FORM, SPELL_INSECT_SWARM}, // Balance + {SPELL_BERSERK, SPELL_MANGLE, SPELL_SURVIVAL_INSTINCTS}, // Feral + {SPELL_WILD_GROWTH, SPELL_TREE_OF_LIFE, SPELL_SWIFTMEND} // Restoration + } +}; + +uint8 PlayerAI::GetPlayerSpec(Player const* who) +{ + if (!who) + return 0; + + uint8 wClass = who->getClass(); + for (uint8 tier = 0; tier < NUM_SPEC_ICONICS; ++tier) + for (uint8 tree = 0; tree < NUM_TALENT_TREES; ++tree) + if (SPEC_ICONICS[wClass][tree][tier] && who->HasSpell(SPEC_ICONICS[wClass][tree][tier])) + return tree; + + return 0; +} + bool PlayerAI::IsPlayerHealer(Player const* who) { + if (!who) + return false; + switch (who->getClass()) { case CLASS_WARRIOR: @@ -61,18 +526,21 @@ bool PlayerAI::IsPlayerHealer(Player const* who) default: return false; case CLASS_PALADIN: - return who->HasSpell(PASSIVE_ILLUMINATION); + return (PlayerAI::GetPlayerSpec(who) == SPEC_PALADIN_HOLY); case CLASS_PRIEST: - return who->HasSpell(SPELL_SOUL_WARDING) || who->HasSpell(SPELL_SPIRIT_REDEMPTION); + return (PlayerAI::GetPlayerSpec(who) != SPEC_PRIEST_SHADOW); case CLASS_SHAMAN: - return who->HasSpell(SPELL_MANA_TIDE_TOTEM) || who->HasSpell(SPELL_SHA_NATURE_SWIFT) || who->HasSpell(SPELL_TIDAL_FORCE); + return (PlayerAI::GetPlayerSpec(who) == SPEC_SHAMAN_RESTORATION); case CLASS_DRUID: - return who->HasSpell(SPELL_SWIFTMEND) || who->HasSpell(SPELL_DRU_NATURE_SWIFT) || who->HasSpell(SPELL_TREE_OF_LIFE); + return (PlayerAI::GetPlayerSpec(who) == SPEC_DRUID_RESTORATION); } } bool PlayerAI::IsPlayerRangedAttacker(Player const* who) { + if (!who) + return false; + switch (who->getClass()) { case CLASS_WARRIOR: @@ -94,12 +562,106 @@ bool PlayerAI::IsPlayerRangedAttacker(Player const* who) return false; } case CLASS_PRIEST: - return who->HasSpell(SPELL_SHADOWFORM); + return (PlayerAI::GetPlayerSpec(who) == SPEC_PRIEST_SHADOW); case CLASS_SHAMAN: - return !who->HasSpell(SPELL_STORMSTRIKE); + return (PlayerAI::GetPlayerSpec(who) == SPEC_SHAMAN_ELEMENTAL); case CLASS_DRUID: - return who->HasSpell(SPELL_MOONKIN_FORM); + return (PlayerAI::GetPlayerSpec(who) == SPEC_DRUID_BALANCE); + } +} + +PlayerAI::TargetedSpell PlayerAI::VerifySpellCast(uint32 spellId, Unit* target) +{ + // Find highest spell rank that we know + uint32 knownRank, nextRank; + if (me->HasSpell(spellId)) + { + // this will save us some lookups if the player has the highest rank (expected case) + knownRank = spellId; + nextRank = sSpellMgr->GetNextSpellInChain(spellId); + } + else + { + knownRank = 0; + nextRank = sSpellMgr->GetFirstSpellInChain(spellId); + } + + while (nextRank && me->HasSpell(nextRank)) + { + knownRank = nextRank; + nextRank = sSpellMgr->GetNextSpellInChain(knownRank); + } + + if (!knownRank) + return {}; + + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(knownRank); + if (!spellInfo) + return {}; + + if (me->GetSpellHistory()->HasGlobalCooldown(spellInfo)) + return {}; + + Spell* spell = new Spell(me, spellInfo, TRIGGERED_NONE); + if (spell->CanAutoCast(target)) + return{ spell, target }; + + delete spell; + return {}; +} + +PlayerAI::TargetedSpell PlayerAI::VerifySpellCast(uint32 spellId, SpellTarget target) +{ + Unit* pTarget = nullptr; + switch (target) + { + case TARGET_NONE: + break; + case TARGET_VICTIM: + pTarget = me->GetVictim(); + if (!pTarget) + return {}; + break; + case TARGET_CHARMER: + pTarget = me->GetCharmer(); + if (!pTarget) + return {}; + break; + case TARGET_SELF: + pTarget = me; + break; + } + + return VerifySpellCast(spellId, pTarget); +} + +PlayerAI::TargetedSpell PlayerAI::SelectSpellCast(PossibleSpellVector& spells) +{ + uint32 totalWeights = 0; + for (PossibleSpell const& wSpell : spells) + totalWeights += wSpell.second; + + TargetedSpell selected; + uint32 randNum = urand(0, totalWeights - 1); + for (PossibleSpell const& wSpell : spells) + { + if (selected) + { + delete wSpell.first.first; + continue; + } + + if (randNum < wSpell.second) + selected = wSpell.first; + else + { + randNum -= wSpell.second; + delete wSpell.first.first; + } } + + spells.clear(); + return selected; } void PlayerAI::DoRangedAttackIfReady() @@ -150,6 +712,29 @@ void PlayerAI::DoAutoAttackIfReady() DoMeleeAttackIfReady(); } +void PlayerAI::CancelAllShapeshifts() +{ + std::list<AuraEffect*> const& shapeshiftAuras = me->GetAuraEffectsByType(SPELL_AURA_MOD_SHAPESHIFT); + std::set<Aura*> removableShapeshifts; + for (AuraEffect* auraEff : shapeshiftAuras) + { + Aura* aura = auraEff->GetBase(); + if (!aura) + continue; + SpellInfo const* auraInfo = aura->GetSpellInfo(); + if (!auraInfo) + continue; + if (auraInfo->HasAttribute(SPELL_ATTR0_CANT_CANCEL)) + continue; + if (!auraInfo->IsPositive() || auraInfo->IsPassive()) + continue; + removableShapeshifts.insert(aura); + } + + for (Aura* aura : removableShapeshifts) + me->RemoveOwnedAura(aura, AURA_REMOVE_BY_CANCEL); +} + struct UncontrolledTargetSelectPredicate : public std::unary_function<Unit*, bool> { bool operator()(Unit const* target) const @@ -164,7 +749,516 @@ Unit* SimpleCharmedPlayerAI::SelectAttackTarget() const return nullptr; } -void SimpleCharmedPlayerAI::UpdateAI(const uint32 /*diff*/) +PlayerAI::TargetedSpell SimpleCharmedPlayerAI::SelectAppropriateCastForSpec() +{ + PossibleSpellVector spells; + + switch (me->getClass()) + { + case CLASS_WARRIOR: + if (!me->IsWithinMeleeRange(me->GetVictim())) + { + VerifyAndPushSpellCast(spells, SPELL_CHARGE, TARGET_VICTIM, 15); + VerifyAndPushSpellCast(spells, SPELL_INTERCEPT, TARGET_VICTIM, 10); + } + VerifyAndPushSpellCast(spells, SPELL_ENRAGED_REGEN, TARGET_NONE, 3); + VerifyAndPushSpellCast(spells, SPELL_INTIMIDATING_SHOUT, TARGET_VICTIM, 4); + if (me->GetVictim() && me->GetVictim()->HasUnitState(UNIT_STATE_CASTING)) + { + VerifyAndPushSpellCast(spells, SPELL_PUMMEL, TARGET_VICTIM, 15); + VerifyAndPushSpellCast(spells, SPELL_SHIELD_BASH, TARGET_VICTIM, 15); + } + VerifyAndPushSpellCast(spells, SPELL_BLOODRAGE, TARGET_NONE, 5); + switch (GetSpec()) + { + case SPEC_WARRIOR_PROTECTION: + VerifyAndPushSpellCast(spells, SPELL_SHOCKWAVE, TARGET_VICTIM, 3); + VerifyAndPushSpellCast(spells, SPELL_CONCUSSION_BLOW, TARGET_VICTIM, 5); + VerifyAndPushSpellCast(spells, SPELL_DISARM, TARGET_VICTIM, 2); + VerifyAndPushSpellCast(spells, SPELL_LAST_STAND, TARGET_NONE, 5); + VerifyAndPushSpellCast(spells, SPELL_SHIELD_BLOCK, TARGET_NONE, 1); + VerifyAndPushSpellCast(spells, SPELL_SHIELD_SLAM, TARGET_VICTIM, 4); + VerifyAndPushSpellCast(spells, SPELL_SHIELD_WALL, TARGET_NONE, 5); + VerifyAndPushSpellCast(spells, SPELL_SPELL_REFLECTION, TARGET_NONE, 3); + VerifyAndPushSpellCast(spells, SPELL_DEVASTATE, TARGET_VICTIM, 2); + VerifyAndPushSpellCast(spells, SPELL_REND, TARGET_VICTIM, 1); + VerifyAndPushSpellCast(spells, SPELL_THUNDER_CLAP, TARGET_VICTIM, 2); + VerifyAndPushSpellCast(spells, SPELL_DEMO_SHOUT, TARGET_VICTIM, 1); + break; + case SPEC_WARRIOR_ARMS: + VerifyAndPushSpellCast(spells, SPELL_SWEEPING_STRIKES, TARGET_NONE, 2); + VerifyAndPushSpellCast(spells, SPELL_MORTAL_STRIKE, TARGET_VICTIM, 5); + VerifyAndPushSpellCast(spells, SPELL_BLADESTORM, TARGET_NONE, 10); + VerifyAndPushSpellCast(spells, SPELL_REND, TARGET_VICTIM, 1); + VerifyAndPushSpellCast(spells, SPELL_RETALIATION, TARGET_NONE, 3); + VerifyAndPushSpellCast(spells, SPELL_SHATTERING_THROW, TARGET_VICTIM, 3); + VerifyAndPushSpellCast(spells, SPELL_SWEEPING_STRIKES, TARGET_NONE, 5); + VerifyAndPushSpellCast(spells, SPELL_THUNDER_CLAP, TARGET_VICTIM, 1); + VerifyAndPushSpellCast(spells, SPELL_EXECUTE, TARGET_VICTIM, 15); + break; + case SPEC_WARRIOR_FURY: + VerifyAndPushSpellCast(spells, SPELL_DEATH_WISH, TARGET_NONE, 10); + VerifyAndPushSpellCast(spells, SPELL_BLOODTHIRST, TARGET_VICTIM, 4); + VerifyAndPushSpellCast(spells, SPELL_DEMO_SHOUT, TARGET_VICTIM, 2); + VerifyAndPushSpellCast(spells, SPELL_EXECUTE, TARGET_VICTIM, 15); + VerifyAndPushSpellCast(spells, SPELL_HEROIC_FURY, TARGET_NONE, 5); + VerifyAndPushSpellCast(spells, SPELL_RECKLESSNESS, TARGET_NONE, 8); + VerifyAndPushSpellCast(spells, SPELL_PIERCING_HOWL, TARGET_VICTIM, 2); + break; + } + break; + case CLASS_PALADIN: + VerifyAndPushSpellCast(spells, SPELL_AURA_MASTERY, TARGET_NONE, 3); + VerifyAndPushSpellCast(spells, SPELL_LAY_ON_HANDS, TARGET_CHARMER, 8); + VerifyAndPushSpellCast(spells, SPELL_BLESSING_OF_MIGHT, TARGET_CHARMER, 8); + VerifyAndPushSpellCast(spells, SPELL_AVENGING_WRATH, TARGET_NONE, 5); + VerifyAndPushSpellCast(spells, SPELL_DIVINE_PROTECTION, TARGET_NONE, 4); + VerifyAndPushSpellCast(spells, SPELL_DIVINE_SHIELD, TARGET_NONE, 2); + VerifyAndPushSpellCast(spells, SPELL_HAMMER_OF_JUSTICE, TARGET_VICTIM, 6); + VerifyAndPushSpellCast(spells, SPELL_HAND_OF_FREEDOM, TARGET_SELF, 3); + VerifyAndPushSpellCast(spells, SPELL_HAND_OF_PROTECTION, TARGET_SELF, 1); + if (Creature* creatureCharmer = ObjectAccessor::GetCreature(*me, me->GetCharmerGUID())) + { + if (creatureCharmer->IsDungeonBoss() || creatureCharmer->isWorldBoss()) + VerifyAndPushSpellCast(spells, SPELL_HAND_OF_SACRIFICE, creatureCharmer, 10); + else + VerifyAndPushSpellCast(spells, SPELL_HAND_OF_PROTECTION, creatureCharmer, 3); + } + + switch (GetSpec()) + { + case SPEC_PALADIN_PROTECTION: + VerifyAndPushSpellCast(spells, SPELL_HAMMER_OF_RIGHTEOUS, TARGET_VICTIM, 3); + VerifyAndPushSpellCast(spells, SPELL_DIVINE_SACRIFICE, TARGET_NONE, 2); + VerifyAndPushSpellCast(spells, SPELL_SHIELD_OF_RIGHTEOUS, TARGET_VICTIM, 4); + VerifyAndPushSpellCast(spells, SPELL_JUDGEMENT, TARGET_VICTIM, 2); + VerifyAndPushSpellCast(spells, SPELL_CONSECRATION, TARGET_VICTIM, 2); + VerifyAndPushSpellCast(spells, SPELL_HOLY_SHIELD, TARGET_NONE, 1); + break; + case SPEC_PALADIN_HOLY: + VerifyAndPushSpellCast(spells, SPELL_HOLY_SHOCK, TARGET_CHARMER, 3); + VerifyAndPushSpellCast(spells, SPELL_HOLY_SHOCK, TARGET_VICTIM, 1); + VerifyAndPushSpellCast(spells, SPELL_FLASH_OF_LIGHT, TARGET_CHARMER, 4); + VerifyAndPushSpellCast(spells, SPELL_HOLY_LIGHT, TARGET_CHARMER, 3); + VerifyAndPushSpellCast(spells, SPELL_DIVINE_FAVOR, TARGET_NONE, 5); + VerifyAndPushSpellCast(spells, SPELL_DIVINE_ILLUMINATION, TARGET_NONE, 3); + break; + case SPEC_PALADIN_RETRIBUTION: + VerifyAndPushSpellCast(spells, SPELL_CRUSADER_STRIKE, TARGET_VICTIM, 4); + VerifyAndPushSpellCast(spells, SPELL_DIVINE_STORM, TARGET_VICTIM, 5); + VerifyAndPushSpellCast(spells, SPELL_JUDGEMENT, TARGET_VICTIM, 3); + VerifyAndPushSpellCast(spells, SPELL_HAMMER_OF_WRATH, TARGET_VICTIM, 5); + VerifyAndPushSpellCast(spells, SPELL_RIGHTEOUS_FURY, TARGET_NONE, 2); + break; + } + break; + case CLASS_HUNTER: + VerifyAndPushSpellCast(spells, SPELL_DETERRENCE, TARGET_NONE, 3); + VerifyAndPushSpellCast(spells, SPELL_EXPLOSIVE_TRAP, TARGET_NONE, 1); + VerifyAndPushSpellCast(spells, SPELL_FREEZING_ARROW, TARGET_VICTIM, 2); + VerifyAndPushSpellCast(spells, SPELL_RAPID_FIRE, TARGET_NONE, 10); + VerifyAndPushSpellCast(spells, SPELL_KILL_SHOT, TARGET_VICTIM, 10); + if (me->GetVictim() && me->GetVictim()->getPowerType() == POWER_MANA && !me->GetVictim()->GetAuraApplicationOfRankedSpell(SPELL_VIPER_STING, me->GetGUID())) + VerifyAndPushSpellCast(spells, SPELL_VIPER_STING, TARGET_VICTIM, 5); + + switch (GetSpec()) + { + case SPEC_HUNTER_BEAST_MASTERY: + VerifyAndPushSpellCast(spells, SPELL_AIMED_SHOT, TARGET_VICTIM, 2); + VerifyAndPushSpellCast(spells, SPELL_ARCANE_SHOT, TARGET_VICTIM, 3); + VerifyAndPushSpellCast(spells, SPELL_STEADY_SHOT, TARGET_VICTIM, 2); + VerifyAndPushSpellCast(spells, SPELL_MULTI_SHOT, TARGET_VICTIM, 2); + break; + case SPEC_HUNTER_MARKSMANSHIP: + VerifyAndPushSpellCast(spells, SPELL_AIMED_SHOT, TARGET_VICTIM, 2); + VerifyAndPushSpellCast(spells, SPELL_CHIMERA_SHOT, TARGET_VICTIM, 5); + VerifyAndPushSpellCast(spells, SPELL_ARCANE_SHOT, TARGET_VICTIM, 3); + VerifyAndPushSpellCast(spells, SPELL_STEADY_SHOT, TARGET_VICTIM, 2); + VerifyAndPushSpellCast(spells, SPELL_READINESS, TARGET_NONE, 10); + VerifyAndPushSpellCast(spells, SPELL_SILENCING_SHOT, TARGET_VICTIM, 5); + break; + case SPEC_HUNTER_SURVIVAL: + VerifyAndPushSpellCast(spells, SPELL_EXPLOSIVE_SHOT, TARGET_VICTIM, 8); + VerifyAndPushSpellCast(spells, SPELL_BLACK_ARROW, TARGET_VICTIM, 5); + VerifyAndPushSpellCast(spells, SPELL_MULTI_SHOT, TARGET_VICTIM, 3); + VerifyAndPushSpellCast(spells, SPELL_STEADY_SHOT, TARGET_VICTIM, 1); + break; + } + break; + case CLASS_ROGUE: + { + VerifyAndPushSpellCast(spells, SPELL_DISMANTLE, TARGET_VICTIM, 8); + VerifyAndPushSpellCast(spells, SPELL_EVASION, TARGET_NONE, 8); + VerifyAndPushSpellCast(spells, SPELL_VANISH, TARGET_NONE, 4); + VerifyAndPushSpellCast(spells, SPELL_BLIND, TARGET_VICTIM, 2); + VerifyAndPushSpellCast(spells, SPELL_CLOAK_OF_SHADOWS, TARGET_NONE, 2); + + uint32 builder, finisher; + switch (GetSpec()) + { + case SPEC_ROGUE_ASSASSINATION: + builder = SPELL_MUTILATE, finisher = SPELL_ENVENOM; + VerifyAndPushSpellCast(spells, SPELL_COLD_BLOOD, TARGET_NONE, 20); + break; + case SPEC_ROGUE_COMBAT: + builder = SPELL_SINISTER_STRIKE, finisher = SPELL_EVISCERATE; + VerifyAndPushSpellCast(spells, SPELL_ADRENALINE_RUSH, TARGET_NONE, 6); + VerifyAndPushSpellCast(spells, SPELL_BLADE_FLURRY, TARGET_NONE, 5); + VerifyAndPushSpellCast(spells, SPELL_KILLING_SPREE, TARGET_NONE, 25); + break; + case SPEC_ROGUE_SUBLETY: + builder = SPELL_HEMORRHAGE, finisher = SPELL_EVISCERATE; + VerifyAndPushSpellCast(spells, SPELL_PREPARATION, TARGET_NONE, 10); + if (!me->IsWithinMeleeRange(me->GetVictim())) + VerifyAndPushSpellCast(spells, SPELL_SHADOWSTEP, TARGET_VICTIM, 25); + VerifyAndPushSpellCast(spells, SPELL_SHADOW_DANCE, TARGET_NONE, 10); + break; + } + + if (Unit* victim = me->GetVictim()) + { + if (victim->HasUnitState(UNIT_STATE_CASTING)) + VerifyAndPushSpellCast(spells, SPELL_KICK, TARGET_VICTIM, 25); + + uint8 const cp = (me->GetComboTarget() == victim->GetGUID()) ? me->GetComboPoints() : 0; + if (cp >= 4) + VerifyAndPushSpellCast(spells, finisher, TARGET_VICTIM, 10); + if (cp <= 4) + VerifyAndPushSpellCast(spells, builder, TARGET_VICTIM, 5); + } + break; + } + case CLASS_PRIEST: + VerifyAndPushSpellCast(spells, SPELL_FEAR_WARD, TARGET_SELF, 2); + VerifyAndPushSpellCast(spells, SPELL_POWER_WORD_FORT, TARGET_CHARMER, 1); + VerifyAndPushSpellCast(spells, SPELL_DIVINE_SPIRIT, TARGET_CHARMER, 1); + VerifyAndPushSpellCast(spells, SPELL_SHADOW_PROTECTION, TARGET_CHARMER, 2); + VerifyAndPushSpellCast(spells, SPELL_DIVINE_HYMN, TARGET_NONE, 5); + VerifyAndPushSpellCast(spells, SPELL_HYMN_OF_HOPE, TARGET_NONE, 5); + VerifyAndPushSpellCast(spells, SPELL_SHADOW_WORD_DEATH, TARGET_VICTIM, 1); + VerifyAndPushSpellCast(spells, SPELL_PSYCHIC_SCREAM, TARGET_VICTIM, 3); + switch (GetSpec()) + { + case SPEC_PRIEST_DISCIPLINE: + VerifyAndPushSpellCast(spells, SPELL_POWER_WORD_SHIELD, TARGET_CHARMER, 3); + VerifyAndPushSpellCast(spells, SPELL_INNER_FOCUS, TARGET_NONE, 3); + VerifyAndPushSpellCast(spells, SPELL_PAIN_SUPPRESSION, TARGET_CHARMER, 15); + VerifyAndPushSpellCast(spells, SPELL_POWER_INFUSION, TARGET_CHARMER, 10); + VerifyAndPushSpellCast(spells, SPELL_PENANCE, TARGET_CHARMER, 3); + VerifyAndPushSpellCast(spells, SPELL_FLASH_HEAL, TARGET_CHARMER, 1); + break; + case SPEC_PRIEST_HOLY: + VerifyAndPushSpellCast(spells, SPELL_DESPERATE_PRAYER, TARGET_NONE, 3); + VerifyAndPushSpellCast(spells, SPELL_GUARDIAN_SPIRIT, TARGET_CHARMER, 5); + VerifyAndPushSpellCast(spells, SPELL_FLASH_HEAL, TARGET_CHARMER, 1); + VerifyAndPushSpellCast(spells, SPELL_RENEW, TARGET_CHARMER, 3); + break; + case SPEC_PRIEST_SHADOW: + if (!me->HasAura(SPELL_SHADOWFORM)) + { + VerifyAndPushSpellCast(spells, SPELL_SHADOWFORM, TARGET_NONE, 100); + break; + } + if (Unit* victim = me->GetVictim()) + { + if (!victim->GetAuraApplicationOfRankedSpell(SPELL_VAMPIRIC_TOUCH, me->GetGUID())) + VerifyAndPushSpellCast(spells, SPELL_VAMPIRIC_TOUCH, TARGET_VICTIM, 4); + if (!victim->GetAuraApplicationOfRankedSpell(SPELL_SHADOW_WORD_PAIN, me->GetGUID())) + VerifyAndPushSpellCast(spells, SPELL_SHADOW_WORD_PAIN, TARGET_VICTIM, 3); + if (!victim->GetAuraApplicationOfRankedSpell(SPELL_DEVOURING_PLAGUE, me->GetGUID())) + VerifyAndPushSpellCast(spells, SPELL_DEVOURING_PLAGUE, TARGET_VICTIM, 4); + } + VerifyAndPushSpellCast(spells, SPELL_MIND_BLAST, TARGET_VICTIM, 3); + VerifyAndPushSpellCast(spells, SPELL_MIND_FLAY, TARGET_VICTIM, 2); + VerifyAndPushSpellCast(spells, SPELL_DISPERSION, TARGET_NONE, 10); + break; + } + break; + case CLASS_DEATH_KNIGHT: + { + if (!me->IsWithinMeleeRange(me->GetVictim())) + VerifyAndPushSpellCast(spells, SPELL_DEATH_GRIP, TARGET_VICTIM, 25); + VerifyAndPushSpellCast(spells, SPELL_STRANGULATE, TARGET_VICTIM, 15); + VerifyAndPushSpellCast(spells, SPELL_EMPOWER_RUNE_WEAP, TARGET_NONE, 5); + VerifyAndPushSpellCast(spells, SPELL_ICEBORN_FORTITUDE, TARGET_NONE, 15); + VerifyAndPushSpellCast(spells, SPELL_ANTI_MAGIC_SHELL, TARGET_NONE, 10); + + bool hasFF = false, hasBP = false; + if (Unit* victim = me->GetVictim()) + { + if (victim->HasUnitState(UNIT_STATE_CASTING)) + VerifyAndPushSpellCast(spells, SPELL_MIND_FREEZE, TARGET_VICTIM, 25); + + hasFF = !!victim->GetAuraApplicationOfRankedSpell(AURA_FROST_FEVER, me->GetGUID()), hasBP = !!victim->GetAuraApplicationOfRankedSpell(AURA_BLOOD_PLAGUE, me->GetGUID()); + if (hasFF && hasBP) + VerifyAndPushSpellCast(spells, SPELL_PESTILENCE, TARGET_VICTIM, 3); + if (!hasFF) + VerifyAndPushSpellCast(spells, SPELL_ICY_TOUCH, TARGET_VICTIM, 4); + if (!hasBP) + VerifyAndPushSpellCast(spells, SPELL_PLAGUE_STRIKE, TARGET_VICTIM, 4); + } + switch (GetSpec()) + { + case SPEC_DEATH_KNIGHT_BLOOD: + VerifyAndPushSpellCast(spells, SPELL_RUNE_TAP, TARGET_NONE, 2); + VerifyAndPushSpellCast(spells, SPELL_HYSTERIA, TARGET_SELF, 5); + if (Creature* creatureCharmer = ObjectAccessor::GetCreature(*me, me->GetCharmerGUID())) + if (!creatureCharmer->IsDungeonBoss() && !creatureCharmer->isWorldBoss()) + VerifyAndPushSpellCast(spells, SPELL_HYSTERIA, creatureCharmer, 15); + VerifyAndPushSpellCast(spells, SPELL_HEART_STRIKE, TARGET_VICTIM, 2); + if (hasFF && hasBP) + VerifyAndPushSpellCast(spells, SPELL_DEATH_STRIKE, TARGET_VICTIM, 8); + VerifyAndPushSpellCast(spells, SPELL_DEATH_COIL_DK, TARGET_VICTIM, 1); + VerifyAndPushSpellCast(spells, SPELL_MARK_OF_BLOOD, TARGET_VICTIM, 20); + VerifyAndPushSpellCast(spells, SPELL_VAMPIRIC_BLOOD, TARGET_NONE, 10); + break; + case SPEC_DEATH_KNIGHT_FROST: + if (hasFF && hasBP) + VerifyAndPushSpellCast(spells, SPELL_OBLITERATE, TARGET_VICTIM, 5); + VerifyAndPushSpellCast(spells, SPELL_HOWLING_BLAST, TARGET_VICTIM, 2); + VerifyAndPushSpellCast(spells, SPELL_UNBREAKABLE_ARMOR, TARGET_NONE, 10); + VerifyAndPushSpellCast(spells, SPELL_DEATHCHILL, TARGET_NONE, 10); + VerifyAndPushSpellCast(spells, SPELL_FROST_STRIKE, TARGET_VICTIM, 3); + VerifyAndPushSpellCast(spells, SPELL_BLOOD_STRIKE, TARGET_VICTIM, 1); + break; + case SPEC_DEATH_KNIGHT_UNHOLY: + if (hasFF && hasBP) + VerifyAndPushSpellCast(spells, SPELL_SCOURGE_STRIKE, TARGET_VICTIM, 5); + VerifyAndPushSpellCast(spells, SPELL_DEATH_AND_DECAY, TARGET_VICTIM, 2); + VerifyAndPushSpellCast(spells, SPELL_ANTI_MAGIC_ZONE, TARGET_NONE, 8); + VerifyAndPushSpellCast(spells, SPELL_SUMMON_GARGOYLE, TARGET_VICTIM, 7); + VerifyAndPushSpellCast(spells, SPELL_BLOOD_STRIKE, TARGET_VICTIM, 1); + VerifyAndPushSpellCast(spells, SPELL_DEATH_COIL_DK, TARGET_VICTIM, 3); + break; + } + break; + } + case CLASS_SHAMAN: + VerifyAndPushSpellCast(spells, SPELL_HEROISM, TARGET_NONE, 25); + VerifyAndPushSpellCast(spells, SPELL_BLOODLUST, TARGET_NONE, 25); + VerifyAndPushSpellCast(spells, SPELL_GROUNDING_TOTEM, TARGET_NONE, 2); + switch (GetSpec()) + { + case SPEC_SHAMAN_RESTORATION: + if (Unit* charmer = me->GetCharmer()) + if (!charmer->GetAuraApplicationOfRankedSpell(SPELL_EARTH_SHIELD, me->GetGUID())) + VerifyAndPushSpellCast(spells, SPELL_EARTH_SHIELD, charmer, 2); + if (me->HasAura(SPELL_SHA_NATURE_SWIFT)) + VerifyAndPushSpellCast(spells, SPELL_HEALING_WAVE, TARGET_CHARMER, 20); + else + VerifyAndPushSpellCast(spells, SPELL_LESSER_HEAL_WAVE, TARGET_CHARMER, 1); + VerifyAndPushSpellCast(spells, SPELL_TIDAL_FORCE, TARGET_NONE, 4); + VerifyAndPushSpellCast(spells, SPELL_SHA_NATURE_SWIFT, TARGET_NONE, 4); + VerifyAndPushSpellCast(spells, SPELL_MANA_TIDE_TOTEM, TARGET_NONE, 3); + break; + case SPEC_SHAMAN_ELEMENTAL: + if (Unit* victim = me->GetVictim()) + { + if (victim->GetAuraOfRankedSpell(SPELL_FLAME_SHOCK, GetGUID())) + VerifyAndPushSpellCast(spells, SPELL_LAVA_BURST, TARGET_VICTIM, 5); + else + VerifyAndPushSpellCast(spells, SPELL_FLAME_SHOCK, TARGET_VICTIM, 3); + } + VerifyAndPushSpellCast(spells, SPELL_CHAIN_LIGHTNING, TARGET_VICTIM, 2); + VerifyAndPushSpellCast(spells, SPELL_LIGHTNING_BOLT, TARGET_VICTIM, 1); + VerifyAndPushSpellCast(spells, SPELL_ELEMENTAL_MASTERY, TARGET_VICTIM, 5); + VerifyAndPushSpellCast(spells, SPELL_THUNDERSTORM, TARGET_NONE, 3); + break; + case SPEC_SHAMAN_ENHANCEMENT: + if (Aura const* maelstrom = me->GetAura(AURA_MAELSTROM_WEAPON)) + if (maelstrom->GetStackAmount() == 5) + VerifyAndPushSpellCast(spells, SPELL_LIGHTNING_BOLT, TARGET_VICTIM, 5); + VerifyAndPushSpellCast(spells, SPELL_STORMSTRIKE, TARGET_VICTIM, 3); + VerifyAndPushSpellCast(spells, SPELL_EARTH_SHOCK, TARGET_VICTIM, 2); + VerifyAndPushSpellCast(spells, SPELL_LAVA_LASH, TARGET_VICTIM, 1); + VerifyAndPushSpellCast(spells, SPELL_SHAMANISTIC_RAGE, TARGET_NONE, 10); + break; + } + break; + case CLASS_MAGE: + if (me->GetVictim() && me->GetVictim()->HasUnitState(UNIT_STATE_CASTING)) + VerifyAndPushSpellCast(spells, SPELL_COUNTERSPELL, TARGET_VICTIM, 25); + VerifyAndPushSpellCast(spells, SPELL_DAMPEN_MAGIC, TARGET_CHARMER, 2); + VerifyAndPushSpellCast(spells, SPELL_EVOCATION, TARGET_NONE, 3); + VerifyAndPushSpellCast(spells, SPELL_MANA_SHIELD, TARGET_NONE, 1); + VerifyAndPushSpellCast(spells, SPELL_MIRROR_IMAGE, TARGET_NONE, 3); + VerifyAndPushSpellCast(spells, SPELL_SPELLSTEAL, TARGET_VICTIM, 2); + VerifyAndPushSpellCast(spells, SPELL_ICE_BLOCK, TARGET_NONE, 1); + VerifyAndPushSpellCast(spells, SPELL_ICY_VEINS, TARGET_NONE, 3); + switch (GetSpec()) + { + case SPEC_MAGE_ARCANE: + if (Aura* abAura = me->GetAura(AURA_ARCANE_BLAST)) + if (abAura->GetStackAmount() >= 3) + VerifyAndPushSpellCast(spells, SPELL_ARCANE_MISSILES, TARGET_VICTIM, 7); + VerifyAndPushSpellCast(spells, SPELL_ARCANE_BLAST, TARGET_VICTIM, 5); + VerifyAndPushSpellCast(spells, SPELL_ARCANE_BARRAGE, TARGET_VICTIM, 1); + VerifyAndPushSpellCast(spells, SPELL_ARCANE_POWER, TARGET_NONE, 8); + VerifyAndPushSpellCast(spells, SPELL_PRESENCE_OF_MIND, TARGET_NONE, 7); + break; + case SPEC_MAGE_FIRE: + if (me->GetVictim() && !me->GetVictim()->GetAuraApplicationOfRankedSpell(SPELL_LIVING_BOMB)) + VerifyAndPushSpellCast(spells, SPELL_LIVING_BOMB, TARGET_VICTIM, 3); + VerifyAndPushSpellCast(spells, SPELL_COMBUSTION, TARGET_VICTIM, 3); + VerifyAndPushSpellCast(spells, SPELL_FIREBALL, TARGET_VICTIM, 2); + VerifyAndPushSpellCast(spells, SPELL_FIRE_BLAST, TARGET_VICTIM, 1); + VerifyAndPushSpellCast(spells, SPELL_DRAGONS_BREATH, TARGET_VICTIM, 2); + VerifyAndPushSpellCast(spells, SPELL_BLAST_WAVE, TARGET_VICTIM, 1); + break; + case SPEC_MAGE_FROST: + VerifyAndPushSpellCast(spells, SPELL_DEEP_FREEZE, TARGET_VICTIM, 10); + VerifyAndPushSpellCast(spells, SPELL_FROST_NOVA, TARGET_VICTIM, 3); + VerifyAndPushSpellCast(spells, SPELL_FROSTBOLT, TARGET_VICTIM, 3); + VerifyAndPushSpellCast(spells, SPELL_COLD_SNAP, TARGET_VICTIM, 5); + if (me->GetVictim() && me->GetVictim()->HasAuraState(AURA_STATE_FROZEN, nullptr, me)) + VerifyAndPushSpellCast(spells, SPELL_ICE_LANCE, TARGET_VICTIM, 5); + break; + } + break; + case CLASS_WARLOCK: + VerifyAndPushSpellCast(spells, SPELL_DEATH_COIL_W, TARGET_VICTIM, 2); + VerifyAndPushSpellCast(spells, SPELL_FEAR, TARGET_VICTIM, 2); + VerifyAndPushSpellCast(spells, SPELL_SEED_OF_CORRUPTION, TARGET_VICTIM, 4); + VerifyAndPushSpellCast(spells, SPELL_HOWL_OF_TERROR, TARGET_NONE, 2); + if (me->GetVictim() && !me->GetVictim()->GetAuraApplicationOfRankedSpell(SPELL_CORRUPTION, me->GetGUID())) + VerifyAndPushSpellCast(spells, SPELL_CORRUPTION, TARGET_VICTIM, 10); + switch (GetSpec()) + { + case SPEC_WARLOCK_AFFLICTION: + if (Unit* victim = me->GetVictim()) + { + VerifyAndPushSpellCast(spells, SPELL_SHADOW_BOLT, TARGET_VICTIM, 7); + if (!victim->GetAuraApplicationOfRankedSpell(SPELL_UNSTABLE_AFFLICTION, me->GetGUID())) + VerifyAndPushSpellCast(spells, SPELL_UNSTABLE_AFFLICTION, TARGET_VICTIM, 8); + if (!victim->GetAuraApplicationOfRankedSpell(SPELL_HAUNT, me->GetGUID())) + VerifyAndPushSpellCast(spells, SPELL_HAUNT, TARGET_VICTIM, 8); + if (!victim->GetAuraApplicationOfRankedSpell(SPELL_CURSE_OF_AGONY, me->GetGUID())) + VerifyAndPushSpellCast(spells, SPELL_CURSE_OF_AGONY, TARGET_VICTIM, 4); + if (victim->HealthBelowPct(25)) + VerifyAndPushSpellCast(spells, SPELL_DRAIN_SOUL, TARGET_VICTIM, 100); + } + break; + case SPEC_WARLOCK_DEMONOLOGY: + VerifyAndPushSpellCast(spells, SPELL_METAMORPHOSIS, TARGET_NONE, 15); + VerifyAndPushSpellCast(spells, SPELL_SHADOW_BOLT, TARGET_VICTIM, 7); + if (me->HasAura(AURA_DECIMATION)) + VerifyAndPushSpellCast(spells, SPELL_SOUL_FIRE, TARGET_VICTIM, 100); + if (me->HasAura(SPELL_METAMORPHOSIS)) + { + VerifyAndPushSpellCast(spells, SPELL_IMMOLATION_AURA, TARGET_NONE, 30); + if (!me->IsWithinMeleeRange(me->GetVictim())) + VerifyAndPushSpellCast(spells, SPELL_DEMON_CHARGE, TARGET_VICTIM, 20); + } + if (me->GetVictim() && !me->GetVictim()->GetAuraApplicationOfRankedSpell(SPELL_IMMOLATE, me->GetGUID())) + VerifyAndPushSpellCast(spells, SPELL_IMMOLATE, TARGET_VICTIM, 5); + if (me->HasAura(AURA_MOLTEN_CORE)) + VerifyAndPushSpellCast(spells, SPELL_INCINERATE, TARGET_VICTIM, 10); + break; + case SPEC_WARLOCK_DESTRUCTION: + if (me->GetVictim() && !me->GetVictim()->GetAuraApplicationOfRankedSpell(SPELL_IMMOLATE, me->GetGUID())) + VerifyAndPushSpellCast(spells, SPELL_IMMOLATE, TARGET_VICTIM, 8); + if (me->GetVictim() && me->GetVictim()->GetAuraApplicationOfRankedSpell(SPELL_IMMOLATE, me->GetGUID())) + VerifyAndPushSpellCast(spells, SPELL_CONFLAGRATE, TARGET_VICTIM, 8); + VerifyAndPushSpellCast(spells, SPELL_SHADOWFURY, TARGET_VICTIM, 5); + VerifyAndPushSpellCast(spells, SPELL_CHAOS_BOLT, TARGET_VICTIM, 10); + VerifyAndPushSpellCast(spells, SPELL_SHADOWBURN, TARGET_VICTIM, 3); + VerifyAndPushSpellCast(spells, SPELL_INCINERATE, TARGET_VICTIM, 7); + break; + } + break; + case CLASS_DRUID: + VerifyAndPushSpellCast(spells, SPELL_INNERVATE, TARGET_CHARMER, 5); + VerifyAndPushSpellCast(spells, SPELL_BARKSKIN, TARGET_NONE, 5); + switch (GetSpec()) + { + case SPEC_DRUID_RESTORATION: + if (!me->HasAura(SPELL_TREE_OF_LIFE)) + { + CancelAllShapeshifts(); + VerifyAndPushSpellCast(spells, SPELL_TREE_OF_LIFE, TARGET_NONE, 100); + break; + } + VerifyAndPushSpellCast(spells, SPELL_TRANQUILITY, TARGET_NONE, 10); + VerifyAndPushSpellCast(spells, SPELL_NATURE_SWIFTNESS, TARGET_NONE, 7); + if (Creature* creatureCharmer = ObjectAccessor::GetCreature(*me, me->GetCharmerGUID())) + { + VerifyAndPushSpellCast(spells, SPELL_NOURISH, creatureCharmer, 5); + VerifyAndPushSpellCast(spells, SPELL_WILD_GROWTH, creatureCharmer, 5); + if (!creatureCharmer->GetAuraApplicationOfRankedSpell(SPELL_REJUVENATION, me->GetGUID())) + VerifyAndPushSpellCast(spells, SPELL_REJUVENATION, creatureCharmer, 8); + if (!creatureCharmer->GetAuraApplicationOfRankedSpell(SPELL_REGROWTH, me->GetGUID())) + VerifyAndPushSpellCast(spells, SPELL_REGROWTH, creatureCharmer, 8); + uint8 lifebloomStacks = 0; + if (Aura const* lifebloom = creatureCharmer->GetAura(SPELL_LIFEBLOOM, me->GetGUID())) + lifebloomStacks = lifebloom->GetStackAmount(); + if (lifebloomStacks < 3) + VerifyAndPushSpellCast(spells, SPELL_LIFEBLOOM, creatureCharmer, 5); + if (creatureCharmer->GetAuraApplicationOfRankedSpell(SPELL_REJUVENATION) || + creatureCharmer->GetAuraApplicationOfRankedSpell(SPELL_REGROWTH)) + VerifyAndPushSpellCast(spells, SPELL_SWIFTMEND, creatureCharmer, 10); + if (me->HasAura(SPELL_NATURE_SWIFTNESS)) + VerifyAndPushSpellCast(spells, SPELL_HEALING_TOUCH, creatureCharmer, 100); + } + break; + case SPEC_DRUID_BALANCE: + { + if (!me->HasAura(SPELL_MOONKIN_FORM)) + { + CancelAllShapeshifts(); + VerifyAndPushSpellCast(spells, SPELL_MOONKIN_FORM, TARGET_NONE, 100); + break; + } + uint32 const mainAttackSpell = me->HasAura(AURA_ECLIPSE_LUNAR) ? SPELL_STARFIRE : SPELL_WRATH; + VerifyAndPushSpellCast(spells, SPELL_STARFALL, TARGET_NONE, 20); + VerifyAndPushSpellCast(spells, mainAttackSpell, TARGET_VICTIM, 10); + if (me->GetVictim() && !me->GetVictim()->GetAuraApplicationOfRankedSpell(SPELL_INSECT_SWARM, me->GetGUID())) + VerifyAndPushSpellCast(spells, SPELL_INSECT_SWARM, TARGET_VICTIM, 7); + if (me->GetVictim() && !me->GetVictim()->GetAuraApplicationOfRankedSpell(SPELL_MOONFIRE, me->GetGUID())) + VerifyAndPushSpellCast(spells, SPELL_MOONFIRE, TARGET_VICTIM, 5); + if (me->GetVictim() && me->GetVictim()->HasUnitState(UNIT_STATE_CASTING)) + VerifyAndPushSpellCast(spells, SPELL_TYPHOON, TARGET_NONE, 15); + break; + } + case SPEC_DRUID_FERAL: + if (!me->HasAura(SPELL_CAT_FORM)) + { + CancelAllShapeshifts(); + VerifyAndPushSpellCast(spells, SPELL_CAT_FORM, TARGET_NONE, 100); + break; + } + VerifyAndPushSpellCast(spells, SPELL_BERSERK, TARGET_NONE, 20); + VerifyAndPushSpellCast(spells, SPELL_SURVIVAL_INSTINCTS, TARGET_NONE, 15); + VerifyAndPushSpellCast(spells, SPELL_TIGER_FURY, TARGET_NONE, 15); + VerifyAndPushSpellCast(spells, SPELL_DASH, TARGET_NONE, 5); + if (Unit* victim = me->GetVictim()) + { + uint8 const cp = (me->GetComboTarget() == victim->GetGUID()) ? me->GetComboPoints() : 0; + if (victim->HasUnitState(UNIT_STATE_CASTING) && cp >= 1) + VerifyAndPushSpellCast(spells, SPELL_MAIM, TARGET_VICTIM, 25); + if (!me->IsWithinMeleeRange(victim)) + VerifyAndPushSpellCast(spells, SPELL_FERAL_CHARGE_CAT, TARGET_VICTIM, 25); + if (cp >= 4) + VerifyAndPushSpellCast(spells, SPELL_RIP, TARGET_VICTIM, 50); + if (cp <= 4) + { + VerifyAndPushSpellCast(spells, SPELL_MANGLE_CAT, TARGET_VICTIM, 10); + VerifyAndPushSpellCast(spells, SPELL_CLAW, TARGET_VICTIM, 5); + if (!victim->GetAuraApplicationOfRankedSpell(SPELL_RAKE, me->GetGUID())) + VerifyAndPushSpellCast(spells, SPELL_RAKE, TARGET_VICTIM, 8); + if (!me->HasAura(SPELL_SAVAGE_ROAR)) + VerifyAndPushSpellCast(spells, SPELL_SAVAGE_ROAR, TARGET_NONE, 15); + } + } + break; + } + break; + } + + return SelectSpellCast(spells); +} + +static const float CASTER_CHASE_DISTANCE = 28.0f; +void SimpleCharmedPlayerAI::UpdateAI(const uint32 diff) { Creature* charmer = me->GetCharmer() ? me->GetCharmer()->ToCreature() : nullptr; if (!charmer) @@ -177,7 +1271,7 @@ void SimpleCharmedPlayerAI::UpdateAI(const uint32 /*diff*/) for (Player::AuraEffectList::const_iterator iter = auras.begin(); iter != auras.end(); ++iter) if ((*iter)->GetCasterGUID() == charmer->GetGUID() && (*iter)->GetBase()->IsPermanent()) { - me->Kill(me); + me->KillSelf(); return; } } @@ -192,10 +1286,54 @@ void SimpleCharmedPlayerAI::UpdateAI(const uint32 /*diff*/) return; if (IsRangedAttacker()) - AttackStartCaster(target, 28.0f); + { + _chaseCloser = !me->IsWithinLOSInMap(target); + if (_chaseCloser) + AttackStart(target); + else + AttackStartCaster(target, CASTER_CHASE_DISTANCE); + } else AttackStart(target); + _forceFacing = true; } + + if (me->IsStopped() && !me->HasUnitState(UNIT_STATE_CANNOT_TURN)) + { + float targetAngle = me->GetAngle(target); + if (_forceFacing || fabs(me->GetOrientation() - targetAngle) > 0.4f) + { + me->SetFacingTo(targetAngle); + _forceFacing = false; + } + } + + if (_castCheckTimer <= diff) + { + if (me->HasUnitState(UNIT_STATE_CASTING)) + _castCheckTimer = 0; + else + { + if (IsRangedAttacker()) + { // chase to zero if the target isn't in line of sight + bool inLOS = me->IsWithinLOSInMap(target); + if (_chaseCloser != !inLOS) + { + _chaseCloser = !inLOS; + if (_chaseCloser) + AttackStart(target); + else + AttackStartCaster(target, CASTER_CHASE_DISTANCE); + } + } + if (TargetedSpell shouldCast = SelectAppropriateCastForSpec()) + DoCastAtTarget(shouldCast); + _castCheckTimer = 500; + } + } + else + _castCheckTimer -= diff; + DoAutoAttackIfReady(); } else @@ -214,6 +1352,9 @@ void SimpleCharmedPlayerAI::OnCharmed(bool apply) { me->CastStop(); me->AttackStop(); + me->StopMoving(); + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MovePoint(0, me->GetPosition(), false); // force re-sync of current position for all clients } else { diff --git a/src/server/game/AI/PlayerAI/PlayerAI.h b/src/server/game/AI/PlayerAI/PlayerAI.h index b717816f9a3..18f65485161 100644 --- a/src/server/game/AI/PlayerAI/PlayerAI.h +++ b/src/server/game/AI/PlayerAI/PlayerAI.h @@ -20,41 +20,99 @@ #include "UnitAI.h" #include "Player.h" +#include "Spell.h" #include "Creature.h" class TC_GAME_API PlayerAI : public UnitAI { public: - explicit PlayerAI(Player* player) : UnitAI(static_cast<Unit*>(player)), me(player), _isSelfHealer(PlayerAI::IsPlayerHealer(player)), _isSelfRangedAttacker(PlayerAI::IsPlayerRangedAttacker(player)) { } + explicit PlayerAI(Player* player) : UnitAI(static_cast<Unit*>(player)), me(player), _selfSpec(PlayerAI::GetPlayerSpec(player)), _isSelfHealer(PlayerAI::IsPlayerHealer(player)), _isSelfRangedAttacker(PlayerAI::IsPlayerRangedAttacker(player)) { } void OnCharmed(bool /*apply*/) override { } // charm AI application for players is handled by Unit::SetCharmedBy / Unit::RemoveCharmedBy // helper functions to determine player info + // Return values range from 0 (left-most spec) to 2 (right-most spec). If two specs have the same number of talent points, the left-most of those specs is returned. + static uint8 GetPlayerSpec(Player const* who); + // Return values range from 0 (left-most spec) to 2 (right-most spec). If two specs have the same number of talent points, the left-most of those specs is returned. + uint8 GetSpec(Player const* who = nullptr) const { return (!who || who == me) ? _selfSpec : GetPlayerSpec(who); } static bool IsPlayerHealer(Player const* who); bool IsHealer(Player const* who = nullptr) const { return (!who || who == me) ? _isSelfHealer : IsPlayerHealer(who); } static bool IsPlayerRangedAttacker(Player const* who); bool IsRangedAttacker(Player const* who = nullptr) const { return (!who || who == me) ? _isSelfRangedAttacker : IsPlayerRangedAttacker(who); } protected: + struct TargetedSpell : public std::pair<Spell*, Unit*> + { + TargetedSpell() : pair<Spell*, Unit*>() { } + TargetedSpell(Spell* first, Unit* second) : pair<Spell*, Unit*>(first, second) { } + explicit operator bool() { return !!first; } + }; + typedef std::pair<TargetedSpell, uint32> PossibleSpell; + typedef std::vector<PossibleSpell> PossibleSpellVector; + Player* const me; void SetIsRangedAttacker(bool state) { _isSelfRangedAttacker = state; } // this allows overriding of the default ranged attacker detection + enum SpellTarget + { + TARGET_NONE, + TARGET_VICTIM, + TARGET_CHARMER, + TARGET_SELF + }; + /* Check if the specified spell can be cast on that target. + Caller is responsible for cleaning up created Spell object from pointer. */ + TargetedSpell VerifySpellCast(uint32 spellId, Unit* target); + /* Check if the specified spell can be cast on that target. + Caller is responsible for cleaning up created Spell object from pointer. */ + TargetedSpell VerifySpellCast(uint32 spellId, SpellTarget target); + + /* Helper method - checks spell cast, then pushes it onto provided vector if valid. */ + template<typename T> inline void VerifyAndPushSpellCast(PossibleSpellVector& spells, uint32 spellId, T target, uint32 weight) + { + if (TargetedSpell spell = VerifySpellCast(spellId, target)) + spells.push_back({ spell,weight }); + } + + /* Helper method - selects one spell from the vector and returns it, while deleting everything else. + This invalidates the vector, and empties it to prevent accidental misuse. */ + TargetedSpell SelectSpellCast(PossibleSpellVector& spells); + /* Helper method - casts the included spell at the included target */ + inline void DoCastAtTarget(TargetedSpell spell) + { + SpellCastTargets targets; + targets.SetUnitTarget(spell.second); + spell.first->prepare(&targets); + } + virtual Unit* SelectAttackTarget() const { return me->GetCharmer() ? me->GetCharmer()->GetVictim() : nullptr; } void DoRangedAttackIfReady(); void DoAutoAttackIfReady(); + // Cancels all shapeshifts that the player could voluntarily cancel + void CancelAllShapeshifts(); + private: - bool _isSelfHealer; + uint8 const _selfSpec; + bool const _isSelfHealer; bool _isSelfRangedAttacker; }; class SimpleCharmedPlayerAI : public PlayerAI { public: - SimpleCharmedPlayerAI(Player* player) : PlayerAI(player) { } + SimpleCharmedPlayerAI(Player* player) : PlayerAI(player), _castCheckTimer(500), _chaseCloser(false), _forceFacing(true) { } void UpdateAI(uint32 diff) override; void OnCharmed(bool apply) override; + + protected: Unit* SelectAttackTarget() const override; + + private: + TargetedSpell SelectAppropriateCastForSpec(); + uint32 _castCheckTimer; + bool _chaseCloser; + bool _forceFacing; }; #endif diff --git a/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp b/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp index 6f04a852b61..6475cc8117e 100644 --- a/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp +++ b/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp @@ -32,7 +32,7 @@ struct TSpellSummary uint8 Effects; // set of enum SelectEffect } extern* SpellSummary; -void SummonList::DoZoneInCombat(uint32 entry) +void SummonList::DoZoneInCombat(uint32 entry, float maxRangeToNearestTarget) { for (StorageType::iterator i = storage_.begin(); i != storage_.end();) { @@ -41,7 +41,7 @@ void SummonList::DoZoneInCombat(uint32 entry) if (summon && summon->IsAIEnabled && (!entry || summon->GetEntry() == entry)) { - summon->AI()->DoZoneInCombat(); + summon->AI()->DoZoneInCombat(nullptr, maxRangeToNearestTarget); } } } @@ -183,22 +183,22 @@ SpellInfo const* ScriptedAI::SelectSpell(Unit* target, uint32 school, uint32 mec { //No target so we can't cast if (!target) - return NULL; + return nullptr; //Silenced so we can't cast if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED)) - return NULL; + return nullptr; //Using the extended script system we first create a list of viable spells - SpellInfo const* apSpell[CREATURE_MAX_SPELLS]; - memset(apSpell, 0, CREATURE_MAX_SPELLS * sizeof(SpellInfo*)); + SpellInfo const* apSpell[MAX_CREATURE_SPELLS]; + memset(apSpell, 0, MAX_CREATURE_SPELLS * sizeof(SpellInfo*)); uint32 spellCount = 0; - SpellInfo const* tempSpell = NULL; + SpellInfo const* tempSpell = nullptr; //Check if each spell is viable(set it to null if not) - for (uint32 i = 0; i < CREATURE_MAX_SPELLS; i++) + for (uint32 i = 0; i < MAX_CREATURE_SPELLS; i++) { tempSpell = sSpellMgr->GetSpellInfo(me->m_spells[i]); @@ -251,7 +251,7 @@ SpellInfo const* ScriptedAI::SelectSpell(Unit* target, uint32 school, uint32 mec //We got our usable spells so now lets randomly pick one if (!spellCount) - return NULL; + return nullptr; return apSpell[urand(0, spellCount - 1)]; } @@ -327,7 +327,7 @@ void ScriptedAI::DoTeleportAll(float x, float y, float z, float o) Unit* ScriptedAI::DoSelectLowestHpFriendly(float range, uint32 minHPDiff) { - Unit* unit = NULL; + Unit* unit = nullptr; Trinity::MostHPMissingInRange u_check(me, range, minHPDiff); Trinity::UnitLastSearcher<Trinity::MostHPMissingInRange> searcher(me, unit, u_check); me->VisitNearbyObject(range, searcher); @@ -357,7 +357,7 @@ std::list<Creature*> ScriptedAI::DoFindFriendlyMissingBuff(float range, uint32 u Player* ScriptedAI::GetPlayerAtMinimumRange(float minimumRange) { - Player* player = NULL; + Player* player = nullptr; CellCoord pair(Trinity::ComputeCellCoord(me->GetPositionX(), me->GetPositionY())); Cell cell(pair); @@ -547,7 +547,7 @@ void BossAI::UpdateAI(uint32 diff) DoMeleeAttackIfReady(); } -void BossAI::_DespawnAtEvade(uint32 delayToRespawn) +void BossAI::_DespawnAtEvade(uint32 delayToRespawn, Creature* who) { if (delayToRespawn < 2) { @@ -555,18 +555,28 @@ void BossAI::_DespawnAtEvade(uint32 delayToRespawn) delayToRespawn = 2; } - uint32 corpseDelay = me->GetCorpseDelay(); - uint32 respawnDelay = me->GetRespawnDelay(); + if (!who) + who = me; - me->SetCorpseDelay(1); - me->SetRespawnDelay(delayToRespawn - 1); + if (TempSummon* whoSummon = who->ToTempSummon()) + { + TC_LOG_WARN("scripts", "_DespawnAtEvade called on a temporary summon."); + whoSummon->UnSummon(); + return; + } - me->DespawnOrUnsummon(); + uint32 corpseDelay = who->GetCorpseDelay(); + uint32 respawnDelay = who->GetRespawnDelay(); - me->SetCorpseDelay(corpseDelay); - me->SetRespawnDelay(respawnDelay); + who->SetCorpseDelay(1); + who->SetRespawnDelay(delayToRespawn - 1); - if (instance) + who->DespawnOrUnsummon(); + + who->SetCorpseDelay(corpseDelay); + who->SetRespawnDelay(respawnDelay); + + if (instance && who == me) instance->SetBossState(_bossId, FAIL); } @@ -628,27 +638,27 @@ void WorldBossAI::UpdateAI(uint32 diff) } // SD2 grid searchers. -TC_GAME_API Creature* GetClosestCreatureWithEntry(WorldObject* source, uint32 entry, float maxSearchRange, bool alive /*= true*/) +Creature* GetClosestCreatureWithEntry(WorldObject* source, uint32 entry, float maxSearchRange, bool alive /*= true*/) { return source->FindNearestCreature(entry, maxSearchRange, alive); } -TC_GAME_API GameObject* GetClosestGameObjectWithEntry(WorldObject* source, uint32 entry, float maxSearchRange) +GameObject* GetClosestGameObjectWithEntry(WorldObject* source, uint32 entry, float maxSearchRange) { return source->FindNearestGameObject(entry, maxSearchRange); } -TC_GAME_API void GetCreatureListWithEntryInGrid(std::list<Creature*>& list, WorldObject* source, uint32 entry, float maxSearchRange) +void GetCreatureListWithEntryInGrid(std::list<Creature*>& list, WorldObject* source, uint32 entry, float maxSearchRange) { source->GetCreatureListWithEntryInGrid(list, entry, maxSearchRange); } -TC_GAME_API void GetGameObjectListWithEntryInGrid(std::list<GameObject*>& list, WorldObject* source, uint32 entry, float maxSearchRange) +void GetGameObjectListWithEntryInGrid(std::list<GameObject*>& list, WorldObject* source, uint32 entry, float maxSearchRange) { source->GetGameObjectListWithEntryInGrid(list, entry, maxSearchRange); } -TC_GAME_API void GetPlayerListInGrid(std::list<Player*>& list, WorldObject* source, float maxSearchRange) +void GetPlayerListInGrid(std::list<Player*>& list, WorldObject* source, float maxSearchRange) { source->GetPlayerListInGrid(list, maxSearchRange); } diff --git a/src/server/game/AI/ScriptedAI/ScriptedCreature.h b/src/server/game/AI/ScriptedAI/ScriptedCreature.h index 42befa26a23..6144a4e5203 100644 --- a/src/server/game/AI/ScriptedAI/ScriptedCreature.h +++ b/src/server/game/AI/ScriptedAI/ScriptedCreature.h @@ -114,7 +114,7 @@ public: } } - void DoZoneInCombat(uint32 entry = 0); + void DoZoneInCombat(uint32 entry = 0, float maxRangeToNearestTarget = 250.0f); void RemoveNotExisting(); bool HasEntry(uint32 entry) const; @@ -367,7 +367,7 @@ class TC_GAME_API BossAI : public ScriptedAI void _EnterCombat(); void _JustDied(); void _JustReachedHome() { me->setActive(false); } - void _DespawnAtEvade(uint32 delayToRespawn = 30); + void _DespawnAtEvade(uint32 delayToRespawn = 30, Creature* who = nullptr); void TeleportCheaters(); diff --git a/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp b/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp index fa80634e0f0..1b8b472b805 100644 --- a/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp +++ b/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp @@ -72,7 +72,7 @@ bool npc_escortAI::AssistPlayerInCombat(Unit* who) return false; //experimental (unknown) flag not present - if (!(me->GetCreatureTemplate()->type_flags & CREATURE_TYPEFLAGS_AID_PLAYERS)) + if (!(me->GetCreatureTemplate()->type_flags & CREATURE_TYPE_FLAG_CAN_ASSIST)) return false; //not a player diff --git a/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp b/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp index 778edf8cab5..bd07e688fb0 100644 --- a/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp +++ b/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp @@ -69,7 +69,7 @@ bool FollowerAI::AssistPlayerInCombat(Unit* who) return false; //experimental (unknown) flag not present - if (!(me->GetCreatureTemplate()->type_flags & CREATURE_TYPEFLAGS_AID_PLAYERS)) + if (!(me->GetCreatureTemplate()->type_flags & CREATURE_TYPE_FLAG_CAN_ASSIST)) return false; //not a player diff --git a/src/server/game/AI/SmartScripts/SmartAI.cpp b/src/server/game/AI/SmartScripts/SmartAI.cpp index 361bb1a5b1d..e21f59fe582 100644 --- a/src/server/game/AI/SmartScripts/SmartAI.cpp +++ b/src/server/game/AI/SmartScripts/SmartAI.cpp @@ -413,15 +413,10 @@ void SmartAI::EnterEvadeMode(EvadeReason /*why*/) if (!me->IsAlive() || me->IsInEvadeMode()) return; - me->RemoveAllAurasExceptType(SPELL_AURA_CONTROL_VEHICLE, SPELL_AURA_CLONE_CASTER); + me->RemoveAurasOnEvade(); me->AddUnitState(UNIT_STATE_EVADE); - me->DeleteThreatList(); - me->CombatStop(true); - me->LoadCreaturesAddon(); - me->SetLootRecipient(NULL); - me->ResetPlayerDamageReq(); - me->SetLastDamagedTime(0); + _EnterEvadeMode(); GetScript()->ProcessEventsFor(SMART_EVENT_EVADE);//must be after aura clear so we can cast spells from db @@ -473,7 +468,7 @@ bool SmartAI::AssistPlayerInCombat(Unit* who) return false; //experimental (unknown) flag not present - if (!(me->GetCreatureTemplate()->type_flags & CREATURE_TYPEFLAGS_AID_PLAYERS)) + if (!(me->GetCreatureTemplate()->type_flags & CREATURE_TYPE_FLAG_CAN_ASSIST)) return false; //not a player @@ -653,8 +648,8 @@ void SmartAI::OnCharmed(bool apply) { GetScript()->ProcessEventsFor(SMART_EVENT_CHARMED, NULL, 0, 0, apply); - if (!apply && !me->IsInEvadeMode() && me->GetCharmerGUID()) - if (Unit* charmer = ObjectAccessor::GetUnit(*me, me->GetCharmerGUID())) + if (!apply && !me->IsInEvadeMode()) + if (Unit* charmer = me->GetCharmer()) AttackStart(charmer); } diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp index 9db36c76bb4..7c258e09b09 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.cpp +++ b/src/server/game/AI/SmartScripts/SmartScript.cpp @@ -1037,10 +1037,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u target->DespawnOrUnsummon(e.action.forceDespawn.delay); } else if (GameObject* goTarget = (*itr)->ToGameObject()) - { - if (IsSmartGO(goTarget)) - goTarget->SetRespawnTime(e.action.forceDespawn.delay + 1); - } + goTarget->SetRespawnTime(e.action.forceDespawn.delay + 1); } delete targets; @@ -3239,29 +3236,28 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui if (!me) return; - WorldObject* creature = NULL; + Creature* creature = nullptr; if (e.event.distance.guid != 0) { creature = FindCreatureNear(me, e.event.distance.guid); - if (!creature) return; - if (!me->IsInRange(creature, 0, (float)e.event.distance.dist)) + if (!me->IsInRange(creature, 0, static_cast<float>(e.event.distance.dist))) return; } else if (e.event.distance.entry != 0) { std::list<Creature*> list; - me->GetCreatureListWithEntryInGrid(list, e.event.distance.entry, (float)e.event.distance.dist); + me->GetCreatureListWithEntryInGrid(list, e.event.distance.entry, static_cast<float>(e.event.distance.dist)); if (!list.empty()) creature = list.front(); } if (creature) - ProcessTimedAction(e, e.event.distance.repeat, e.event.distance.repeat); + ProcessTimedAction(e, e.event.distance.repeat, e.event.distance.repeat, creature); break; } @@ -3270,29 +3266,28 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui if (!me) return; - WorldObject* gameobject = NULL; + GameObject* gameobject = nullptr; if (e.event.distance.guid != 0) { gameobject = FindGameObjectNear(me, e.event.distance.guid); - if (!gameobject) return; - if (!me->IsInRange(gameobject, 0, (float)e.event.distance.dist)) + if (!me->IsInRange(gameobject, 0, static_cast<float>(e.event.distance.dist))) return; } else if (e.event.distance.entry != 0) { std::list<GameObject*> list; - me->GetGameObjectListWithEntryInGrid(list, e.event.distance.entry, (float)e.event.distance.dist); + me->GetGameObjectListWithEntryInGrid(list, e.event.distance.entry, static_cast<float>(e.event.distance.dist)); if (!list.empty()) gameobject = list.front(); } if (gameobject) - ProcessTimedAction(e, e.event.distance.repeat, e.event.distance.repeat); + ProcessTimedAction(e, e.event.distance.repeat, e.event.distance.repeat, nullptr, 0, 0, false, nullptr, gameobject); break; } diff --git a/src/server/game/Accounts/RBAC.h b/src/server/game/Accounts/RBAC.h index 5f883175157..d1d418b0931 100644 --- a/src/server/game/Accounts/RBAC.h +++ b/src/server/game/Accounts/RBAC.h @@ -540,7 +540,7 @@ enum RBACPermissions RBAC_PERM_COMMAND_RELOAD_DISENCHANT_LOOT_TEMPLATE = 642, RBAC_PERM_COMMAND_RELOAD_EVENT_SCRIPTS = 643, RBAC_PERM_COMMAND_RELOAD_FISHING_LOOT_TEMPLATE = 644, - RBAC_PERM_COMMAND_RELOAD_GAME_GRAVEYARD_ZONE = 645, + RBAC_PERM_COMMAND_RELOAD_GRAVEYARD_ZONE = 645, RBAC_PERM_COMMAND_RELOAD_GAME_TELE = 646, RBAC_PERM_COMMAND_RELOAD_GAMEOBJECT_QUESTENDER = 647, RBAC_PERM_COMMAND_RELOAD_GAMEOBJECT_QUEST_LOOT_TEMPLATE = 648, @@ -697,6 +697,10 @@ enum RBACPermissions // 799 - 834 6.x only RBAC_PERM_COMMAND_DEBUG_LOADCELLS = 835, RBAC_PERM_COMMAND_DEBUG_BOUNDARY = 836, + RBAC_PERM_COMMAND_NPC_EVADE = 837, + RBAC_PERM_COMMAND_PET_LEVEL = 838, + RBAC_PERM_COMMAND_SERVER_SHUTDOWN_FORCE = 839, + RBAC_PERM_COMMAND_SERVER_RESTART_FORCE = 840, // custom permissions 1000+ RBAC_PERM_MAX diff --git a/src/server/game/Achievements/AchievementMgr.cpp b/src/server/game/Achievements/AchievementMgr.cpp index 87f5ff6ce5c..11c2635da33 100644 --- a/src/server/game/Achievements/AchievementMgr.cpp +++ b/src/server/game/Achievements/AchievementMgr.cpp @@ -646,13 +646,20 @@ void AchievementMgr::SendAchievementEarned(AchievementEntry const* achievement) if (achievement->flags & (ACHIEVEMENT_FLAG_REALM_FIRST_KILL | ACHIEVEMENT_FLAG_REALM_FIRST_REACH)) { + uint32 team = GetPlayer()->GetTeam(); + // broadcast realm first reached WorldPacket data(SMSG_SERVER_FIRST_ACHIEVEMENT, GetPlayer()->GetName().size() + 1 + 8 + 4 + 4); data << GetPlayer()->GetName(); data << uint64(GetPlayer()->GetGUID()); data << uint32(achievement->ID); - data << uint32(0); // 1=link supplied string as player name, 0=display plain string - sWorld->SendGlobalMessage(&data); + + std::size_t linkTypePos = data.wpos(); + data << uint32(1); // display name as clickable link in chat + sWorld->SendGlobalMessage(&data, nullptr, team); + + data.put<uint32>(linkTypePos, 0); // display name as plain string in chat + sWorld->SendGlobalMessage(&data, nullptr, team == ALLIANCE ? HORDE : ALLIANCE); } // if player is in world he can tell his friends about new achievement else if (GetPlayer()->IsInWorld()) diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp index 52e0deaf86f..8c144cbc8be 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp @@ -142,8 +142,8 @@ void BattlegroundIC::PostUpdateImpl(uint32 diff) { if (siege->IsAlive()) { - if (siege->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_UNK_14|UNIT_FLAG_IMMUNE_TO_PC)) - // following sniffs the vehicle always has UNIT_FLAG_UNK_14 + if (siege->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_CANNOT_SWIM|UNIT_FLAG_IMMUNE_TO_PC)) + // following sniffs the vehicle always has UNIT_FLAG_CANNOT_SWIM siege->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_IMMUNE_TO_PC); else siege->SetHealth(siege->GetMaxHealth()); @@ -762,7 +762,7 @@ void BattlegroundIC::HandleCapturedNodes(ICNodePoint* node, bool recapture) if (Creature* siegeEngine = GetBGCreature(siegeType)) { - siegeEngine->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_UNK_14|UNIT_FLAG_IMMUNE_TO_PC); + siegeEngine->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_CANNOT_SWIM|UNIT_FLAG_IMMUNE_TO_PC); siegeEngine->setFaction(BG_IC_Factions[(node->faction == TEAM_ALLIANCE ? 0 : 1)]); } } diff --git a/src/server/game/Conditions/ConditionMgr.cpp b/src/server/game/Conditions/ConditionMgr.cpp index afb6255079b..74e94135b86 100644 --- a/src/server/game/Conditions/ConditionMgr.cpp +++ b/src/server/game/Conditions/ConditionMgr.cpp @@ -738,7 +738,7 @@ bool ConditionMgr::IsObjectMeetToConditionList(ConditionSourceInfo& sourceInfo, //! If not found, add an entry in the store and set to true (placeholder) if (itr == elseGroupStore.end()) elseGroupStore[condition->ElseGroup] = true; - else if (!(*itr).second) + else if (!(*itr).second) //! If another condition in this group was unmatched before this, don't bother checking (the group is false anyway) continue; if (condition->ReferenceId)//handle reference diff --git a/src/server/game/DataStores/DBCEnums.h b/src/server/game/DataStores/DBCEnums.h index f0ea5b4a5f1..cb2f26e567f 100644 --- a/src/server/game/DataStores/DBCEnums.h +++ b/src/server/game/DataStores/DBCEnums.h @@ -19,6 +19,22 @@ #ifndef DBCENUMS_H #define DBCENUMS_H +#pragma pack(push, 1) + +struct DBCPosition2D +{ + float X; + float Y; +}; + +struct DBCPosition3D +{ + float X; + float Y; + float Z; +}; + +#pragma pack(pop) enum LevelLimit { // Client expected level limitation, like as used in DBC item max levels for "until max player level" diff --git a/src/server/game/DataStores/DBCStores.cpp b/src/server/game/DataStores/DBCStores.cpp index 5ede70da2a3..36ec418ed56 100644 --- a/src/server/game/DataStores/DBCStores.cpp +++ b/src/server/game/DataStores/DBCStores.cpp @@ -27,9 +27,6 @@ #include <boost/regex.hpp> #include <map> -#include <fstream> -#include <iostream> -#include <iomanip> typedef std::map<uint16, uint32> AreaFlagByAreaID; typedef std::map<uint32, uint32> AreaFlagByMapID; @@ -221,8 +218,6 @@ DBCStorage <WorldMapAreaEntry> sWorldMapAreaStore(WorldMapAreaEntryfmt); DBCStorage <WorldMapOverlayEntry> sWorldMapOverlayStore(WorldMapOverlayEntryfmt); DBCStorage <WorldSafeLocsEntry> sWorldSafeLocsStore(WorldSafeLocsEntryfmt); -std::unordered_map<uint32, FlyByCameraCollection> sFlyByCameraStore; - typedef std::list<std::string> StoreProblemList; uint32 DBCFileCount = 0; @@ -724,250 +719,10 @@ void LoadDBCStores(const std::string& dataPath) exit(1); } - LoadM2Cameras(dataPath); - TC_LOG_INFO("server.loading", ">> Initialized %d data stores in %u ms", DBCFileCount, GetMSTimeDiffToNow(oldMSTime)); } -// Convert the geomoetry from a spline value, to an actual WoW XYZ -G3D::Vector3 TranslateLocation(G3D::Vector4 const* DBCPosition, G3D::Vector3 const* basePosition, G3D::Vector3 const* splineVector) -{ - G3D::Vector3 work; - float x = basePosition->x + splineVector->x; - float y = basePosition->y + splineVector->y; - float z = basePosition->z + splineVector->z; - float const distance = sqrt((x * x) + (y * y)); - float angle = std::atan2(x, y) - DBCPosition->w; - - if (angle < 0) - angle += 2 * float(M_PI); - - work.x = DBCPosition->x + (distance * sin(angle)); - work.y = DBCPosition->y + (distance * cos(angle)); - work.z = DBCPosition->z + z; - return work; -} - -// Number of cameras not used. Multiple cameras never used in 3.3.5 -bool readCamera(M2Camera const* cam, uint32 buffSize, M2Header const* header, CinematicCameraEntry const* dbcentry) -{ - char const* buffer = reinterpret_cast<char const*>(header); - - FlyByCameraCollection cameras; - FlyByCameraCollection targetcam; - - G3D::Vector4 DBCData; - DBCData.x = dbcentry->base_x; - DBCData.y = dbcentry->base_y; - DBCData.z = dbcentry->base_z; - DBCData.w = dbcentry->base_o; - - // Read target locations, only so that we can calculate orientation - for (uint32 k = 0; k < cam->target_positions.timestamps.number; ++k) - { - // Extract Target positions - if (cam->target_positions.timestamps.offset_elements + sizeof(M2Array) > buffSize) - return false; - M2Array const* targTsArray = reinterpret_cast<M2Array const*>(buffer + cam->target_positions.timestamps.offset_elements); - if (targTsArray->offset_elements + sizeof(uint32) > buffSize || cam->target_positions.values.offset_elements + sizeof(M2Array) > buffSize) - return false; - uint32 const* targTimestamps = reinterpret_cast<uint32 const*>(buffer + targTsArray->offset_elements); - M2Array const* targArray = reinterpret_cast<M2Array const*>(buffer + cam->target_positions.values.offset_elements); - - if (targArray->offset_elements + sizeof(M2SplineKey<G3D::Vector3>) > buffSize) - return false; - M2SplineKey<G3D::Vector3> const* targPositions = reinterpret_cast<M2SplineKey<G3D::Vector3> const*>(buffer + targArray->offset_elements); - - // Read the data for this set - uint32 currPos = targArray->offset_elements; - for (uint32 i = 0; i < targTsArray->number; ++i) - { - if (currPos + sizeof(M2SplineKey<G3D::Vector3>) > buffSize) - return false; - // Translate co-ordinates - G3D::Vector3 newPos = TranslateLocation(&DBCData, &cam->target_position_base, &targPositions->p0); - - // Add to vector - FlyByCamera thisCam; - thisCam.timeStamp = targTimestamps[i]; - thisCam.locations.x = newPos.x; - thisCam.locations.y = newPos.y; - thisCam.locations.z = newPos.z; - thisCam.locations.w = 0.0f; - targetcam.push_back(thisCam); - targPositions++; - currPos += sizeof(M2SplineKey<G3D::Vector3>); - } - } - - // Read camera positions and timestamps (translating first position of 3 only, we don't need to translate the whole spline) - for (uint32 k = 0; k < cam->positions.timestamps.number; ++k) - { - // Extract Camera positions for this set - if (cam->positions.timestamps.offset_elements + sizeof(M2Array) > buffSize) - return false; - M2Array const* posTsArray = reinterpret_cast<M2Array const*>(buffer + cam->positions.timestamps.offset_elements); - if (posTsArray->offset_elements + sizeof(uint32) > buffSize || cam->positions.values.offset_elements + sizeof(M2Array) > buffSize) - return false; - uint32 const* posTimestamps = reinterpret_cast<uint32 const*>(buffer + posTsArray->offset_elements); - M2Array const* posArray = reinterpret_cast<M2Array const*>(buffer + cam->positions.values.offset_elements); - if (posArray->offset_elements + sizeof(M2SplineKey<G3D::Vector3>) > buffSize) - return false; - M2SplineKey<G3D::Vector3> const* positions = reinterpret_cast<M2SplineKey<G3D::Vector3> const*>(buffer + posArray->offset_elements); - - // Read the data for this set - uint32 currPos = posArray->offset_elements; - for (uint32 i = 0; i < posTsArray->number; ++i) - { - if (currPos + sizeof(M2SplineKey<G3D::Vector3>) > buffSize) - return false; - // Translate co-ordinates - G3D::Vector3 newPos = TranslateLocation(&DBCData, &cam->position_base, &positions->p0); - - // Add to vector - FlyByCamera thisCam; - thisCam.timeStamp = posTimestamps[i]; - thisCam.locations.x = newPos.x; - thisCam.locations.y = newPos.y; - thisCam.locations.z = newPos.z; - - if (targetcam.size() > 0) - { - // Find the target camera before and after this camera - FlyByCamera lastTarget; - FlyByCamera nextTarget; - - // Pre-load first item - lastTarget = targetcam[0]; - nextTarget = targetcam[0]; - for (uint32 j = 0; j < targetcam.size(); ++j) - { - nextTarget = targetcam[j]; - if (targetcam[j].timeStamp > posTimestamps[i]) - break; - - lastTarget = targetcam[j]; - } - - float x = lastTarget.locations.x; - float y = lastTarget.locations.y; - float z = lastTarget.locations.z; - - // Now, the timestamps for target cam and position can be different. So, if they differ we interpolate - if (lastTarget.timeStamp != posTimestamps[i]) - { - uint32 timeDiffTarget = nextTarget.timeStamp - lastTarget.timeStamp; - uint32 timeDiffThis = posTimestamps[i] - lastTarget.timeStamp; - float xDiff = nextTarget.locations.x - lastTarget.locations.x; - float yDiff = nextTarget.locations.y - lastTarget.locations.y; - float zDiff = nextTarget.locations.z - lastTarget.locations.z; - x = lastTarget.locations.x + (xDiff * (float(timeDiffThis) / float(timeDiffTarget))); - y = lastTarget.locations.y + (yDiff * (float(timeDiffThis) / float(timeDiffTarget))); - z = lastTarget.locations.z + (zDiff * (float(timeDiffThis) / float(timeDiffTarget))); - } - float xDiff = x - thisCam.locations.x; - float yDiff = y - thisCam.locations.y; - thisCam.locations.w = std::atan2(yDiff, xDiff); - - if (thisCam.locations.w < 0) - thisCam.locations.w += 2 * float(M_PI); - } - - cameras.push_back(thisCam); - positions++; - currPos += sizeof(M2SplineKey<G3D::Vector3>); - } - } - - sFlyByCameraStore[dbcentry->id] = cameras; - return true; -} - -void LoadM2Cameras(const std::string& dataPath) -{ - sFlyByCameraStore.clear(); - TC_LOG_INFO("server.loading", ">> Loading Cinematic Camera files"); - - uint32 oldMSTime = getMSTime(); - for (uint32 i = 0; i < sCinematicCameraStore.GetNumRows(); ++i) - { - if (CinematicCameraEntry const* dbcentry = sCinematicCameraStore.LookupEntry(i)) - { - std::string filename = dataPath.c_str(); - filename.append(dbcentry->filename); - - // Replace slashes - size_t loc = filename.find("\\"); - while (loc != std::string::npos) - { - filename.replace(loc, 1, "/"); - loc = filename.find("\\"); - } - - // Replace mdx to .m2 - loc = filename.find(".mdx"); - if (loc != std::string::npos) - filename.replace(loc, 4, ".m2"); - - std::ifstream m2file(filename.c_str(), std::ios::in | std::ios::binary); - if (!m2file.is_open()) - continue; - - // Get file size - m2file.seekg(0, std::ios::end); - std::streamoff const fileSize = m2file.tellg(); - - // Reject if not at least the size of the header - if (static_cast<uint32 const>(fileSize) < sizeof(M2Header)) - { - TC_LOG_ERROR("server.loading", "Camera file %s is damaged. File is smaller than header size", filename.c_str()); - m2file.close(); - continue; - } - - // Read 4 bytes (signature) - m2file.seekg(0, std::ios::beg); - char fileCheck[5]; - m2file.read(fileCheck, 4); - fileCheck[4] = 0; - - // Check file has correct magic (MD20) - if (strcmp(fileCheck, "MD20")) - { - TC_LOG_ERROR("server.loading", "Camera file %s is damaged. File identifier not found", filename.c_str()); - m2file.close(); - continue; - } - - // Now we have a good file, read it all into a vector of char's, then close the file. - std::vector<char> buffer(fileSize); - m2file.seekg(0, std::ios::beg); - if (!m2file.read(buffer.data(), fileSize)) - { - m2file.close(); - continue; - } - m2file.close(); - - // Read header - M2Header const* header = reinterpret_cast<M2Header const*>(buffer.data()); - - if (header->ofsCameras + sizeof(M2Camera) > static_cast<uint32 const>(fileSize)) - { - TC_LOG_ERROR("server.loading", "Camera file %s is damaged. Camera references position beyond file end", filename.c_str()); - continue; - } - - // Get camera(s) - Main header, then dump them. - M2Camera const* cam = reinterpret_cast<M2Camera const*>(buffer.data() + header->ofsCameras); - if (!readCamera(cam, fileSize, header, dbcentry)) - TC_LOG_ERROR("server.loading", "Camera file %s is damaged. Camera references position beyond file end", filename.c_str()); - } - } - TC_LOG_INFO("server.loading", ">> Loaded %u cinematic waypoint sets in %u ms", (uint32)sFlyByCameraStore.size(), GetMSTimeDiffToNow(oldMSTime)); -} - SimpleFactionsList const* GetFactionTeamList(uint32 faction) { FactionTeamMap::const_iterator itr = sFactionTeamMap.find(faction); diff --git a/src/server/game/DataStores/DBCStores.h b/src/server/game/DataStores/DBCStores.h index 6cad13fdf9a..00b4141555f 100644 --- a/src/server/game/DataStores/DBCStores.h +++ b/src/server/game/DataStores/DBCStores.h @@ -27,8 +27,6 @@ #include <list> typedef std::list<uint32> SimpleFactionsList; -typedef std::vector<FlyByCamera> FlyByCameraCollection; - TC_GAME_API SimpleFactionsList const* GetFactionTeamList(uint32 faction); TC_GAME_API char* GetPetName(uint32 petfamily, uint32 dbclang); @@ -196,9 +194,7 @@ TC_GAME_API extern DBCStorage <WMOAreaTableEntry> sWMOAreaTableStore; //TC_GAME_API extern DBCStorage <WorldMapAreaEntry> sWorldMapAreaStore; -- use Zone2MapCoordinates and Map2ZoneCoordinates TC_GAME_API extern DBCStorage <WorldMapOverlayEntry> sWorldMapOverlayStore; TC_GAME_API extern DBCStorage <WorldSafeLocsEntry> sWorldSafeLocsStore; -TC_GAME_API extern std::unordered_map<uint32, FlyByCameraCollection> sFlyByCameraStore; TC_GAME_API void LoadDBCStores(const std::string& dataPath); -TC_GAME_API void LoadM2Cameras(const std::string& dataPath); #endif diff --git a/src/server/game/DataStores/DBCStructure.h b/src/server/game/DataStores/DBCStructure.h index 51b3dcbd38b..13f0198a5e7 100644 --- a/src/server/game/DataStores/DBCStructure.h +++ b/src/server/game/DataStores/DBCStructure.h @@ -727,13 +727,11 @@ struct ChrRacesEntry struct CinematicCameraEntry { - uint32 id; // 0 index - char* filename; // 1 - uint32 soundid; // 2 in SoundEntries.dbc or 0 - float base_x; // 3 - float base_y; // 4 - float base_z; // 5 - float base_o; // 6 + uint32 ID; // 0 + char const* Model; // 1 Model filename (translate .mdx to .m2) + uint32 SoundID; // 2 Sound ID (voiceover for cinematic) + DBCPosition3D Origin; // 3-5 Position in map used for basis for M2 co-ordinates + float OriginFacing; // 6 Orientation in map used for basis for M2 co-ordinates }; struct CinematicSequencesEntry diff --git a/src/server/game/DataStores/M2Stores.cpp b/src/server/game/DataStores/M2Stores.cpp new file mode 100644 index 00000000000..69581f16549 --- /dev/null +++ b/src/server/game/DataStores/M2Stores.cpp @@ -0,0 +1,266 @@ +/* +* Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation; either version 2 of the License, or (at your +* option) any later version. +* +* This program is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along +* with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "DBCStores.h" +#include "M2Structure.h" +#include "M2Stores.h" +#include "Common.h" +#include "Containers.h" +#include "Log.h" +#include "World.h" +#include <fstream> +#include <iostream> +#include <iomanip> +#include <boost/filesystem/path.hpp> + +std::unordered_map<uint32, FlyByCameraCollection> sFlyByCameraStore; + +// Convert the geomoetry from a spline value, to an actual WoW XYZ +G3D::Vector3 TranslateLocation(G3D::Vector4 const* DBCPosition, G3D::Vector3 const* basePosition, G3D::Vector3 const* splineVector) +{ + G3D::Vector3 work; + float x = basePosition->x + splineVector->x; + float y = basePosition->y + splineVector->y; + float z = basePosition->z + splineVector->z; + float const distance = sqrt((x * x) + (y * y)); + float angle = std::atan2(x, y) - DBCPosition->w; + + if (angle < 0) + angle += 2 * float(M_PI); + + work.x = DBCPosition->x + (distance * sin(angle)); + work.y = DBCPosition->y + (distance * cos(angle)); + work.z = DBCPosition->z + z; + return work; +} + +// Number of cameras not used. Multiple cameras never used in 3.3.5 +bool readCamera(M2Camera const* cam, uint32 buffSize, M2Header const* header, CinematicCameraEntry const* dbcentry) +{ + char const* buffer = reinterpret_cast<char const*>(header); + + FlyByCameraCollection cameras; + FlyByCameraCollection targetcam; + + G3D::Vector4 DBCData; + DBCData.x = dbcentry->Origin.X; + DBCData.y = dbcentry->Origin.Y; + DBCData.z = dbcentry->Origin.Z; + DBCData.w = dbcentry->OriginFacing; + + // Read target locations, only so that we can calculate orientation + for (uint32 k = 0; k < cam->target_positions.timestamps.number; ++k) + { + // Extract Target positions + if (cam->target_positions.timestamps.offset_elements + sizeof(M2Array) > buffSize) + return false; + M2Array const* targTsArray = reinterpret_cast<M2Array const*>(buffer + cam->target_positions.timestamps.offset_elements); + if (targTsArray->offset_elements + sizeof(uint32) > buffSize || cam->target_positions.values.offset_elements + sizeof(M2Array) > buffSize) + return false; + uint32 const* targTimestamps = reinterpret_cast<uint32 const*>(buffer + targTsArray->offset_elements); + M2Array const* targArray = reinterpret_cast<M2Array const*>(buffer + cam->target_positions.values.offset_elements); + + if (targArray->offset_elements + sizeof(M2SplineKey<G3D::Vector3>) > buffSize) + return false; + M2SplineKey<G3D::Vector3> const* targPositions = reinterpret_cast<M2SplineKey<G3D::Vector3> const*>(buffer + targArray->offset_elements); + + // Read the data for this set + uint32 currPos = targArray->offset_elements; + for (uint32 i = 0; i < targTsArray->number; ++i) + { + if (currPos + sizeof(M2SplineKey<G3D::Vector3>) > buffSize) + return false; + // Translate co-ordinates + G3D::Vector3 newPos = TranslateLocation(&DBCData, &cam->target_position_base, &targPositions->p0); + + // Add to vector + FlyByCamera thisCam; + thisCam.timeStamp = targTimestamps[i]; + thisCam.locations.x = newPos.x; + thisCam.locations.y = newPos.y; + thisCam.locations.z = newPos.z; + thisCam.locations.w = 0.0f; + targetcam.push_back(thisCam); + targPositions++; + currPos += sizeof(M2SplineKey<G3D::Vector3>); + } + } + + // Read camera positions and timestamps (translating first position of 3 only, we don't need to translate the whole spline) + for (uint32 k = 0; k < cam->positions.timestamps.number; ++k) + { + // Extract Camera positions for this set + if (cam->positions.timestamps.offset_elements + sizeof(M2Array) > buffSize) + return false; + M2Array const* posTsArray = reinterpret_cast<M2Array const*>(buffer + cam->positions.timestamps.offset_elements); + if (posTsArray->offset_elements + sizeof(uint32) > buffSize || cam->positions.values.offset_elements + sizeof(M2Array) > buffSize) + return false; + uint32 const* posTimestamps = reinterpret_cast<uint32 const*>(buffer + posTsArray->offset_elements); + M2Array const* posArray = reinterpret_cast<M2Array const*>(buffer + cam->positions.values.offset_elements); + if (posArray->offset_elements + sizeof(M2SplineKey<G3D::Vector3>) > buffSize) + return false; + M2SplineKey<G3D::Vector3> const* positions = reinterpret_cast<M2SplineKey<G3D::Vector3> const*>(buffer + posArray->offset_elements); + + // Read the data for this set + uint32 currPos = posArray->offset_elements; + for (uint32 i = 0; i < posTsArray->number; ++i) + { + if (currPos + sizeof(M2SplineKey<G3D::Vector3>) > buffSize) + return false; + // Translate co-ordinates + G3D::Vector3 newPos = TranslateLocation(&DBCData, &cam->position_base, &positions->p0); + + // Add to vector + FlyByCamera thisCam; + thisCam.timeStamp = posTimestamps[i]; + thisCam.locations.x = newPos.x; + thisCam.locations.y = newPos.y; + thisCam.locations.z = newPos.z; + + if (targetcam.size() > 0) + { + // Find the target camera before and after this camera + FlyByCamera lastTarget; + FlyByCamera nextTarget; + + // Pre-load first item + lastTarget = targetcam[0]; + nextTarget = targetcam[0]; + for (uint32 j = 0; j < targetcam.size(); ++j) + { + nextTarget = targetcam[j]; + if (targetcam[j].timeStamp > posTimestamps[i]) + break; + + lastTarget = targetcam[j]; + } + + float x = lastTarget.locations.x; + float y = lastTarget.locations.y; + float z = lastTarget.locations.z; + + // Now, the timestamps for target cam and position can be different. So, if they differ we interpolate + if (lastTarget.timeStamp != posTimestamps[i]) + { + uint32 timeDiffTarget = nextTarget.timeStamp - lastTarget.timeStamp; + uint32 timeDiffThis = posTimestamps[i] - lastTarget.timeStamp; + float xDiff = nextTarget.locations.x - lastTarget.locations.x; + float yDiff = nextTarget.locations.y - lastTarget.locations.y; + float zDiff = nextTarget.locations.z - lastTarget.locations.z; + x = lastTarget.locations.x + (xDiff * (float(timeDiffThis) / float(timeDiffTarget))); + y = lastTarget.locations.y + (yDiff * (float(timeDiffThis) / float(timeDiffTarget))); + z = lastTarget.locations.z + (zDiff * (float(timeDiffThis) / float(timeDiffTarget))); + } + float xDiff = x - thisCam.locations.x; + float yDiff = y - thisCam.locations.y; + thisCam.locations.w = std::atan2(yDiff, xDiff); + + if (thisCam.locations.w < 0) + thisCam.locations.w += 2 * float(M_PI); + } + + cameras.push_back(thisCam); + positions++; + currPos += sizeof(M2SplineKey<G3D::Vector3>); + } + } + + sFlyByCameraStore[dbcentry->ID] = cameras; + return true; +} + +void LoadM2Cameras(std::string const& dataPath) +{ + sFlyByCameraStore.clear(); + TC_LOG_INFO("server.loading", ">> Loading Cinematic Camera files"); + + uint32 oldMSTime = getMSTime(); + for (uint32 i = 0; i < sCinematicCameraStore.GetNumRows(); ++i) + { + if (CinematicCameraEntry const* dbcentry = sCinematicCameraStore.LookupEntry(i)) + { + std::string filenameWork = dataPath; + filenameWork.append(dbcentry->Model); + + // Replace slashes (always to forward slash, because boost!) + std::replace(filenameWork.begin(), filenameWork.end(), '\\', '/'); + + boost::filesystem::path filename = filenameWork; + + // Convert to native format + filename.make_preferred(); + + // Replace mdx to .m2 + filename.replace_extension("m2"); + + std::ifstream m2file(filename.string().c_str(), std::ios::in | std::ios::binary); + if (!m2file.is_open()) + continue; + + // Get file size + m2file.seekg(0, std::ios::end); + std::streamoff const fileSize = m2file.tellg(); + + // Reject if not at least the size of the header + if (static_cast<uint32 const>(fileSize) < sizeof(M2Header)) + { + TC_LOG_ERROR("server.loading", "Camera file %s is damaged. File is smaller than header size", filename.string().c_str()); + m2file.close(); + continue; + } + + // Read 4 bytes (signature) + m2file.seekg(0, std::ios::beg); + char fileCheck[5]; + m2file.read(fileCheck, 4); + fileCheck[4] = 0; + + // Check file has correct magic (MD20) + if (strcmp(fileCheck, "MD20")) + { + TC_LOG_ERROR("server.loading", "Camera file %s is damaged. File identifier not found", filename.string().c_str()); + m2file.close(); + continue; + } + + // Now we have a good file, read it all into a vector of char's, then close the file. + std::vector<char> buffer(fileSize); + m2file.seekg(0, std::ios::beg); + if (!m2file.read(buffer.data(), fileSize)) + { + m2file.close(); + continue; + } + m2file.close(); + + // Read header + M2Header const* header = reinterpret_cast<M2Header const*>(buffer.data()); + + if (header->ofsCameras + sizeof(M2Camera) > static_cast<uint32 const>(fileSize)) + { + TC_LOG_ERROR("server.loading", "Camera file %s is damaged. Camera references position beyond file end", filename.string().c_str()); + continue; + } + + // Get camera(s) - Main header, then dump them. + M2Camera const* cam = reinterpret_cast<M2Camera const*>(buffer.data() + header->ofsCameras); + if (!readCamera(cam, fileSize, header, dbcentry)) + TC_LOG_ERROR("server.loading", "Camera file %s is damaged. Camera references position beyond file end", filename.string().c_str()); + } + } + TC_LOG_INFO("server.loading", ">> Loaded %u cinematic waypoint sets in %u ms", (uint32)sFlyByCameraStore.size(), GetMSTimeDiffToNow(oldMSTime)); +} diff --git a/src/server/game/DataStores/M2Stores.h b/src/server/game/DataStores/M2Stores.h new file mode 100644 index 00000000000..97224475e5d --- /dev/null +++ b/src/server/game/DataStores/M2Stores.h @@ -0,0 +1,36 @@ +/* +* Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation; either version 2 of the License, or (at your +* option) any later version. +* +* This program is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along +* with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef TRINITY_M2STORES_H +#define TRINITY_M2STORES_H + +#include "SharedDefines.h" +#include "Common.h" + +struct FlyByCamera +{ + uint32 timeStamp; + G3D::Vector4 locations; +}; + +typedef std::vector<FlyByCamera> FlyByCameraCollection; + +TC_GAME_API extern std::unordered_map<uint32, FlyByCameraCollection> sFlyByCameraStore; + +TC_GAME_API void LoadM2Cameras(std::string const& dataPath); + +#endif
\ No newline at end of file diff --git a/src/server/game/DataStores/M2Structure.h b/src/server/game/DataStores/M2Structure.h new file mode 100644 index 00000000000..43e8d008b9f --- /dev/null +++ b/src/server/game/DataStores/M2Structure.h @@ -0,0 +1,133 @@ +/* +* Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation; either version 2 of the License, or (at your +* option) any later version. +* +* This program is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along +* with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef TRINITY_M2STRUCTURE_H +#define TRINITY_M2STRUCTURE_H + +#include <G3D/Vector3.h> +#include <G3D/AABox.h> + +// Structures for M2 file. Source: https://wowdev.wiki +#pragma pack(push, 1) +template<typename T> +struct M2SplineKey +{ + T p0; + T p1; + T p2; +}; + +struct M2Header +{ + char Magic[4]; // "MD20" + uint32 Version; // The version of the format. + uint32 lName; // Length of the model's name including the trailing \0 + uint32 ofsName; // Offset to the name, it seems like models can get reloaded by this name.should be unique, i guess. + uint32 GlobalModelFlags; // 0x0001: tilt x, 0x0002: tilt y, 0x0008: add 2 fields in header, 0x0020: load .phys data (MoP+), 0x0080: has _lod .skin files (MoP?+), 0x0100: is camera related. + uint32 nGlobalSequences; + uint32 ofsGlobalSequences; // A list of timestamps. + uint32 nAnimations; + uint32 ofsAnimations; // Information about the animations in the model. + uint32 nAnimationLookup; + uint32 ofsAnimationLookup; // Mapping of global IDs to the entries in the Animation sequences block. + uint32 nBones; // MAX_BONES = 0x100 + uint32 ofsBones; // Information about the bones in this model. + uint32 nKeyBoneLookup; + uint32 ofsKeyBoneLookup; // Lookup table for key skeletal bones. + uint32 nVertices; + uint32 ofsVertices; // Vertices of the model. + uint32 nViews; // Views (LOD) are now in .skins. + uint32 nSubmeshAnimations; + uint32 ofsSubmeshAnimations; // Submesh color and alpha animations definitions. + uint32 nTextures; + uint32 ofsTextures; // Textures of this model. + uint32 nTransparency; + uint32 ofsTransparency; // Transparency of textures. + uint32 nUVAnimation; + uint32 ofsUVAnimation; + uint32 nTexReplace; + uint32 ofsTexReplace; // Replaceable Textures. + uint32 nRenderFlags; + uint32 ofsRenderFlags; // Blending modes / render flags. + uint32 nBoneLookupTable; + uint32 ofsBoneLookupTable; // A bone lookup table. + uint32 nTexLookup; + uint32 ofsTexLookup; // The same for textures. + uint32 nTexUnits; // possibly removed with cata?! + uint32 ofsTexUnits; // And texture units. Somewhere they have to be too. + uint32 nTransLookup; + uint32 ofsTransLookup; // Everything needs its lookup. Here are the transparencies. + uint32 nUVAnimLookup; + uint32 ofsUVAnimLookup; + G3D::AABox BoundingBox; // min/max( [1].z, 2.0277779f ) - 0.16f seems to be the maximum camera height + float BoundingSphereRadius; + G3D::AABox CollisionBox; + float CollisionSphereRadius; + uint32 nBoundingTriangles; + uint32 ofsBoundingTriangles; // Our bounding volumes. Similar structure like in the old ofsViews. + uint32 nBoundingVertices; + uint32 ofsBoundingVertices; + uint32 nBoundingNormals; + uint32 ofsBoundingNormals; + uint32 nAttachments; + uint32 ofsAttachments; // Attachments are for weapons etc. + uint32 nAttachLookup; + uint32 ofsAttachLookup; // Of course with a lookup. + uint32 nEvents; + uint32 ofsEvents; // Used for playing sounds when dying and a lot else. + uint32 nLights; + uint32 ofsLights; // Lights are mainly used in loginscreens but in wands and some doodads too. + uint32 nCameras; // Format of Cameras changed with version 271! + uint32 ofsCameras; // The cameras are present in most models for having a model in the Character-Tab. + uint32 nCameraLookup; + uint32 ofsCameraLookup; // And lookup-time again. + uint32 nRibbonEmitters; + uint32 ofsRibbonEmitters; // Things swirling around. See the CoT-entrance for light-trails. + uint32 nParticleEmitters; + uint32 ofsParticleEmitters; // Spells and weapons, doodads and loginscreens use them. Blood dripping of a blade? Particles. + uint32 nBlendMaps; // This has to deal with blending. Exists IFF (flags & 0x8) != 0. When set, textures blending is overriden by the associated array. See M2/WotLK#Blend_mode_overrides + uint32 ofsBlendMaps; // Same as above. Points to an array of uint16 of nBlendMaps entries -- From WoD information.}; +}; + +struct M2Array +{ + uint32_t number; + uint32 offset_elements; +}; +struct M2Track +{ + uint16_t interpolation_type; + uint16_t global_sequence; + M2Array timestamps; + M2Array values; +}; + +struct M2Camera +{ + uint32_t type; // 0: portrait, 1: characterinfo; -1: else (flyby etc.); referenced backwards in the lookup table. + float fov; // No radians, no degrees. Multiply by 35 to get degrees. + float far_clip; + float near_clip; + M2Track positions; // How the camera's position moves. Should be 3*3 floats. + G3D::Vector3 position_base; + M2Track target_positions; // How the target moves. Should be 3*3 floats. + G3D::Vector3 target_position_base; + M2Track rolldata; // The camera can have some roll-effect. Its 0 to 2*Pi. +}; +#pragma pack(pop) + +#endif
\ No newline at end of file diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index d3843c86aa4..a11f4131dcf 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -182,13 +182,13 @@ m_groupLootTimer(0), lootingGroupLowGUID(0), m_PlayerDamageReq(0), m_lootRecipient(), m_lootRecipientGroup(0), _skinner(), _pickpocketLootRestore(0), m_corpseRemoveTime(0), m_respawnTime(0), m_respawnDelay(300), m_corpseDelay(60), m_respawnradius(0.0f), m_boundaryCheckTime(2500), m_combatPulseTime(0), m_combatPulseDelay(0), m_reactState(REACT_AGGRESSIVE), m_defaultMovementType(IDLE_MOTION_TYPE), m_spawnId(0), m_equipmentId(0), m_originalEquipmentId(0), m_AlreadyCallAssistance(false), -m_AlreadySearchedAssistance(false), m_regenHealth(true), m_AI_locked(false), m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL), +m_AlreadySearchedAssistance(false), m_regenHealth(true), m_cannotReachTarget(false), m_cannotReachTimer(0), m_AI_locked(false), m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL), m_originalEntry(0), m_homePosition(), m_transportHomePosition(), m_creatureInfo(nullptr), m_creatureData(nullptr), m_waypointID(0), m_path_id(0), m_formation(nullptr), m_focusSpell(nullptr), m_focusDelay(0) { m_regenTimer = CREATURE_REGEN_INTERVAL; m_valuesCount = UNIT_END; - for (uint8 i = 0; i < CREATURE_MAX_SPELLS; ++i) + for (uint8 i = 0; i < MAX_CREATURE_SPELLS; ++i) m_spells[i] = 0; DisableReputationGain = false; @@ -367,13 +367,13 @@ bool Creature::InitEntry(uint32 entry, CreatureData const* data /*= nullptr*/) SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_GENDER, minfo->gender); // Load creature equipment - if (data && data->equipmentId != 0) + if (!data || data->equipmentId == 0) + LoadEquipment(); // use default equipment (if available) + else if (data && data->equipmentId != 0) // override, 0 means no equipment { m_originalEquipmentId = data->equipmentId; LoadEquipment(data->equipmentId); } - else - LoadEquipment(0, true); SetName(normalInfo->Name); // at normal entry always @@ -394,7 +394,7 @@ bool Creature::InitEntry(uint32 entry, CreatureData const* data /*= nullptr*/) if (!m_respawnradius && m_defaultMovementType == RANDOM_MOTION_TYPE) m_defaultMovementType = IDLE_MOTION_TYPE; - for (uint8 i=0; i < CREATURE_MAX_SPELLS; ++i) + for (uint8 i=0; i < MAX_CREATURE_SPELLS; ++i) m_spells[i] = GetCreatureTemplate()->spells[i]; return true; @@ -648,33 +648,32 @@ void Creature::Update(uint32 diff) m_regenTimer -= diff; } - if (m_regenTimer != 0) - break; - - bool bInCombat = IsInCombat() && (!GetVictim() || // if IsInCombat() is true and this has no victim - !EnsureVictim()->GetCharmerOrOwnerPlayerOrPlayerItself() || // or the victim/owner/charmer is not a player - !EnsureVictim()->GetCharmerOrOwnerPlayerOrPlayerItself()->IsGameMaster()); // or the victim/owner/charmer is not a GameMaster + if (m_regenTimer == 0) + { + bool bInCombat = IsInCombat() && (!GetVictim() || // if IsInCombat() is true and this has no victim + !EnsureVictim()->GetCharmerOrOwnerPlayerOrPlayerItself() || // or the victim/owner/charmer is not a player + !EnsureVictim()->GetCharmerOrOwnerPlayerOrPlayerItself()->IsGameMaster()); // or the victim/owner/charmer is not a GameMaster - /*if (m_regenTimer <= diff) - {*/ - if (!IsInEvadeMode() && (!bInCombat || IsPolymorphed())) // regenerate health if not in combat or if polymorphed - RegenerateHealth(); + if (!IsInEvadeMode() && (!bInCombat || IsPolymorphed() || CanNotReachTarget())) // regenerate health if not in combat or if polymorphed + RegenerateHealth(); - if (HasFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_REGENERATE_POWER)) - { - if (getPowerType() == POWER_ENERGY) - Regenerate(POWER_ENERGY); - else - RegenerateMana(); + if (HasFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_REGENERATE_POWER)) + { + if (getPowerType() == POWER_ENERGY) + Regenerate(POWER_ENERGY); + else + RegenerateMana(); + } + m_regenTimer = CREATURE_REGEN_INTERVAL; } - /*if (!bIsPolymorphed) // only increase the timer if not polymorphed - m_regenTimer += CREATURE_REGEN_INTERVAL - diff; + if (CanNotReachTarget() && !IsInEvadeMode() && !GetMap()->IsRaid()) + { + m_cannotReachTimer += diff; + if (m_cannotReachTimer >= CREATURE_NOPATH_EVADE_TIME) + if (IsAIEnabled) + AI()->EnterEvadeMode(CreatureAI::EVADE_REASON_NO_PATH); } - else - if (!bIsPolymorphed) // if polymorphed, skip the timer - m_regenTimer -= diff;*/ - m_regenTimer = CREATURE_REGEN_INTERVAL; break; } default: @@ -1824,7 +1823,7 @@ bool Creature::isWorldBoss() const if (IsPet()) return false; - return (GetCreatureTemplate()->type_flags & CREATURE_TYPEFLAGS_BOSS) != 0; + return (GetCreatureTemplate()->type_flags & CREATURE_TYPE_FLAG_BOSS_MOB) != 0; } SpellInfo const* Creature::reachWithSpellAttack(Unit* victim) @@ -1832,7 +1831,7 @@ SpellInfo const* Creature::reachWithSpellAttack(Unit* victim) if (!victim) return nullptr; - for (uint32 i=0; i < CREATURE_MAX_SPELLS; ++i) + for (uint32 i=0; i < MAX_CREATURE_SPELLS; ++i) { if (!m_spells[i]) continue; @@ -1880,7 +1879,7 @@ SpellInfo const* Creature::reachWithSpellCure(Unit* victim) if (!victim) return nullptr; - for (uint32 i=0; i < CREATURE_MAX_SPELLS; ++i) + for (uint32 i=0; i < MAX_CREATURE_SPELLS; ++i) { if (!m_spells[i]) continue; @@ -2325,10 +2324,10 @@ uint32 Creature::GetShieldBlockValue() const //dunno mob block bool Creature::HasSpell(uint32 spellID) const { uint8 i; - for (i = 0; i < CREATURE_MAX_SPELLS; ++i) + for (i = 0; i < MAX_CREATURE_SPELLS; ++i) if (spellID == m_spells[i]) break; - return i < CREATURE_MAX_SPELLS; //broke before end of iteration of known spells + return i < MAX_CREATURE_SPELLS; //broke before end of iteration of known spells } time_t Creature::GetRespawnTimeEx() const diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index 8466dad9e95..cc0e0559d28 100644 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -67,12 +67,13 @@ enum CreatureFlagsExtra CREATURE_FLAG_EXTRA_NO_SKILLGAIN | CREATURE_FLAG_EXTRA_TAUNT_DIMINISH | CREATURE_FLAG_EXTRA_ALL_DIMINISH | \ CREATURE_FLAG_EXTRA_GUARD | CREATURE_FLAG_EXTRA_IGNORE_PATHFINDING | CREATURE_FLAG_EXTRA_NO_PLAYER_DAMAGE_REQ | CREATURE_FLAG_EXTRA_IMMUNITY_KNOCKBACK) -#define CREATURE_REGEN_INTERVAL 2 * IN_MILLISECONDS +static const uint32 CREATURE_REGEN_INTERVAL = 2 * IN_MILLISECONDS; +static const uint32 CREATURE_NOPATH_EVADE_TIME = 5 * IN_MILLISECONDS; -#define MAX_KILL_CREDIT 2 -#define MAX_CREATURE_MODELS 4 -#define MAX_CREATURE_QUEST_ITEMS 6 -#define CREATURE_MAX_SPELLS 8 +static const uint8 MAX_KILL_CREDIT = 2; +static const uint32 MAX_CREATURE_MODELS = 4; +static const uint32 MAX_CREATURE_QUEST_ITEMS = 6; +static const uint32 MAX_CREATURE_SPELLS = 8; // from `creature_template` table struct TC_GAME_API CreatureTemplate @@ -106,7 +107,7 @@ struct TC_GAME_API CreatureTemplate uint32 unit_flags; // enum UnitFlags mask values uint32 unit_flags2; // enum UnitFlags2 mask values uint32 dynamicflags; - uint32 family; // enum CreatureFamily values (optional) + CreatureFamily family; // enum CreatureFamily values (optional) uint32 trainer_type; uint32 trainer_spell; uint32 trainer_class; @@ -117,7 +118,7 @@ struct TC_GAME_API CreatureTemplate uint32 pickpocketLootId; uint32 SkinLootId; int32 resistance[MAX_SPELL_SCHOOL]; - uint32 spells[CREATURE_MAX_SPELLS]; + uint32 spells[MAX_CREATURE_SPELLS]; uint32 PetSpellDataId; uint32 VehicleId; uint32 mingold; @@ -145,11 +146,11 @@ struct TC_GAME_API CreatureTemplate // helpers SkillType GetRequiredLootSkill() const { - if (type_flags & CREATURE_TYPEFLAGS_HERBLOOT) + if (type_flags & CREATURE_TYPE_FLAG_HERB_SKINNING_SKILL) return SKILL_HERBALISM; - else if (type_flags & CREATURE_TYPEFLAGS_MININGLOOT) + else if (type_flags & CREATURE_TYPE_FLAG_MINING_SKINNING_SKILL) return SKILL_MINING; - else if (type_flags & CREATURE_TYPEFLAGS_ENGINEERLOOT) + else if (type_flags & CREATURE_TYPE_FLAG_ENGINEERING_SKINNING_SKILL) return SKILL_ENGINEERING; else return SKILL_SKINNING; // normal case @@ -157,12 +158,12 @@ struct TC_GAME_API CreatureTemplate bool IsExotic() const { - return (type_flags & CREATURE_TYPEFLAGS_EXOTIC) != 0; + return (type_flags & CREATURE_TYPE_FLAG_EXOTIC_PET) != 0; } bool IsTameable(bool canTameExotic) const { - if (type != CREATURE_TYPE_BEAST || family == 0 || (type_flags & CREATURE_TYPEFLAGS_TAMEABLE) == 0) + if (type != CREATURE_TYPE_BEAST || family == CREATURE_FAMILY_NONE || (type_flags & CREATURE_TYPE_FLAG_TAMEABLE_PET) == 0) return false; // if can tame exotic then can tame any tameable @@ -475,6 +476,7 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma uint8 getLevelForTarget(WorldObject const* target) const override; // overwrite Unit::getLevelForTarget for boss level support bool IsInEvadeMode() const { return HasUnitState(UNIT_STATE_EVADE); } + bool IsEvadingAttacks() const { return IsInEvadeMode() || CanNotReachTarget(); } bool AIM_Destroy(); bool AIM_Initialize(CreatureAI* ai = NULL); @@ -567,7 +569,7 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma SpellInfo const* reachWithSpellAttack(Unit* victim); SpellInfo const* reachWithSpellCure(Unit* victim); - uint32 m_spells[CREATURE_MAX_SPELLS]; + uint32 m_spells[MAX_CREATURE_SPELLS]; bool CanStartAttack(Unit const* u, bool force) const; float GetAttackDistance(Unit const* player) const; @@ -632,6 +634,15 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma virtual uint8 GetPetAutoSpellSize() const { return MAX_SPELL_CHARM; } virtual uint32 GetPetAutoSpellOnPos(uint8 pos) const; + void SetCannotReachTarget(bool cannotReach) + { + if (cannotReach == m_cannotReachTarget) + return; + m_cannotReachTarget = cannotReach; + m_cannotReachTimer = 0; + } + bool CanNotReachTarget() const { return m_cannotReachTarget; } + void SetPosition(float x, float y, float z, float o); void SetPosition(const Position &pos) { SetPosition(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation()); } @@ -719,6 +730,8 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma bool m_AlreadyCallAssistance; bool m_AlreadySearchedAssistance; bool m_regenHealth; + bool m_cannotReachTarget; + uint32 m_cannotReachTimer; bool m_AI_locked; SpellSchoolMask m_meleeDamageSchoolMask; diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index 7f922f89572..d7e478bb4e5 100644 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -34,7 +34,7 @@ #include "Transport.h" GameObject::GameObject() : WorldObject(false), MapObject(), - m_model(NULL), m_goValue(), m_AI(NULL) + m_model(nullptr), m_goValue(), m_AI(nullptr) { m_objectType |= TYPEMASK_GAMEOBJECT; m_objectTypeId = TYPEID_GAMEOBJECT; @@ -49,8 +49,8 @@ GameObject::GameObject() : WorldObject(false), MapObject(), m_usetimes = 0; m_spellId = 0; m_cooldownTime = 0; - m_goInfo = NULL; - m_goData = NULL; + m_goInfo = nullptr; + m_goData = nullptr; m_spawnId = 0; m_rotation = 0; @@ -496,7 +496,7 @@ void GameObject::Update(uint32 diff) radius = goInfo->trap.diameter / 2.f; // Pointer to appropriate target if found any - Unit* target = NULL; + Unit* target = nullptr; /// @todo this hack with search required until GO casting not implemented if (Unit* owner = GetOwner()) @@ -511,7 +511,7 @@ void GameObject::Update(uint32 diff) else { // Environmental trap: Any player - Player* player = NULL; + Player* player = nullptr; Trinity::AnyPlayerInObjectRangeCheck checker(this, radius); Trinity::PlayerSearcher<Trinity::AnyPlayerInObjectRangeCheck> searcher(this, player, checker); VisitNearbyWorldObject(radius, searcher); @@ -571,8 +571,8 @@ void GameObject::Update(uint32 diff) GameObjectTemplate const* goInfo = GetGOInfo(); if (goInfo->trap.type == 2 && goInfo->trap.spellId) { - /// @todo NULL target won't work for target type 1 - CastSpell(NULL, goInfo->trap.spellId); + /// @todo nullptr target won't work for target type 1 + CastSpell(nullptr, goInfo->trap.spellId); SetLootState(GO_JUST_DEACTIVATED); } else if (Unit* target = ObjectAccessor::GetUnit(*this, m_lootStateUnitGUID)) @@ -1093,7 +1093,7 @@ void GameObject::TriggeringLinkedGameObject(uint32 trapEntry, Unit* target) float range = float(target->GetSpellMaxRangeForTarget(GetOwner(), trapSpell)); // search nearest linked GO - GameObject* trapGO = NULL; + GameObject* trapGO = nullptr; { // using original GO distance CellCoord p(Trinity::ComputeCellCoord(GetPositionX(), GetPositionY())); @@ -1113,7 +1113,7 @@ void GameObject::TriggeringLinkedGameObject(uint32 trapEntry, Unit* target) GameObject* GameObject::LookupFishingHoleAround(float range) { - GameObject* ok = NULL; + GameObject* ok = nullptr; CellCoord p(Trinity::ComputeCellCoord(GetPositionX(), GetPositionY())); Cell cell(p); @@ -1136,7 +1136,7 @@ void GameObject::ResetDoorOrButton() m_cooldownTime = 0; } -void GameObject::UseDoorOrButton(uint32 time_to_restore, bool alternative /* = false */, Unit* user /*=NULL*/) +void GameObject::UseDoorOrButton(uint32 time_to_restore, bool alternative /* = false */, Unit* user /*=nullptr*/) { if (m_lootState != GO_READY) return; @@ -1160,7 +1160,7 @@ void GameObject::SetGoArtKit(uint8 kit) void GameObject::SetGoArtKit(uint8 artkit, GameObject* go, ObjectGuid::LowType lowguid) { - const GameObjectData* data = NULL; + const GameObjectData* data = nullptr; if (go) { go->SetGoArtKit(artkit); @@ -1386,7 +1386,7 @@ void GameObject::Use(Unit* user) // cast this spell later if provided spellId = info->goober.spellId; - spellCaster = NULL; + spellCaster = nullptr; break; } @@ -1505,7 +1505,7 @@ void GameObject::Use(Unit* user) GameObjectTemplate const* info = GetGOInfo(); - Player* m_ritualOwner = NULL; + Player* m_ritualOwner = nullptr; if (m_ritualOwnerGUID) m_ritualOwner = ObjectAccessor::FindPlayer(m_ritualOwnerGUID); @@ -1869,7 +1869,7 @@ bool GameObject::IsInRange(float x, float y, float z, float radius) const && dz < info->maxZ + radius && dz > info->minZ - radius; } -void GameObject::EventInform(uint32 eventId, WorldObject* invoker /*= NULL*/) +void GameObject::EventInform(uint32 eventId, WorldObject* invoker /*= nullptr*/) { if (!eventId) return; @@ -1929,7 +1929,7 @@ void GameObject::UpdateRotationFields(float rotation2 /*=0.0f*/, float rotation3 SetFloatValue(GAMEOBJECT_PARENTROTATION+3, rotation3); } -void GameObject::ModifyHealth(int32 change, Unit* attackerOrHealer /*= NULL*/, uint32 spellId /*= 0*/) +void GameObject::ModifyHealth(int32 change, Unit* attackerOrHealer /*= nullptr*/, uint32 spellId /*= 0*/) { if (!m_goValue.Building.MaxHealth || !change) return; @@ -1948,7 +1948,7 @@ void GameObject::ModifyHealth(int32 change, Unit* attackerOrHealer /*= NULL*/, u // Set the health bar, value = 255 * healthPct; SetGoAnimProgress(m_goValue.Building.Health * 255 / m_goValue.Building.MaxHealth); - Player* player = attackerOrHealer ? attackerOrHealer->GetCharmerOrOwnerPlayerOrPlayerItself() : NULL; + Player* player = attackerOrHealer ? attackerOrHealer->GetCharmerOrOwnerPlayerOrPlayerItself() : nullptr; // dealing damage, send packet if (player) @@ -1979,7 +1979,7 @@ void GameObject::ModifyHealth(int32 change, Unit* attackerOrHealer /*= NULL*/, u SetDestructibleState(newState, player, false); } -void GameObject::SetDestructibleState(GameObjectDestructibleState state, Player* eventInvoker /*= NULL*/, bool setHealth /*= false*/) +void GameObject::SetDestructibleState(GameObjectDestructibleState state, Player* eventInvoker /*= nullptr*/, bool setHealth /*= false*/) { // the user calling this must know he is already operating on destructible gameobject ASSERT(GetGoType() == GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING); @@ -2161,14 +2161,14 @@ void GameObject::UpdateModel() Player* GameObject::GetLootRecipient() const { if (!m_lootRecipient) - return NULL; + return nullptr; return ObjectAccessor::FindConnectedPlayer(m_lootRecipient); } Group* GameObject::GetLootRecipientGroup() const { if (!m_lootRecipientGroup) - return NULL; + return nullptr; return sGroupMgr->GetGroupByGUID(m_lootRecipientGroup); } @@ -2176,7 +2176,7 @@ void GameObject::SetLootRecipient(Unit* unit) { // set the player whose group should receive the right // to loot the creature after it dies - // should be set to NULL after the loot disappears + // should be set to nullptr after the loot disappears if (!unit) { @@ -2295,7 +2295,7 @@ void GameObject::BuildValuesUpdate(uint8 updateType, ByteBuffer* data, Player* t data->append(fieldBuffer); } -void GameObject::GetRespawnPosition(float &x, float &y, float &z, float* ori /* = NULL*/) const +void GameObject::GetRespawnPosition(float &x, float &y, float &z, float* ori /* = nullptr*/) const { if (m_spawnId) { diff --git a/src/server/game/Entities/Item/ItemEnchantmentMgr.cpp b/src/server/game/Entities/Item/ItemEnchantmentMgr.cpp index b44a3e7ad7b..a7b410bc04b 100644 --- a/src/server/game/Entities/Item/ItemEnchantmentMgr.cpp +++ b/src/server/game/Entities/Item/ItemEnchantmentMgr.cpp @@ -44,7 +44,7 @@ typedef std::unordered_map<uint32, EnchStoreList> EnchantmentStore; static EnchantmentStore RandomItemEnch; -TC_GAME_API void LoadRandomEnchantmentsTable() +void LoadRandomEnchantmentsTable() { uint32 oldMSTime = getMSTime(); @@ -77,7 +77,7 @@ TC_GAME_API void LoadRandomEnchantmentsTable() TC_LOG_ERROR("server.loading", ">> Loaded 0 Item Enchantment definitions. DB table `item_enchantment_template` is empty."); } -TC_GAME_API uint32 GetItemEnchantMod(int32 entry) +uint32 GetItemEnchantMod(int32 entry) { if (!entry) return 0; @@ -118,7 +118,7 @@ TC_GAME_API uint32 GetItemEnchantMod(int32 entry) return 0; } -TC_GAME_API uint32 GenerateEnchSuffixFactor(uint32 item_id) +uint32 GenerateEnchSuffixFactor(uint32 item_id) { ItemTemplate const* itemProto = sObjectMgr->GetItemTemplate(item_id); diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index 45952ba51ac..daad0c9d958 100644 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -1154,9 +1154,13 @@ bool WorldObject::IsWithinLOSInMap(const WorldObject* obj) const if (!IsInMap(obj)) return false; - float ox, oy, oz; - obj->GetPosition(ox, oy, oz); - return IsWithinLOS(ox, oy, oz); + float x, y, z; + if (obj->GetTypeId() == TYPEID_PLAYER) + obj->GetPosition(x, y, z); + else + obj->GetHitSpherePointFor(GetPosition(), x, y, z); + + return IsWithinLOS(x, y, z); } float WorldObject::GetDistance(const WorldObject* obj) const @@ -1240,11 +1244,36 @@ bool WorldObject::IsWithinLOS(float ox, float oy, float oz) const VMAP::IVMapManager* vMapManager = VMAP::VMapFactory::createOrGetVMapManager(); return vMapManager->isInLineOfSight(GetMapId(), x, y, z+2.0f, ox, oy, oz+2.0f);*/ if (IsInWorld()) - return GetMap()->isInLineOfSight(GetPositionX(), GetPositionY(), GetPositionZ()+2.f, ox, oy, oz+2.f, GetPhaseMask()); + { + float x, y, z; + if (GetTypeId() == TYPEID_PLAYER) + GetPosition(x, y, z); + else + GetHitSpherePointFor({ ox, oy, oz }, x, y, z); + + return GetMap()->isInLineOfSight(x, y, z + 2.0f, ox, oy, oz + 2.0f, GetPhaseMask()); + } return true; } +Position WorldObject::GetHitSpherePointFor(Position const& dest) const +{ + G3D::Vector3 vThis(GetPositionX(), GetPositionY(), GetPositionZ()); + G3D::Vector3 vObj(dest.GetPositionX(), dest.GetPositionY(), dest.GetPositionZ()); + G3D::Vector3 contactPoint = vThis + (vObj - vThis).directionOrZero() * GetObjectSize(); + + return Position(contactPoint.x, contactPoint.y, contactPoint.z, GetAngle(contactPoint.x, contactPoint.y)); +} + +void WorldObject::GetHitSpherePointFor(Position const& dest, float& x, float& y, float& z) const +{ + Position pos = GetHitSpherePointFor(dest); + x = pos.GetPositionX(); + y = pos.GetPositionY(); + z = pos.GetPositionZ(); +} + bool WorldObject::GetDistanceOrder(WorldObject const* obj1, WorldObject const* obj2, bool is3D /* = true */) const { float dx1 = GetPositionX() - obj1->GetPositionX(); @@ -1471,7 +1500,7 @@ float WorldObject::GetGridActivationRange() const { if (ToPlayer()) { - if (ToPlayer()->IsOnCinematic()) + if (ToPlayer()->GetCinematicMgr()->IsOnCinematic()) return DEFAULT_VISIBILITY_INSTANCE; return GetMap()->GetVisibilityRange(); } @@ -1504,7 +1533,7 @@ float WorldObject::GetSightRange(const WorldObject* target) const { if (target && target->isActiveObject() && !target->ToPlayer()) return MAX_VISIBILITY_DISTANCE; - else if (ToPlayer()->IsOnCinematic()) + else if (ToPlayer()->GetCinematicMgr()->IsOnCinematic()) return DEFAULT_VISIBILITY_INSTANCE; else return GetMap()->GetVisibilityRange(); @@ -2038,7 +2067,10 @@ void WorldObject::SummonCreatureGroup(uint8 group, std::list<TempSummon*>* list std::vector<TempSummonData> const* data = sObjectMgr->GetSummonGroup(GetEntry(), GetTypeId() == TYPEID_GAMEOBJECT ? SUMMONER_TYPE_GAMEOBJECT : SUMMONER_TYPE_CREATURE, group); if (!data) + { + TC_LOG_WARN("scripts", "%s (%s) tried to summon non-existing summon group %u.", GetName().c_str(), GetGUID().ToString().c_str(), group); return; + } for (std::vector<TempSummonData>::const_iterator itr = data->begin(); itr != data->end(); ++itr) if (TempSummon* summon = SummonCreature(itr->entry, itr->pos, itr->type, itr->time)) diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h index d4c8fc35451..47b28d8ea3a 100644 --- a/src/server/game/Entities/Object/Object.h +++ b/src/server/game/Entities/Object/Object.h @@ -488,6 +488,8 @@ class TC_GAME_API WorldObject : public Object, public WorldLocation bool IsWithinDistInMap(WorldObject const* obj, float dist2compare, bool is3D = true) const; bool IsWithinLOS(float x, float y, float z) const; bool IsWithinLOSInMap(WorldObject const* obj) const; + Position GetHitSpherePointFor(Position const& dest) const; + void GetHitSpherePointFor(Position const& dest, float& x, float& y, float& z) const; bool GetDistanceOrder(WorldObject const* obj1, WorldObject const* obj2, bool is3D = true) const; bool IsInRange(WorldObject const* obj, float minRange, float maxRange, bool is3D = true) const; bool IsInRange2d(float x, float y, float minRange, float maxRange) const; @@ -550,8 +552,8 @@ class TC_GAME_API WorldObject : public Object, public WorldLocation GameObject* FindNearestGameObject(uint32 entry, float range) const; GameObject* FindNearestGameObjectOfType(GameobjectTypes type, float range) const; - void GetGameObjectListWithEntryInGrid(std::list<GameObject*>& lList, uint32 uiEntry, float fMaxSearchRange) const; - void GetCreatureListWithEntryInGrid(std::list<Creature*>& lList, uint32 uiEntry, float fMaxSearchRange) const; + void GetGameObjectListWithEntryInGrid(std::list<GameObject*>& lList, uint32 uiEntry = 0, float fMaxSearchRange = 250.0f) const; + void GetCreatureListWithEntryInGrid(std::list<Creature*>& lList, uint32 uiEntry = 0, float fMaxSearchRange = 250.0f) const; void GetPlayerListInGrid(std::list<Player*>& lList, float fMaxSearchRange) const; void DestroyForNearbyPlayers(); @@ -584,14 +586,6 @@ class TC_GAME_API WorldObject : public Object, public WorldLocation template<class NOTIFIER> void VisitNearbyGridObject(float const& radius, NOTIFIER& notifier) const { if (IsInWorld()) GetMap()->VisitGrid(GetPositionX(), GetPositionY(), radius, notifier); } template<class NOTIFIER> void VisitNearbyWorldObject(float const& radius, NOTIFIER& notifier) const { if (IsInWorld()) GetMap()->VisitWorld(GetPositionX(), GetPositionY(), radius, notifier); } -#ifdef MAP_BASED_RAND_GEN - int32 irand(int32 min, int32 max) const { return int32 (GetMap()->mtRand.randInt(max - min)) + min; } - uint32 urand(uint32 min, uint32 max) const { return GetMap()->mtRand.randInt(max - min) + min;} - int32 rand32() const { return GetMap()->mtRand.randInt();} - double rand_norm() const { return GetMap()->mtRand.randExc();} - double rand_chance() const { return GetMap()->mtRand.randExc(100.0);} -#endif - uint32 LastUsedScriptID; // Transports diff --git a/src/server/game/Entities/Player/CinematicMgr.cpp b/src/server/game/Entities/Player/CinematicMgr.cpp new file mode 100644 index 00000000000..cc5a62300ad --- /dev/null +++ b/src/server/game/Entities/Player/CinematicMgr.cpp @@ -0,0 +1,174 @@ +/* +* Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> +* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation; either version 2 of the License, or (at your +* option) any later version. +* +* This program is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along +* with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "CinematicMgr.h" +#include "Creature.h" +#include "Player.h" +#include "TemporarySummon.h" + +CinematicMgr::CinematicMgr(Player* playerref) +{ + player = playerref; + m_cinematicDiff = 0; + m_lastCinematicCheck = 0; + m_activeCinematicCameraId = 0; + m_cinematicLength = 0; + m_cinematicCamera = nullptr; + m_remoteSightPosition = Position(0.0f, 0.0f, 0.0f); + m_CinematicObject = nullptr; +} + +CinematicMgr::~CinematicMgr() +{ + if (m_cinematicCamera && m_activeCinematicCameraId) + EndCinematic(); +} + +void CinematicMgr::BeginCinematic() +{ + // Sanity check for active camera set + if (m_activeCinematicCameraId == 0) + return; + + auto itr = sFlyByCameraStore.find(m_activeCinematicCameraId); + if (itr != sFlyByCameraStore.end()) + { + // Initialize diff, and set camera + m_cinematicDiff = 0; + m_cinematicCamera = &itr->second; + + auto camitr = m_cinematicCamera->begin(); + if (camitr != m_cinematicCamera->end()) + { + Position pos(camitr->locations.x, camitr->locations.y, camitr->locations.z, camitr->locations.w); + if (!pos.IsPositionValid()) + return; + + player->GetMap()->LoadGrid(camitr->locations.x, camitr->locations.y); + m_CinematicObject = player->SummonCreature(VISUAL_WAYPOINT, pos.m_positionX, pos.m_positionY, pos.m_positionZ, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 5 * MINUTE * IN_MILLISECONDS); + if (m_CinematicObject) + { + m_CinematicObject->setActive(true); + player->SetViewpoint(m_CinematicObject, true); + } + + // Get cinematic length + FlyByCameraCollection::const_reverse_iterator camrevitr = m_cinematicCamera->rbegin(); + if (camrevitr != m_cinematicCamera->rend()) + m_cinematicLength = camrevitr->timeStamp; + else + m_cinematicLength = 0; + } + } +} + +void CinematicMgr::EndCinematic() +{ + if (m_activeCinematicCameraId == 0) + return; + + m_cinematicDiff = 0; + m_cinematicCamera = nullptr; + m_activeCinematicCameraId = 0; + if (m_CinematicObject) + { + if (WorldObject* vpObject = player->GetViewpoint()) + if (vpObject == m_CinematicObject) + player->SetViewpoint(m_CinematicObject, false); + + m_CinematicObject->AddObjectToRemoveList(); + } +} + +void CinematicMgr::UpdateCinematicLocation(uint32 /*diff*/) +{ + if (m_activeCinematicCameraId == 0 || !m_cinematicCamera || m_cinematicCamera->size() == 0) + return; + + Position lastPosition; + uint32 lastTimestamp = 0; + Position nextPosition; + uint32 nextTimestamp = 0; + + // Obtain direction of travel + for (FlyByCamera cam : *m_cinematicCamera) + { + if (cam.timeStamp > m_cinematicDiff) + { + nextPosition = Position(cam.locations.x, cam.locations.y, cam.locations.z, cam.locations.w); + nextTimestamp = cam.timeStamp; + break; + } + lastPosition = Position(cam.locations.x, cam.locations.y, cam.locations.z, cam.locations.w); + lastTimestamp = cam.timeStamp; + } + float angle = lastPosition.GetAngle(&nextPosition); + angle -= lastPosition.GetOrientation(); + if (angle < 0) + angle += 2 * float(M_PI); + + // Look for position around 2 second ahead of us. + int32 workDiff = m_cinematicDiff; + + // Modify result based on camera direction (Humans for example, have the camera point behind) + workDiff += static_cast<int32>(float(CINEMATIC_LOOKAHEAD) * cos(angle)); + + // Get an iterator to the last entry in the cameras, to make sure we don't go beyond the end + FlyByCameraCollection::const_reverse_iterator endItr = m_cinematicCamera->rbegin(); + if (endItr != m_cinematicCamera->rend() && workDiff > static_cast<int32>(endItr->timeStamp)) + workDiff = endItr->timeStamp; + + // Never try to go back in time before the start of cinematic! + if (workDiff < 0) + workDiff = m_cinematicDiff; + + // Obtain the previous and next waypoint based on timestamp + for (FlyByCamera cam : *m_cinematicCamera) + { + if (static_cast<int32>(cam.timeStamp) >= workDiff) + { + nextPosition = Position(cam.locations.x, cam.locations.y, cam.locations.z, cam.locations.w); + nextTimestamp = cam.timeStamp; + break; + } + lastPosition = Position(cam.locations.x, cam.locations.y, cam.locations.z, cam.locations.w); + lastTimestamp = cam.timeStamp; + } + + // Never try to go beyond the end of the cinematic + if (workDiff > static_cast<int32>(nextTimestamp)) + workDiff = static_cast<int32>(nextTimestamp); + + // Interpolate the position for this moment in time (or the adjusted moment in time) + uint32 timeDiff = nextTimestamp - lastTimestamp; + uint32 interDiff = workDiff - lastTimestamp; + float xDiff = nextPosition.m_positionX - lastPosition.m_positionX; + float yDiff = nextPosition.m_positionY - lastPosition.m_positionY; + float zDiff = nextPosition.m_positionZ - lastPosition.m_positionZ; + Position interPosition(lastPosition.m_positionX + (xDiff * (float(interDiff) / float(timeDiff))), lastPosition.m_positionY + + (yDiff * (float(interDiff) / float(timeDiff))), lastPosition.m_positionZ + (zDiff * (float(interDiff) / float(timeDiff)))); + + // Advance (at speed) to this position. The remote sight object is used + // to send update information to player in cinematic + if (m_CinematicObject && interPosition.IsPositionValid()) + m_CinematicObject->MonsterMoveWithSpeed(interPosition.m_positionX, interPosition.m_positionY, interPosition.m_positionZ, 500.0f, false, true); + + // If we never received an end packet 10 seconds after the final timestamp then force an end + if (m_cinematicDiff > m_cinematicLength + 10 * IN_MILLISECONDS) + EndCinematic(); +} diff --git a/src/server/game/Entities/Player/CinematicMgr.h b/src/server/game/Entities/Player/CinematicMgr.h new file mode 100644 index 00000000000..ab067afa042 --- /dev/null +++ b/src/server/game/Entities/Player/CinematicMgr.h @@ -0,0 +1,60 @@ +/* +* Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> +* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation; either version 2 of the License, or (at your +* option) any later version. +* +* This program is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along +* with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef CinematicMgr_h__ +#define CinematicMgr_h__ + +#include "Define.h" +#include "Object.h" +#include "M2Stores.h" + +#define CINEMATIC_LOOKAHEAD (2 * IN_MILLISECONDS) +#define CINEMATIC_UPDATEDIFF 500 + +class Player; + +class TC_GAME_API CinematicMgr +{ + friend class Player; +public: + explicit CinematicMgr(Player* playerref); + ~CinematicMgr(); + + // Cinematic camera data and remote sight functions + uint32 GetActiveCinematicCamera() const { return m_activeCinematicCameraId; } + void SetActiveCinematicCamera(uint32 cinematicCameraId = 0) { m_activeCinematicCameraId = cinematicCameraId; } + bool IsOnCinematic() const { return (m_cinematicCamera != nullptr); } + void BeginCinematic(); + void EndCinematic(); + void UpdateCinematicLocation(uint32 diff); + +private: + // Remote location information + Player* player; + +protected: + uint32 m_cinematicDiff; + uint32 m_lastCinematicCheck; + uint32 m_activeCinematicCameraId; + uint32 m_cinematicLength; + FlyByCameraCollection* m_cinematicCamera; + Position m_remoteSightPosition; + TempSummon* m_CinematicObject; +}; + +#endif
\ No newline at end of file diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index c58f2c940fc..ec86e8fe4c3 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -96,9 +96,6 @@ #define SKILL_PERM_BONUS(x) int16(PAIR32_HIPART(x)) #define MAKE_SKILL_BONUS(t, p) MAKE_PAIR32(t, p) -#define CINEMATIC_LOOKAHEAD (2 * IN_MILLISECONDS) -#define CINEMATIC_UPDATEDIFF 500 - enum CharacterFlags { CHARACTER_FLAG_NONE = 0x00000000, @@ -477,21 +474,11 @@ Player::Player(WorldSession* session): Unit(true) // Player summoning m_summon_expire = 0; - m_summon_mapid = 0; - m_summon_x = 0.0f; - m_summon_y = 0.0f; - m_summon_z = 0.0f; m_mover = this; m_movedPlayer = this; m_seer = this; - m_recallMap = 0; - m_recallX = 0; - m_recallY = 0; - m_recallZ = 0; - m_recallO = 0; - m_homebindMapId = 0; m_homebindAreaId = 0; m_homebindX = 0; @@ -539,12 +526,7 @@ Player::Player(WorldSession* session): Unit(true) healthBeforeDuel = 0; manaBeforeDuel = 0; - m_cinematicDiff = 0; - m_lastCinematicCheck = 0; - m_activeCinematicCameraId = 0; - m_cinematicCamera = nullptr; - m_remoteSightPosition = Position(0.0f, 0.0f, 0.0f); - m_CinematicObject = nullptr; + _cinematicMgr = new CinematicMgr(this); m_achievementMgr = new AchievementMgr(this); m_reputationMgr = new ReputationMgr(this); @@ -585,6 +567,7 @@ Player::~Player() delete m_runes; delete m_achievementMgr; delete m_reputationMgr; + delete _cinematicMgr; sWorld->DecreasePlayerCount(); } @@ -1236,11 +1219,11 @@ void Player::Update(uint32 p_time) } // Update cinematic location, if 500ms have passed and we're doing a cinematic now. - m_cinematicDiff += p_time; - if (m_cinematicCamera && m_activeCinematicCameraId && GetMSTimeDiffToNow(m_lastCinematicCheck) > CINEMATIC_UPDATEDIFF) + _cinematicMgr->m_cinematicDiff += p_time; + if (_cinematicMgr->m_cinematicCamera && _cinematicMgr->m_activeCinematicCameraId && GetMSTimeDiffToNow(_cinematicMgr->m_lastCinematicCheck) > CINEMATIC_UPDATEDIFF) { - m_lastCinematicCheck = getMSTime(); - UpdateCinematicLocation(p_time); + _cinematicMgr->m_lastCinematicCheck = getMSTime(); + _cinematicMgr->UpdateCinematicLocation(p_time); } //used to implement delayed far teleports @@ -1728,7 +1711,7 @@ bool Player::BuildEnumData(PreparedQueryResult result, WorldPacket* data) // Pets info uint32 petDisplayId = 0; uint32 petLevel = 0; - uint32 petFamily = 0; + CreatureFamily petFamily = CREATURE_FAMILY_NONE; // show pet at selection character in character list only for non-ghost character if (result && !(playerFlags & PLAYER_FLAGS_GHOST) && (plrClass == CLASS_WARLOCK || plrClass == CLASS_HUNTER || plrClass == CLASS_DEATH_KNIGHT)) @@ -2436,11 +2419,11 @@ Creature* Player::GetNPCIfCanInteractWith(ObjectGuid const& guid, uint32 npcflag return nullptr; // Deathstate checks - if (!IsAlive() && !(creature->GetCreatureTemplate()->type_flags & CREATURE_TYPEFLAGS_GHOST)) + if (!IsAlive() && !(creature->GetCreatureTemplate()->type_flags & CREATURE_TYPE_FLAG_GHOST_VISIBLE)) return nullptr; // alive or spirit healer - if (!creature->IsAlive() && !(creature->GetCreatureTemplate()->type_flags & CREATURE_TYPEFLAGS_DEAD_INTERACT)) + if (!creature->IsAlive() && !(creature->GetCreatureTemplate()->type_flags & CREATURE_TYPE_FLAG_CAN_INTERACT_WHILE_DEAD)) return nullptr; // appropriate npc type @@ -2811,6 +2794,8 @@ void Player::GiveLevel(uint8 level) if (sWorld->getBoolConfig(CONFIG_ALWAYS_MAXSKILL)) // Max weapon skill when leveling up UpdateSkillsToMaxSkillsForLevel(); + _ApplyAllLevelScaleItemMods(true); + // set current level health and mana/energy to maximum after applying all mods. SetFullHealth(); SetPower(POWER_MANA, GetMaxPower(POWER_MANA)); @@ -2820,8 +2805,6 @@ void Player::GiveLevel(uint8 level) SetPower(POWER_FOCUS, 0); SetPower(POWER_HAPPINESS, 0); - _ApplyAllLevelScaleItemMods(true); - // update level to hunter/summon pet if (Pet* pet = GetPet()) pet->SynchronizeLevelWithOwner(); @@ -3014,7 +2997,7 @@ void Player::InitStatsForLevel(bool reapplyMods) // cleanup unit flags (will be re-applied if need at aura load). RemoveFlag(UNIT_FIELD_FLAGS, - UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_NOT_ATTACKABLE_1 | + UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_REMOVE_CLIENT_CONTROL | UNIT_FLAG_NOT_ATTACKABLE_1 | UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC | UNIT_FLAG_LOOTING | UNIT_FLAG_PET_IN_COMBAT | UNIT_FLAG_SILENCED | UNIT_FLAG_PACIFIED | UNIT_FLAG_STUNNED | UNIT_FLAG_IN_COMBAT | UNIT_FLAG_DISARMED | @@ -3219,10 +3202,9 @@ bool Player::AddTalent(uint32 spellId, uint8 spec, bool learning) } } - PlayerSpellState state = learning ? PLAYERSPELL_NEW : PLAYERSPELL_UNCHANGED; PlayerTalent* newtalent = new PlayerTalent(); - newtalent->state = state; + newtalent->state = learning ? PLAYERSPELL_NEW : PLAYERSPELL_UNCHANGED; newtalent->spec = spec; (*m_talents[spec])[spellId] = newtalent; @@ -4958,6 +4940,9 @@ void Player::DurabilityPointsLossAll(int32 points, bool inventory) void Player::DurabilityPointsLoss(Item* item, int32 points) { + if (HasAuraType(SPELL_AURA_PREVENT_DURABILITY_LOSS)) + return; + int32 pMaxDurability = item->GetUInt32Value(ITEM_FIELD_MAXDURABILITY); int32 pOldDurability = item->GetUInt32Value(ITEM_FIELD_DURABILITY); int32 pNewDurability = pOldDurability - points; @@ -6374,15 +6359,6 @@ bool Player::UpdatePosition(float x, float y, float z, float orientation, bool t return true; } -void Player::SaveRecallPosition() -{ - m_recallMap = GetMapId(); - m_recallX = GetPositionX(); - m_recallY = GetPositionY(); - m_recallZ = GetPositionZ(); - m_recallO = GetOrientation(); -} - void Player::SendMessageToSetInRange(WorldPacket* data, float dist, bool self) { if (self) @@ -6417,13 +6393,13 @@ void Player::SendDirectMessage(WorldPacket const* data) const m_session->SendPacket(data); } -void Player::SendCinematicStart(uint32 CinematicSequenceId) +void Player::SendCinematicStart(uint32 CinematicSequenceId) const { WorldPacket data(SMSG_TRIGGER_CINEMATIC, 4); data << uint32(CinematicSequenceId); SendDirectMessage(&data); - if (const CinematicSequencesEntry* sequence = sCinematicSequencesStore.LookupEntry(CinematicSequenceId)) - SetActiveCinematicCamera(sequence->cinematicCamera); + if (CinematicSequencesEntry const* sequence = sCinematicSequencesStore.LookupEntry(CinematicSequenceId)) + _cinematicMgr->SetActiveCinematicCamera(sequence->cinematicCamera); } void Player::SendMovieStart(uint32 MovieId) const @@ -14862,12 +14838,8 @@ void Player::CompleteQuest(uint32 quest_id) SetQuestSlotState(log_slot, QUEST_STATE_COMPLETE); if (Quest const* qInfo = sObjectMgr->GetQuestTemplate(quest_id)) - { if (qInfo->HasFlag(QUEST_FLAGS_TRACKING)) RewardQuest(qInfo, 0, this, false); - else - SendQuestComplete(quest_id); - } } if (sWorld->getBoolConfig(CONFIG_QUEST_ENABLE_QUEST_TRACKER)) // check if Quest Tracker is enabled @@ -20328,6 +20300,11 @@ void Player::Say(std::string const& text, Language language, WorldObject const* SendMessageToSetInRange(&data, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_SAY), true); } +void Player::Say(uint32 textId, WorldObject const* target /*= nullptr*/) +{ + Talk(textId, CHAT_MSG_SAY, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_SAY), target); +} + void Player::Yell(std::string const& text, Language language, WorldObject const* /*= nullptr*/) { std::string _text(text); @@ -20338,6 +20315,11 @@ void Player::Yell(std::string const& text, Language language, WorldObject const* SendMessageToSetInRange(&data, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_YELL), true); } +void Player::Yell(uint32 textId, WorldObject const* target /*= nullptr*/) +{ + Talk(textId, CHAT_MSG_YELL, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_YELL), target); +} + void Player::TextEmote(std::string const& text, WorldObject const* /*= nullptr*/, bool /*= false*/) { std::string _text(text); @@ -20348,6 +20330,11 @@ void Player::TextEmote(std::string const& text, WorldObject const* /*= nullptr*/ SendMessageToSetInRange(&data, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE), true, !GetSession()->HasPermission(rbac::RBAC_PERM_TWO_SIDE_INTERACTION_CHAT)); } +void Player::TextEmote(uint32 textId, WorldObject const* target /*= nullptr*/, bool /*isBossEmote = false*/) +{ + Talk(textId, CHAT_MSG_EMOTE, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE), target); +} + void Player::Whisper(std::string const& text, Language language, Player* target, bool /*= false*/) { ASSERT(target); @@ -20384,6 +20371,24 @@ void Player::Whisper(std::string const& text, Language language, Player* target, ChatHandler(GetSession()).PSendSysMessage(LANG_PLAYER_DND, target->GetName().c_str(), target->autoReplyMsg.c_str()); } +void Player::Whisper(uint32 textId, Player* target, bool /*isBossWhisper = false*/) +{ + if (!target) + return; + + BroadcastText const* bct = sObjectMgr->GetBroadcastText(textId); + if (!bct) + { + TC_LOG_ERROR("entities.unit", "WorldObject::MonsterWhisper: `broadcast_text` was not %u found", textId); + return; + } + + LocaleConstant locale = target->GetSession()->GetSessionDbLocaleIndex(); + WorldPacket data; + ChatHandler::BuildChatPacket(data, CHAT_MSG_WHISPER, LANG_UNIVERSAL, this, target, bct->GetText(locale, getGender()), 0, "", locale); + target->SendDirectMessage(&data); +} + Item* Player::GetMItem(uint32 id) { ItemMap::const_iterator itr = mMitems.find(id); @@ -20502,7 +20507,7 @@ void Player::VehicleSpellInitialize() data << uint8(0); // Command State data << uint16(0x800); // DisableActions (set for all vehicles) - for (uint32 i = 0; i < CREATURE_MAX_SPELLS; ++i) + for (uint32 i = 0; i < MAX_CREATURE_SPELLS; ++i) { uint32 spellId = vehicle->m_spells[i]; SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); @@ -20526,7 +20531,7 @@ void Player::VehicleSpellInitialize() data << uint32(MAKE_UNIT_ACTION_BUTTON(spellId, i+8)); } - for (uint32 i = CREATURE_MAX_SPELLS; i < MAX_SPELL_CONTROL_BAR; ++i) + for (uint32 i = MAX_CREATURE_SPELLS; i < MAX_SPELL_CONTROL_BAR; ++i) data << uint32(0); data << uint8(0); // Auras? @@ -20934,7 +20939,7 @@ bool Player::ActivateTaxiPathTo(std::vector<uint32> const& nodes, Creature* npc return false; } - if (HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE)) + if (HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL)) return false; // taximaster case @@ -21133,7 +21138,7 @@ void Player::CleanupAfterTaxiFlight() { m_taxi.ClearTaxiDestinations(); // not destinations, clear source node Dismount(); - RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_TAXI_FLIGHT); + RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL | UNIT_FLAG_TAXI_FLIGHT); getHostileRefManager().setOnlineOfflineState(true); } @@ -23176,13 +23181,32 @@ void Player::UpdateForQuestWorldObjects() GetSession()->SendPacket(&packet); } -void Player::SetSummonPoint(uint32 mapid, float x, float y, float z) +bool Player::HasSummonPending() const +{ + return m_summon_expire >= time(nullptr); +} + +void Player::SendSummonRequestFrom(Unit* summoner) { + if (!summoner) + return; + + // Player already has active summon request + if (HasSummonPending()) + return; + + // Evil Twin (ignore player summon, but hide this for summoner) + if (HasAura(23445)) + return; + m_summon_expire = time(nullptr) + MAX_PLAYER_SUMMON_DELAY; - m_summon_mapid = mapid; - m_summon_x = x; - m_summon_y = y; - m_summon_z = z; + m_summon_location.WorldRelocate(*summoner); + + WorldPacket data(SMSG_SUMMON_REQUEST, 8 + 4 + 4); + data << uint64(summoner->GetGUID()); // summoner guid + data << uint32(summoner->GetZoneId()); // summoner zone + data << uint32(MAX_PLAYER_SUMMON_DELAY*IN_MILLISECONDS); // auto decline after msecs + GetSession()->SendPacket(&data); } void Player::SummonIfPossible(bool agree) @@ -23213,7 +23237,7 @@ void Player::SummonIfPossible(bool agree) UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_ACCEPTED_SUMMONINGS, 1); - TeleportTo(m_summon_mapid, m_summon_x, m_summon_y, m_summon_z, GetOrientation()); + TeleportTo(m_summon_location); } void Player::RemoveItemDurations(Item* item) @@ -26210,125 +26234,6 @@ float Player::GetCollisionHeight(bool mounted) const } } -void Player::BeginCinematic() -{ - // Sanity check for active camera set - if (m_activeCinematicCameraId == 0) - return; - - auto itr = sFlyByCameraStore.find(m_activeCinematicCameraId); - if (itr != sFlyByCameraStore.end()) - { - // Initialize diff, and set camera - m_cinematicDiff = 0; - m_cinematicCamera = &itr->second; - - auto camitr = m_cinematicCamera->begin(); - if (camitr != m_cinematicCamera->end()) - { - Position pos(camitr->locations.x, camitr->locations.y, camitr->locations.z, camitr->locations.w); - if (!pos.IsPositionValid()) - return; - - m_mapRef->LoadGrid(camitr->locations.x, camitr->locations.y); - m_CinematicObject = SummonCreature(VISUAL_WAYPOINT, pos.m_positionX, pos.m_positionY, pos.m_positionZ, 0.0f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 120000); - if (m_CinematicObject) - { - m_CinematicObject->setActive(true); - SetViewpoint(m_CinematicObject, true); - } - } - } -} - -void Player::EndCinematic() -{ - m_cinematicDiff = 0; - m_cinematicCamera = nullptr; - m_activeCinematicCameraId = 0; - if (m_CinematicObject) - { - if (m_seer && m_seer == m_CinematicObject) - SetViewpoint(m_CinematicObject, false); - m_CinematicObject->AddObjectToRemoveList(); - } -} - -void Player::UpdateCinematicLocation(uint32 /*diff*/) -{ - Position lastPosition; - uint32 lastTimestamp = 0; - Position nextPosition; - uint32 nextTimestamp = 0; - - if (m_cinematicCamera->size() == 0) - return; - - // Obtain direction of travel - for (FlyByCamera cam : *m_cinematicCamera) - { - if (cam.timeStamp > m_cinematicDiff) - { - nextPosition = Position(cam.locations.x, cam.locations.y, cam.locations.z, cam.locations.w); - nextTimestamp = cam.timeStamp; - break; - } - lastPosition = Position(cam.locations.x, cam.locations.y, cam.locations.z, cam.locations.w); - lastTimestamp = cam.timeStamp; - } - float angle = lastPosition.GetAngle(&nextPosition); - angle -= lastPosition.GetOrientation(); - if (angle < 0) - angle += 2 * float(M_PI); - - // Look for position around 2 second ahead of us. - int32 workDiff = m_cinematicDiff; - - // Modify result based on camera direction (Humans for example, have the camera point behind) - workDiff += static_cast<int32>(float(CINEMATIC_LOOKAHEAD) * cos(angle)); - - // Get an iterator to the last entry in the cameras, to make sure we don't go beyond the end - FlyByCameraCollection::const_reverse_iterator endItr = m_cinematicCamera->rbegin(); - if (endItr != m_cinematicCamera->rend() && workDiff > static_cast<int32>(endItr->timeStamp)) - workDiff = endItr->timeStamp; - - // Never try to go back in time before the start of cinematic! - if (workDiff < 0) - workDiff = m_cinematicDiff; - - // Obtain the previous and next waypoint based on timestamp - for (FlyByCamera cam : *m_cinematicCamera) - { - if (static_cast<int32>(cam.timeStamp) >= workDiff) - { - nextPosition = Position(cam.locations.x, cam.locations.y, cam.locations.z, cam.locations.w); - nextTimestamp = cam.timeStamp; - break; - } - lastPosition = Position(cam.locations.x, cam.locations.y, cam.locations.z, cam.locations.w); - lastTimestamp = cam.timeStamp; - } - - // Never try to go beyond the end of the cinematic - if (workDiff > static_cast<int32>(nextTimestamp)) - workDiff = static_cast<int32>(nextTimestamp); - - // Interpolate the position for this moment in time (or the adjusted moment in time) - uint32 timeDiff = nextTimestamp - lastTimestamp; - uint32 interDiff = workDiff - lastTimestamp; - float xDiff = nextPosition.m_positionX - lastPosition.m_positionX; - float yDiff = nextPosition.m_positionY - lastPosition.m_positionY; - float zDiff = nextPosition.m_positionZ - lastPosition.m_positionZ; - Position interPosition(lastPosition.m_positionX + (xDiff * (float(interDiff)/float(timeDiff))), lastPosition.m_positionY + - (yDiff * (float(interDiff) / float(timeDiff))), lastPosition.m_positionZ + (zDiff * (float(interDiff) / float(timeDiff)))); - - // Advance (at speed) to this position. The remote sight object is used - // to send update information to player in cinematic - if (m_CinematicObject && interPosition.IsPositionValid()) - m_CinematicObject->MonsterMoveWithSpeed(interPosition.m_positionX, interPosition.m_positionY, interPosition.m_positionZ, 200.0f, false, true); -} - - std::string Player::GetMapAreaAndZoneString() const { uint32 areaId = GetAreaId(); @@ -26561,3 +26466,22 @@ void Player::RemoveRestFlag(RestFlag restFlag) RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING); } } + +uint32 Player::DoRandomRoll(uint32 minimum, uint32 maximum) +{ + ASSERT(maximum <= 10000); + + uint32 roll = urand(minimum, maximum); + + WorldPacket data(MSG_RANDOM_ROLL, 4 + 4 + 4 + 8); + data << uint32(minimum); + data << uint32(maximum); + data << uint32(roll); + data << GetGUID(); + if (Group* group = GetGroup()) + group->BroadcastPacket(&data, false); + else + SendDirectMessage(&data); + + return roll; +} diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index fd0fac69674..6a38cd3b9fe 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -30,6 +30,7 @@ #include "SpellHistory.h" #include "Unit.h" #include "TradeData.h" +#include "CinematicMgr.h" #include <limits> #include <string> @@ -1026,6 +1027,7 @@ struct ResurrectionData class TC_GAME_API Player : public Unit, public GridObject<Player> { friend class WorldSession; + friend class CinematicMgr; friend void Item::AddToUpdateQueueOf(Player* player); friend void Item::RemoveFromUpdateQueueOf(Player* player); public: @@ -1050,7 +1052,8 @@ class TC_GAME_API Player : public Unit, public GridObject<Player> bool TeleportTo(WorldLocation const &loc, uint32 options = 0); bool TeleportToBGEntryPoint(); - void SetSummonPoint(uint32 mapid, float x, float y, float z); + bool HasSummonPending() const; + void SendSummonRequestFrom(Unit* summoner); void SummonIfPossible(bool agree); bool Create(ObjectGuid::LowType guidlow, CharacterCreateInfo* createInfo); @@ -1148,12 +1151,16 @@ class TC_GAME_API Player : public Unit, public GridObject<Player> /// Handles said message in regular chat based on declared language and in config pre-defined Range. void Say(std::string const& text, Language language, WorldObject const* = nullptr) override; + void Say(uint32 textId, WorldObject const* target = nullptr) override; /// Handles yelled message in regular chat based on declared language and in config pre-defined Range. void Yell(std::string const& text, Language language, WorldObject const* = nullptr) override; + void Yell(uint32 textId, WorldObject const* target = nullptr) override; /// Outputs an universal text which is supposed to be an action. void TextEmote(std::string const& text, WorldObject const* = nullptr, bool = false) override; + void TextEmote(uint32 textId, WorldObject const* target = nullptr, bool isBossEmote = false) override; /// Handles whispers from Addons and players based on sender, receiver's guid and language. void Whisper(std::string const& text, Language language, Player* receiver, bool = false) override; + void Whisper(uint32 textId, Player* target, bool isBossWhisper = false) override; /*********************************************************/ /*** STORAGE SYSTEM ***/ @@ -1269,6 +1276,8 @@ class TC_GAME_API Player : public Unit, public GridObject<Player> TradeData* GetTradeData() const { return m_trade; } void TradeCancel(bool sendback); + CinematicMgr* GetCinematicMgr() const { return _cinematicMgr; } + void UpdateEnchantTime(uint32 time); void UpdateSoulboundTradeItems(); void AddTradeableItem(Item* item); @@ -1587,7 +1596,8 @@ class TC_GAME_API Player : public Unit, public GridObject<Player> void AddSpellMod(SpellModifier* mod, bool apply); bool IsAffectedBySpellmod(SpellInfo const* spellInfo, SpellModifier* mod, Spell* spell = nullptr) const; - template <class T> T ApplySpellMod(uint32 spellId, SpellModOp op, T &basevalue, Spell* spell = nullptr); + template <class T> + void ApplySpellMod(uint32 spellId, SpellModOp op, T& basevalue, Spell* spell = nullptr); void RemoveSpellMods(Spell* spell); void RestoreSpellMods(Spell* spell, uint32 ownerAuraId = 0, Aura* aura = nullptr); void RestoreAllSpellMods(uint32 ownerAuraId = 0, Aura* aura = nullptr); @@ -2073,13 +2083,8 @@ class TC_GAME_API Player : public Unit, public GridObject<Player> uint32 GetSaveTimer() const { return m_nextSave; } void SetSaveTimer(uint32 timer) { m_nextSave = timer; } - // Recall position - uint32 m_recallMap; - float m_recallX; - float m_recallY; - float m_recallZ; - float m_recallO; - void SaveRecallPosition(); + void SaveRecallPosition() { m_recall_location.WorldRelocate(*this); } + void Recall() { TeleportTo(m_recall_location); } void SetHomebind(WorldLocation const& loc, uint32 areaId); @@ -2129,9 +2134,11 @@ class TC_GAME_API Player : public Unit, public GridObject<Player> void ResummonPetTemporaryUnSummonedIfAny(); bool IsPetNeedBeTemporaryUnsummoned() const; - void SendCinematicStart(uint32 CinematicSequenceId); + void SendCinematicStart(uint32 CinematicSequenceId) const; void SendMovieStart(uint32 MovieId) const; + uint32 DoRandomRoll(uint32 minimum, uint32 maximum); + /*********************************************************/ /*** INSTANCE SYSTEM ***/ /*********************************************************/ @@ -2265,17 +2272,6 @@ class TC_GAME_API Player : public Unit, public GridObject<Player> std::string GetMapAreaAndZoneString() const; std::string GetCoordsMapAreaAndZoneString() const; - // Cinematic camera data and remote sight functions - uint32 GetActiveCinematicCamera() const { return m_activeCinematicCameraId; } - void SetActiveCinematicCamera(uint32 cinematicCameraId = 0) { m_activeCinematicCameraId = cinematicCameraId; } - bool IsOnCinematic() const { return (m_cinematicCamera != nullptr); } - void BeginCinematic(); - void EndCinematic(); - void UpdateCinematicLocation(uint32 diff); - - std::string GetMapAreaAndZoneString(); - std::string GetCoordsMapAreaAndZoneString(); - protected: // Gamemaster whisper whitelist GuidList WhisperList; @@ -2510,10 +2506,10 @@ class TC_GAME_API Player : public Unit, public GridObject<Player> // Player summoning time_t m_summon_expire; - uint32 m_summon_mapid; - float m_summon_x; - float m_summon_y; - float m_summon_z; + WorldLocation m_summon_location; + + // Recall position + WorldLocation m_recall_location; DeclinedName *m_declinedname; Runes *m_runes; @@ -2535,6 +2531,8 @@ class TC_GAME_API Player : public Unit, public GridObject<Player> Item* _StoreItem(uint16 pos, Item* pItem, uint32 count, bool clone, bool update); Item* _LoadItem(SQLTransaction& trans, uint32 zoneId, uint32 timeDiff, Field* fields); + CinematicMgr* _cinematicMgr; + GuidSet m_refundableItems; void SendRefundInfo(Item* item); void RefundItem(Item* item); @@ -2601,25 +2599,19 @@ class TC_GAME_API Player : public Unit, public GridObject<Player> uint32 manaBeforeDuel; WorldLocation _corpseLocation; - - // Remote location information - uint32 m_cinematicDiff; - uint32 m_lastCinematicCheck; - uint32 m_activeCinematicCameraId; - FlyByCameraCollection* m_cinematicCamera; - Position m_remoteSightPosition; - Creature* m_CinematicObject; }; TC_GAME_API void AddItemsSetItem(Player* player, Item* item); TC_GAME_API void RemoveItemsSetItem(Player* player, ItemTemplate const* proto); // "the bodies of template functions must be made available in a header file" -template <class T> T Player::ApplySpellMod(uint32 spellId, SpellModOp op, T &basevalue, Spell* spell) +template <class T> +void Player::ApplySpellMod(uint32 spellId, SpellModOp op, T& basevalue, Spell* spell /*= nullptr*/) { SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); if (!spellInfo) - return 0; + return; + float totalmul = 1.0f; int32 totalflat = 0; @@ -2655,9 +2647,8 @@ template <class T> T Player::ApplySpellMod(uint32 spellId, SpellModOp op, T &bas DropModCharge(mod, spell); } - float diff = (float)basevalue * (totalmul - 1.0f) + (float)totalflat; - basevalue = T((float)basevalue + diff); - return T(diff); + + basevalue = T(float(basevalue + totalflat) * totalmul); } #endif diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index ee8a0b093e7..2aa32374087 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -578,7 +578,7 @@ bool Unit::HasBreakableByDamageCrowdControlAura(Unit* excludeCasterChannel) cons void Unit::DealDamageMods(Unit* victim, uint32 &damage, uint32* absorb) { - if (!victim || !victim->IsAlive() || victim->HasUnitState(UNIT_STATE_IN_FLIGHT) || (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsInEvadeMode())) + if (!victim || !victim->IsAlive() || victim->HasUnitState(UNIT_STATE_IN_FLIGHT) || (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsEvadingAttacks())) { if (absorb) *absorb += damage; @@ -599,11 +599,14 @@ uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDam if (victim->GetTypeId() == TYPEID_PLAYER && this != victim) { - // Signal to pets that their owner was attacked - Pet* pet = victim->ToPlayer()->GetPet(); + // Signal to pets that their owner was attacked - except when DOT. + if (damagetype != DOT) + { + Pet* pet = victim->ToPlayer()->GetPet(); - if (pet && pet->IsAlive()) - pet->AI()->OwnerAttackedBy(this); + if (pet && pet->IsAlive()) + pet->AI()->OwnerAttackedBy(this); + } if (victim->ToPlayer()->GetCommandStatus(CHEAT_GOD)) return 0; @@ -1120,7 +1123,7 @@ void Unit::DealSpellDamage(SpellNonMeleeDamage* damageInfo, bool durabilityLoss) if (!victim) return; - if (!victim->IsAlive() || victim->HasUnitState(UNIT_STATE_IN_FLIGHT) || (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsInEvadeMode())) + if (!victim->IsAlive() || victim->HasUnitState(UNIT_STATE_IN_FLIGHT) || (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsEvadingAttacks())) return; SpellInfo const* spellProto = sSpellMgr->GetSpellInfo(damageInfo->SpellID); @@ -1346,7 +1349,7 @@ void Unit::DealMeleeDamage(CalcDamageInfo* damageInfo, bool durabilityLoss) { Unit* victim = damageInfo->target; - if (!victim->IsAlive() || victim->HasUnitState(UNIT_STATE_IN_FLIGHT) || (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsInEvadeMode())) + if (!victim->IsAlive() || victim->HasUnitState(UNIT_STATE_IN_FLIGHT) || (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsEvadingAttacks())) return; // Hmmmm dont like this emotes client must by self do all animations @@ -2044,7 +2047,7 @@ MeleeHitOutcome Unit::RollMeleeOutcomeAgainst(const Unit* victim, WeaponAttackTy MeleeHitOutcome Unit::RollMeleeOutcomeAgainst (const Unit* victim, WeaponAttackType attType, int32 crit_chance, int32 miss_chance, int32 dodge_chance, int32 parry_chance, int32 block_chance) const { - if (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsInEvadeMode()) + if (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsEvadingAttacks()) return MELEE_HIT_EVADE; int32 attackerMaxSkillValueForLevel = GetMaxSkillValueForLevel(victim); @@ -2656,7 +2659,7 @@ SpellMissInfo Unit::SpellHitResult(Unit* victim, SpellInfo const* spellInfo, boo return SPELL_MISS_NONE; // Return evade for units in evade mode - if (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsInEvadeMode()) + if (victim->GetTypeId() == TYPEID_UNIT && victim->ToCreature()->IsEvadingAttacks()) return SPELL_MISS_EVADE; // Try victim reflect spell @@ -3189,6 +3192,15 @@ int32 Unit::GetCurrentSpellCastTime(uint32 spell_id) const return 0; } +bool Unit::CanMoveDuringChannel() const +{ + if (Spell* spell = m_currentSpells[CURRENT_CHANNELED_SPELL]) + if (spell->getState() != SPELL_STATE_FINISHED) + return spell->GetSpellInfo()->HasAttribute(SPELL_ATTR5_CAN_CHANNEL_WHEN_MOVING) && spell->IsChannelActive(); + + return false; +} + bool Unit::isInFrontInMap(Unit const* target, float distance, float arc) const { return IsWithinDistInMap(target, distance) && HasInArc(arc, target); @@ -4185,6 +4197,16 @@ void Unit::RemoveArenaAuras() } } +void Unit::RemoveAurasOnEvade() +{ + if (IsCharmedOwnedByPlayerOrPlayer()) // if it is a player owned creature it should not remove the aura + return; + + // don't remove vehicle auras, passengers aren't supposed to drop off the vehicle + // don't remove clone caster on evade (to be verified) + RemoveAllAurasExceptType(SPELL_AURA_CONTROL_VEHICLE, SPELL_AURA_CLONE_CASTER); +} + void Unit::RemoveAllAurasOnDeath() { // used just after dieing to remove all visible auras @@ -5277,7 +5299,7 @@ void Unit::SendAttackStateUpdate(uint32 HitInfo, Unit* target, uint8 /*SwingType } //victim may be NULL -bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown) +bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx, Milliseconds& cooldown) { SpellInfo const* dummySpell = triggeredByAura->GetSpellInfo(); uint32 effIndex = triggeredByAura->GetEffIndex(); @@ -5287,8 +5309,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere ? ToPlayer()->GetItemByGuid(triggeredByAura->GetBase()->GetCastItemGUID()) : NULL; uint32 triggered_spell_id = 0; - uint32 cooldown_spell_id = 0; // for random trigger, will be one of the triggered spell to avoid repeatable triggers - // otherwise, it's the triggered_spell_id by default Unit* target = victim; int32 basepoints0 = 0; ObjectGuid originalCaster; @@ -5364,24 +5384,20 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere case CLASS_PALADIN: // 39511, 40997, 40998, 40999, 41002, 41005, 41009, 41011, 41409 case CLASS_DRUID: // 39511, 40997, 40998, 40999, 41002, 41005, 41009, 41011, 41409 triggered_spell_id = RAND(39511, 40997, 40998, 40999, 41002, 41005, 41009, 41011, 41409); - cooldown_spell_id = 39511; break; case CLASS_ROGUE: // 39511, 40997, 40998, 41002, 41005, 41011 case CLASS_WARRIOR: // 39511, 40997, 40998, 41002, 41005, 41011 case CLASS_DEATH_KNIGHT: triggered_spell_id = RAND(39511, 40997, 40998, 41002, 41005, 41011); - cooldown_spell_id = 39511; break; case CLASS_PRIEST: // 40999, 41002, 41005, 41009, 41011, 41406, 41409 case CLASS_SHAMAN: // 40999, 41002, 41005, 41009, 41011, 41406, 41409 case CLASS_MAGE: // 40999, 41002, 41005, 41009, 41011, 41406, 41409 case CLASS_WARLOCK: // 40999, 41002, 41005, 41009, 41011, 41406, 41409 triggered_spell_id = RAND(40999, 41002, 41005, 41009, 41011, 41406, 41409); - cooldown_spell_id = 40999; break; case CLASS_HUNTER: // 40997, 40999, 41002, 41005, 41009, 41011, 41406, 41409 triggered_spell_id = RAND(40997, 40999, 41002, 41005, 41009, 41011, 41406, 41409); - cooldown_spell_id = 40997; break; default: return false; @@ -5611,11 +5627,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere uint8 rand_spell = urand(0, (RandomSpells.size() - 1)); CastSpell(target, RandomSpells[rand_spell], true, castItem, triggeredByAura, originalCaster); - for (std::vector<uint32>::iterator itr = RandomSpells.begin(); itr != RandomSpells.end(); ++itr) - { - if (!GetSpellHistory()->HasCooldown(*itr)) - GetSpellHistory()->AddCooldown(*itr, 0, std::chrono::seconds(cooldown)); - } break; } case 71562: // Deathbringer's Will Heroic @@ -5657,11 +5668,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere uint8 rand_spell = urand(0, (RandomSpells.size() - 1)); CastSpell(target, RandomSpells[rand_spell], true, castItem, triggeredByAura, originalCaster); - for (std::vector<uint32>::iterator itr = RandomSpells.begin(); itr != RandomSpells.end(); ++itr) - { - if (!GetSpellHistory()->HasCooldown(*itr)) - GetSpellHistory()->AddCooldown(*itr, 0, std::chrono::seconds(cooldown)); - } break; } case 65032: // Boom aura (321 Boombot) @@ -6299,24 +6305,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere return true; } } - // Eclipse - if (dummySpell->SpellIconID == 2856 && GetTypeId() == TYPEID_PLAYER) - { - if (!procSpell || effIndex != 0) - return false; - - bool isWrathSpell = (procSpell->SpellFamilyFlags[0] & 1); - - if (!roll_chance_f(dummySpell->ProcChance * (isWrathSpell ? 0.6f : 1.0f))) - return false; - - target = this; - if (target->HasAura(isWrathSpell ? 48517 : 48518)) - return false; - - triggered_spell_id = isWrathSpell ? 48518 : 48517; - break; - } break; } case SPELLFAMILY_ROGUE: @@ -6497,7 +6485,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere // Item - Paladin T8 Holy 4P Bonus if (Unit* caster = triggeredByAura->GetCaster()) if (AuraEffect const* aurEff = caster->GetAuraEffect(64895, 0)) - cooldown = aurEff->GetAmount(); + cooldown = Milliseconds(aurEff->GetAmount()); target = this; break; @@ -6812,10 +6800,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere if (!player || !castItem || !castItem->IsEquipped() || !victim || !victim->IsAlive()) return false; - // custom cooldown processing case - if (cooldown && GetSpellHistory()->HasCooldown(dummySpell->Id)) - return false; - if (triggeredByAura->GetBase() && castItem->GetGUID() != triggeredByAura->GetBase()->GetCastItemGUID()) return false; @@ -6878,8 +6862,8 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere triggered_spell_id = 33750; // apply cooldown before cast to prevent processing itself - if (cooldown) - player->GetSpellHistory()->AddCooldown(dummySpell->Id, 0, std::chrono::seconds(cooldown)); + triggeredByAura->GetBase()->AddProcCooldown(std::chrono::steady_clock::now() + cooldown); + cooldown = Milliseconds::zero(); // Attack Twice for (uint32 i = 0; i < 2; ++i) @@ -7122,10 +7106,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere if (!procSpell || GetTypeId() != TYPEID_PLAYER || !victim) return false; - // custom cooldown processing case - if (cooldown && GetTypeId() == TYPEID_PLAYER && GetSpellHistory()->HasCooldown(dummySpell->Id)) - return false; - uint32 spellId = 0; // Every Lightning Bolt and Chain Lightning spell have duplicate vs half damage and zero cost switch (procSpell->Id) @@ -7171,10 +7151,6 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere } CastSpell(victim, spellId, true, castItem, triggeredByAura); - - if (cooldown && GetTypeId() == TYPEID_PLAYER) - GetSpellHistory()->AddCooldown(dummySpell->Id, 0, std::chrono::seconds(cooldown)); - return true; } // Static Shock @@ -7476,26 +7452,17 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere return false; } - if (cooldown_spell_id == 0) - cooldown_spell_id = triggered_spell_id; - - if (cooldown && GetTypeId() == TYPEID_PLAYER && GetSpellHistory()->HasCooldown(cooldown_spell_id)) - return false; - if (basepoints0) CastCustomSpell(target, triggered_spell_id, &basepoints0, NULL, NULL, true, castItem, triggeredByAura, originalCaster); else CastSpell(target, triggered_spell_id, true, castItem, triggeredByAura, originalCaster); - if (cooldown && GetTypeId() == TYPEID_PLAYER) - GetSpellHistory()->AddCooldown(cooldown_spell_id, 0, std::chrono::seconds(cooldown)); - return true; } // Used in case when access to whole aura is needed // All procs should be handled like this... -bool Unit::HandleAuraProc(Unit* victim, uint32 damage, Aura* triggeredByAura, SpellInfo const* procSpell, uint32 /*procFlag*/, uint32 procEx, uint32 cooldown, bool * handled) +bool Unit::HandleAuraProc(Unit* victim, uint32 damage, Aura* triggeredByAura, SpellInfo const* procSpell, uint32 /*procFlag*/, uint32 procEx, bool* handled) { SpellInfo const* dummySpell = triggeredByAura->GetSpellInfo(); @@ -7707,12 +7674,6 @@ bool Unit::HandleAuraProc(Unit* victim, uint32 damage, Aura* triggeredByAura, Sp case 49222: { *handled = true; - if (cooldown && GetTypeId() == TYPEID_PLAYER) - { - if (GetSpellHistory()->HasCooldown(100000)) - return false; - GetSpellHistory()->AddCooldown(100000, 0, std::chrono::seconds(cooldown)); - } return true; } // Hungering Cold aura drop @@ -7755,7 +7716,7 @@ bool Unit::HandleAuraProc(Unit* victim, uint32 damage, Aura* triggeredByAura, Sp return false; } -bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 procFlags, uint32 procEx, uint32 cooldown) +bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx) { // Get triggered aura spell info SpellInfo const* auraSpellInfo = triggeredByAura->GetSpellInfo(); @@ -7781,91 +7742,6 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg { switch (auraSpellInfo->SpellFamilyName) { - case SPELLFAMILY_GENERIC: - switch (auraSpellInfo->Id) - { - case 43820: // Charm of the Witch Doctor (Amani Charm of the Witch Doctor trinket) - // Pct value stored in dummy - basepoints0 = victim->GetCreateHealth() * auraSpellInfo->Effects[1].CalcValue() / 100; - target = victim; - break; - case 57345: // Darkmoon Card: Greatness - { - float stat = 0.0f; - // strength - if (GetStat(STAT_STRENGTH) > stat) { trigger_spell_id = 60229;stat = GetStat(STAT_STRENGTH); } - // agility - if (GetStat(STAT_AGILITY) > stat) { trigger_spell_id = 60233;stat = GetStat(STAT_AGILITY); } - // intellect - if (GetStat(STAT_INTELLECT)> stat) { trigger_spell_id = 60234;stat = GetStat(STAT_INTELLECT);} - // spirit - if (GetStat(STAT_SPIRIT) > stat) { trigger_spell_id = 60235; } - break; - } - case 64568: // Blood Reserve - { - if (HealthBelowPctDamaged(35, damage)) - { - CastCustomSpell(this, 64569, &triggerAmount, NULL, NULL, true); - RemoveAura(64568); - } - return false; - } - case 67702: // Death's Choice, Item - Coliseum 25 Normal Melee Trinket - { - float stat = 0.0f; - // strength - if (GetStat(STAT_STRENGTH) > stat) { trigger_spell_id = 67708;stat = GetStat(STAT_STRENGTH); } - // agility - if (GetStat(STAT_AGILITY) > stat) { trigger_spell_id = 67703; } - break; - } - case 67771: // Death's Choice (heroic), Item - Coliseum 25 Heroic Melee Trinket - { - float stat = 0.0f; - // strength - if (GetStat(STAT_STRENGTH) > stat) { trigger_spell_id = 67773;stat = GetStat(STAT_STRENGTH); } - // agility - if (GetStat(STAT_AGILITY) > stat) { trigger_spell_id = 67772; } - break; - } - // Mana Drain Trigger - case 27522: - case 40336: - { - // On successful melee or ranged attack gain $29471s1 mana and if possible drain $27526s1 mana from the target. - if (IsAlive()) - CastSpell(this, 29471, true, castItem, triggeredByAura); - if (victim && victim->IsAlive()) - CastSpell(victim, 27526, true, castItem, triggeredByAura); - return true; - } - // Evasive Maneuvers - case 50240: - { - // Remove a Evasive Charge - Aura* charge = GetAura(50241); - if (charge && charge->ModStackAmount(-1, AURA_REMOVE_BY_ENEMY_SPELL)) - RemoveAurasDueToSpell(50240); - break; - } - } - break; - case SPELLFAMILY_MAGE: - if (auraSpellInfo->SpellIconID == 2127) // Blazing Speed - { - switch (auraSpellInfo->Id) - { - case 31641: // Rank 1 - case 31642: // Rank 2 - trigger_spell_id = 31643; - break; - default: - TC_LOG_ERROR("entities.unit", "Unit::HandleProcTriggerSpell: Spell %u miss posibly Blazing Speed", auraSpellInfo->Id); - return false; - } - } - break; case SPELLFAMILY_WARLOCK: { // Drain Soul @@ -7888,325 +7764,6 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg // Need for correct work Drain Soul SPELL_AURA_CHANNEL_DEATH_ITEM aura return false; } - // Nether Protection - else if (auraSpellInfo->SpellIconID == 1985) - { - if (!procSpell) - return false; - switch (GetFirstSchoolInMask(procSpell->GetSchoolMask())) - { - case SPELL_SCHOOL_NORMAL: - return false; // ignore - case SPELL_SCHOOL_HOLY: trigger_spell_id = 54370; break; - case SPELL_SCHOOL_FIRE: trigger_spell_id = 54371; break; - case SPELL_SCHOOL_NATURE: trigger_spell_id = 54375; break; - case SPELL_SCHOOL_FROST: trigger_spell_id = 54372; break; - case SPELL_SCHOOL_SHADOW: trigger_spell_id = 54374; break; - case SPELL_SCHOOL_ARCANE: trigger_spell_id = 54373; break; - default: - return false; - } - } - break; - } - case SPELLFAMILY_PRIEST: - { - // Blessed Recovery - if (auraSpellInfo->SpellIconID == 1875) - { - switch (auraSpellInfo->Id) - { - case 27811: trigger_spell_id = 27813; break; - case 27815: trigger_spell_id = 27817; break; - case 27816: trigger_spell_id = 27818; break; - default: - TC_LOG_ERROR("entities.unit", "Unit::HandleProcTriggerSpell: Spell %u not handled in BR", auraSpellInfo->Id); - return false; - } - basepoints0 = CalculatePct(int32(damage), triggerAmount) / 3; - target = this; - // Add remaining ticks to healing done - basepoints0 += GetRemainingPeriodicAmount(GetGUID(), trigger_spell_id, SPELL_AURA_PERIODIC_HEAL); - } - break; - } - case SPELLFAMILY_DRUID: - { - switch (auraSpellInfo->Id) - { - // Druid Forms Trinket - case 37336: - { - switch (GetShapeshiftForm()) - { - case FORM_NONE: trigger_spell_id = 37344; break; - case FORM_CAT: trigger_spell_id = 37341; break; - case FORM_BEAR: - case FORM_DIREBEAR: trigger_spell_id = 37340; break; - case FORM_TREE: trigger_spell_id = 37342; break; - case FORM_MOONKIN: trigger_spell_id = 37343; break; - default: - return false; - } - break; - } - // Druid T9 Feral Relic (Lacerate, Swipe, Mangle, and Shred) - case 67353: - { - switch (GetShapeshiftForm()) - { - case FORM_CAT: trigger_spell_id = 67355; break; - case FORM_BEAR: - case FORM_DIREBEAR: trigger_spell_id = 67354; break; - default: - return false; - } - break; - } - default: - break; - } - break; - } - case SPELLFAMILY_HUNTER: - { - if (auraSpellInfo->SpellIconID == 3247) // Piercing Shots - { - switch (auraSpellInfo->Id) - { - case 53234: // Rank 1 - case 53237: // Rank 2 - case 53238: // Rank 3 - trigger_spell_id = 63468; - break; - default: - TC_LOG_ERROR("entities.unit", "Unit::HandleProcTriggerSpell: Spell %u miss posibly Piercing Shots", auraSpellInfo->Id); - return false; - } - SpellInfo const* TriggerPS = sSpellMgr->GetSpellInfo(trigger_spell_id); - if (!TriggerPS) - return false; - - basepoints0 = CalculatePct(int32(damage), triggerAmount) / (TriggerPS->GetMaxDuration() / TriggerPS->Effects[0].Amplitude); - basepoints0 += victim->GetRemainingPeriodicAmount(GetGUID(), trigger_spell_id, SPELL_AURA_PERIODIC_DAMAGE); - break; - } - // Item - Hunter T9 4P Bonus - if (auraSpellInfo->Id == 67151) - { - trigger_spell_id = 68130; - target = this; - break; - } - break; - } - case SPELLFAMILY_PALADIN: - { - switch (auraSpellInfo->Id) - { - // Soul Preserver - case 60510: - { - switch (getClass()) - { - case CLASS_DRUID: - trigger_spell_id = 60512; - break; - case CLASS_PALADIN: - trigger_spell_id = 60513; - break; - case CLASS_PRIEST: - trigger_spell_id = 60514; - break; - case CLASS_SHAMAN: - trigger_spell_id = 60515; - break; - } - - target = this; - break; - } - case 37657: // Lightning Capacitor - case 54841: // Thunder Capacitor - case 67712: // Item - Coliseum 25 Normal Caster Trinket - case 67758: // Item - Coliseum 25 Heroic Caster Trinket - { - if (!victim || !victim->IsAlive() || GetTypeId() != TYPEID_PLAYER) - return false; - - uint32 stack_spell_id = 0; - switch (auraSpellInfo->Id) - { - case 37657: - stack_spell_id = 37658; - trigger_spell_id = 37661; - break; - case 54841: - stack_spell_id = 54842; - trigger_spell_id = 54843; - break; - case 67712: - stack_spell_id = 67713; - trigger_spell_id = 67714; - break; - case 67758: - stack_spell_id = 67759; - trigger_spell_id = 67760; - break; - } - - CastSpell(this, stack_spell_id, true, NULL, triggeredByAura); - - Aura* dummy = GetAura(stack_spell_id); - if (!dummy || dummy->GetStackAmount() < triggerAmount) - return false; - - RemoveAurasDueToSpell(stack_spell_id); - target = victim; - break; - } - default: - // Illumination - if (auraSpellInfo->SpellIconID == 241) - { - if (!procSpell) - return false; - // procspell is triggered spell but we need mana cost of original cast spell - uint32 originalSpellId = procSpell->Id; - // Holy Shock heal - if (procSpell->SpellFamilyFlags[1] & 0x00010000) - { - switch (procSpell->Id) - { - case 25914: originalSpellId = 20473; break; - case 25913: originalSpellId = 20929; break; - case 25903: originalSpellId = 20930; break; - case 27175: originalSpellId = 27174; break; - case 33074: originalSpellId = 33072; break; - case 48820: originalSpellId = 48824; break; - case 48821: originalSpellId = 48825; break; - default: - TC_LOG_ERROR("entities.unit", "Unit::HandleProcTriggerSpell: Spell %u not handled in HShock", procSpell->Id); - return false; - } - } - SpellInfo const* originalSpell = sSpellMgr->GetSpellInfo(originalSpellId); - if (!originalSpell) - { - TC_LOG_ERROR("entities.unit", "Unit::HandleProcTriggerSpell: Spell %u unknown but selected as original in Illu", originalSpellId); - return false; - } - // percent stored in effect 1 (class scripts) base points - int32 cost = int32(originalSpell->ManaCost + CalculatePct(GetCreateMana(), originalSpell->ManaCostPercentage)); - basepoints0 = CalculatePct(cost, auraSpellInfo->Effects[1].CalcValue()); - trigger_spell_id = 20272; - target = this; - } - break; - } - break; - } - case SPELLFAMILY_SHAMAN: - { - switch (auraSpellInfo->Id) - { - case 30881: // Nature's Guardian Rank 1 - case 30883: // Nature's Guardian Rank 2 - case 30884: // Nature's Guardian Rank 3 - case 30885: // Nature's Guardian Rank 4 - case 30886: // Nature's Guardian Rank 5 - { - if (HealthBelowPct(30)) - { - basepoints0 = int32(auraSpellInfo->Effects[EFFECT_0].CalcValue() * GetMaxHealth() / 100.0f); - target = this; - trigger_spell_id = 31616; - /// @todo Threat part - } - else - return false; - break; - } - default: - { - // Lightning Shield (overwrite non existing triggered spell call in spell.dbc - if (auraSpellInfo->SpellFamilyFlags[0] & 0x400) - { - trigger_spell_id = sSpellMgr->GetSpellWithRank(26364, auraSpellInfo->GetRank()); - } - // Nature's Guardian - else if (auraSpellInfo->SpellIconID == 2013) - { - // Check health condition - should drop to less 30% (damage deal after this!) - if (!HealthBelowPctDamaged(30, damage)) - return false; - - if (victim && victim->IsAlive()) - victim->getThreatManager().modifyThreatPercent(this, -10); - - basepoints0 = int32(CountPctFromMaxHealth(triggerAmount)); - trigger_spell_id = 31616; - target = this; - } - } - } - break; - } - case SPELLFAMILY_DEATHKNIGHT: - { - // Acclimation - if (auraSpellInfo->SpellIconID == 1930) - { - if (!procSpell) - return false; - switch (GetFirstSchoolInMask(procSpell->GetSchoolMask())) - { - case SPELL_SCHOOL_NORMAL: - return false; // ignore - case SPELL_SCHOOL_HOLY: trigger_spell_id = 50490; break; - case SPELL_SCHOOL_FIRE: trigger_spell_id = 50362; break; - case SPELL_SCHOOL_NATURE: trigger_spell_id = 50488; break; - case SPELL_SCHOOL_FROST: trigger_spell_id = 50485; break; - case SPELL_SCHOOL_SHADOW: trigger_spell_id = 50489; break; - case SPELL_SCHOOL_ARCANE: trigger_spell_id = 50486; break; - default: - return false; - } - } - // Blood Presence (Improved) - else if (auraSpellInfo->Id == 63611) - { - if (GetTypeId() != TYPEID_PLAYER) - return false; - - trigger_spell_id = 50475; - basepoints0 = CalculatePct(int32(damage), triggerAmount); - } - // Item - Death Knight T10 Melee 4P Bonus - else if (auraSpellInfo->Id == 70656) - { - if (GetTypeId() != TYPEID_PLAYER || getClass() != CLASS_DEATH_KNIGHT) - return false; - - for (uint8 i = 0; i < MAX_RUNES; ++i) - if (ToPlayer()->GetRuneCooldown(i) == 0) - return false; - } - break; - } - case SPELLFAMILY_ROGUE: - { - switch (auraSpellInfo->Id) - { - // Rogue T10 2P bonus, should only proc on caster - case 70805: - { - if (victim != this) - return false; - break; - } - } - break; } default: break; @@ -8240,7 +7797,7 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg float averageDmg = 0; // now compute approximate weapon damage by formula from wowwiki.com - if (procFlags & PROC_FLAG_DONE_OFFHAND_ATTACK) + if (procFlag & PROC_FLAG_DONE_OFFHAND_ATTACK) averageDmg = (GetFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE) + GetFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE)) / 2.f; else averageDmg = (GetFloatValue(UNIT_FIELD_MINDAMAGE) + GetFloatValue(UNIT_FIELD_MAXDAMAGE)) / 2.f; @@ -8402,13 +7959,7 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg if (!target) return false; - if (cooldown && target->GetTypeId() == TYPEID_PLAYER && target->GetSpellHistory()->HasCooldown(trigger_spell_id)) - return false; - target->CastSpell(target, trigger_spell_id, true, castItem, triggeredByAura); - - if (cooldown && GetTypeId() == TYPEID_PLAYER) - GetSpellHistory()->AddCooldown(trigger_spell_id, 0, std::chrono::seconds(cooldown)); return true; } // Cast positive spell on enemy target @@ -8539,7 +8090,7 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg case 56453: { // Proc only from Frost/Freezing trap activation or from Freezing Arrow (the periodic dmg proc handled elsewhere) - if (!(procFlags & PROC_FLAG_DONE_TRAP_ACTIVATION) || !procSpell || !(procSpell->SchoolMask & SPELL_SCHOOL_MASK_FROST) || !roll_chance_i(triggerAmount)) + if (!(procFlag & PROC_FLAG_DONE_TRAP_ACTIVATION) || !procSpell || !(procSpell->SchoolMask & SPELL_SCHOOL_MASK_FROST) || !roll_chance_i(triggerAmount)) return false; break; } @@ -8586,29 +8137,23 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg } } - if (cooldown && GetTypeId() == TYPEID_PLAYER && GetSpellHistory()->HasCooldown(trigger_spell_id)) - return false; - // extra attack should hit same target if (triggerEntry->HasEffect(SPELL_EFFECT_ADD_EXTRA_ATTACKS)) target = victim; // try detect target manually if not set if (target == NULL) - target = !(procFlags & (PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_POS | PROC_FLAG_DONE_SPELL_NONE_DMG_CLASS_POS)) && triggerEntry->IsPositive() ? this : victim; + target = !(procFlag & (PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_POS | PROC_FLAG_DONE_SPELL_NONE_DMG_CLASS_POS)) && triggerEntry->IsPositive() ? this : victim; if (basepoints0) CastCustomSpell(target, trigger_spell_id, &basepoints0, NULL, NULL, true, castItem, triggeredByAura); else CastSpell(target, trigger_spell_id, true, castItem, triggeredByAura); - if (cooldown && GetTypeId() == TYPEID_PLAYER) - GetSpellHistory()->AddCooldown(trigger_spell_id, 0, std::chrono::seconds(cooldown)); - return true; } -bool Unit::HandleOverrideClassScriptAuraProc(Unit* victim, uint32 /*damage*/, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 cooldown) +bool Unit::HandleOverrideClassScriptAuraProc(Unit* victim, uint32 /*damage*/, AuraEffect* triggeredByAura, SpellInfo const* procSpell) { int32 scriptId = triggeredByAura->GetMiscValue(); @@ -8699,14 +8244,7 @@ bool Unit::HandleOverrideClassScriptAuraProc(Unit* victim, uint32 /*damage*/, Au return false; } - if (cooldown && GetTypeId() == TYPEID_PLAYER && GetSpellHistory()->HasCooldown(triggered_spell_id)) - return false; - CastSpell(victim, triggered_spell_id, true, castItem, triggeredByAura); - - if (cooldown && GetTypeId() == TYPEID_PLAYER) - GetSpellHistory()->AddCooldown(triggered_spell_id, 0, std::chrono::seconds(cooldown)); - return true; } @@ -8990,7 +8528,7 @@ bool Unit::Attack(Unit* victim, bool meleeAttack) } else { - if (victim->ToCreature()->IsInEvadeMode()) + if (victim->ToCreature()->IsEvadingAttacks()) return false; } @@ -11875,7 +11413,7 @@ void Unit::SetInCombatState(bool PvP, Unit* enemy) UpdateSpeed(MOVE_FLIGHT); } - if (!(creature->GetCreatureTemplate()->type_flags & CREATURE_TYPEFLAGS_MOUNTED_COMBAT)) + if (!(creature->GetCreatureTemplate()->type_flags & CREATURE_TYPE_FLAG_MOUNTED_COMBAT_ALLOWED)) Dismount(); } @@ -11925,6 +11463,7 @@ void Unit::ClearInCombat() ToPlayer()->UpdatePotionCooldown(); RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PET_IN_COMBAT); + RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_LEAVE_COMBAT); } bool Unit::isTargetableForAttack(bool checkFakeDeath) const @@ -12027,7 +11566,7 @@ bool Unit::_IsValidAttackTarget(Unit const* target, SpellInfo const* bySpell, Wo } Creature const* creatureAttacker = ToCreature(); - if (creatureAttacker && creatureAttacker->GetCreatureTemplate()->type_flags & CREATURE_TYPEFLAGS_PARTY_MEMBER) + if (creatureAttacker && creatureAttacker->GetCreatureTemplate()->type_flags & CREATURE_TYPE_FLAG_TREAT_AS_RAID_UNIT) return false; // check duel - before sanctuary checks @@ -12111,11 +11650,14 @@ bool Unit::_IsValidAssistTarget(Unit const* target, SpellInfo const* bySpell) co // can't assist non-friendly targets if (GetReactionTo(target) < REP_NEUTRAL && target->GetReactionTo(this) < REP_NEUTRAL - && (!ToCreature() || !(ToCreature()->GetCreatureTemplate()->type_flags & CREATURE_TYPEFLAGS_PARTY_MEMBER))) + && (!ToCreature() || !(ToCreature()->GetCreatureTemplate()->type_flags & CREATURE_TYPE_FLAG_TREAT_AS_RAID_UNIT))) return false; + // Controlled player case, we can assist creatures (reaction already checked above, our faction == charmer faction) + if (GetTypeId() == TYPEID_PLAYER && IsCharmed() && GetCharmerGUID().IsCreature()) + return true; // PvP case - if (target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE)) + else if (target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE)) { Player const* targetPlayerOwner = target->GetAffectingPlayer(); if (HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE)) @@ -12145,7 +11687,7 @@ bool Unit::_IsValidAssistTarget(Unit const* target, SpellInfo const* bySpell) co && !((target->GetByteValue(UNIT_FIELD_BYTES_2, 1) & UNIT_BYTE2_FLAG_PVP))) { if (Creature const* creatureTarget = target->ToCreature()) - return creatureTarget->GetCreatureTemplate()->type_flags & CREATURE_TYPEFLAGS_PARTY_MEMBER || creatureTarget->GetCreatureTemplate()->type_flags & CREATURE_TYPEFLAGS_AID_PLAYERS; + return creatureTarget->GetCreatureTemplate()->type_flags & CREATURE_TYPE_FLAG_TREAT_AS_RAID_UNIT || creatureTarget->GetCreatureTemplate()->type_flags & CREATURE_TYPE_FLAG_CAN_ASSIST; } return true; } @@ -12502,7 +12044,7 @@ void Unit::SetSpeedRate(UnitMoveType mtype, float rate) WorldPacket self; self.Initialize(moveTypeToOpcode[mtype][1], mtype != MOVE_RUN ? 8 + 4 + 4 : 8 + 4 + 1 + 4); self << GetPackGUID(); - self << (uint32)0; // Movement counter. Unimplemented at the moment! NUM_PMOVE_EVTS = 0x39Z. + self << (uint32)0; // Movement counter. Unimplemented at the moment! NUM_PMOVE_EVTS = 0x39Z. if (mtype == MOVE_RUN) self << uint8(1); // unknown byte added in 2.1.0 self << float(GetSpeed(mtype)); @@ -12634,7 +12176,7 @@ float Unit::ApplyTotalThreatModifier(float fThreat, SpellSchoolMask schoolMask) void Unit::AddThreat(Unit* victim, float fThreat, SpellSchoolMask schoolMask, SpellInfo const* threatSpell) { // Only mobs can manage threat lists - if (CanHaveThreatList()) + if (CanHaveThreatList() && !HasUnitState(UNIT_STATE_EVADE)) m_ThreatManager.addThreat(victim, fThreat, schoolMask, threatSpell); } @@ -13702,6 +13244,9 @@ void Unit::UpdateCharmAI() delete i_AI; i_AI = i_disabledAI; i_disabledAI = nullptr; + + if (GetTypeId() == TYPEID_UNIT) + ToCreature()->AI()->OnCharmed(false); } } else @@ -13739,6 +13284,7 @@ void Unit::UpdateCharmAI() if (!newAI) // otherwise, we default to the generic one newAI = new SimpleCharmedPlayerAI(ToPlayer()); i_AI = newAI; + newAI->OnCharmed(true); } else { @@ -13849,7 +13395,7 @@ void CharmInfo::InitPossessCreateSpells() break; } - for (uint8 i = 0; i < CREATURE_MAX_SPELLS; ++i) + for (uint8 i = 0; i < MAX_CREATURE_SPELLS; ++i) { uint32 spellId = _unit->ToCreature()->m_spells[i]; SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); @@ -14236,6 +13782,7 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u HealInfo healInfo = HealInfo(actor, actionTarget, damage, procSpell, procSpell ? SpellSchoolMask(procSpell->SchoolMask) : SPELL_SCHOOL_MASK_NORMAL); ProcEventInfo eventInfo = ProcEventInfo(actor, actionTarget, target, procFlag, 0, 0, procExtra, nullptr, &damageInfo, &healInfo); + std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now(); ProcTriggeredList procTriggered; // Fill procTriggered list for (AuraApplicationMap::const_iterator itr = GetAppliedAuras().begin(); itr!= GetAppliedAuras().end(); ++itr) @@ -14243,6 +13790,10 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u // Do not allow auras to proc from effect triggered by itself if (procAura && procAura->Id == itr->first) continue; + + if (itr->second->GetBase()->IsProcOnCooldown(now)) + continue; + ProcTriggeredData triggerData(itr->second->GetBase()); // Defensive procs are active on absorbs (so absorption effects are not a hindrance) bool active = damage || (procExtra & PROC_EX_BLOCK && isVictim); @@ -14267,6 +13818,10 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u if (!triggerData.aura->CallScriptCheckProcHandlers(itr->second, eventInfo)) continue; + bool procSuccess = RollProcResult(target, triggerData.aura, attType, isVictim, triggerData.spellProcEvent); + if (!procSuccess) + continue; + // Triggered spells not triggering additional spells bool triggered = !spellProto->HasAttribute(SPELL_ATTR3_CAN_PROC_WITH_TRIGGERED) ? (procExtra & PROC_EX_INTERNAL_TRIGGERED && !(procFlag & PROC_FLAG_DONE_TRAP_ACTIVATION)) : false; @@ -14320,9 +13875,9 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u bool prepare = i->aura->CallScriptPrepareProcHandlers(aurApp, eventInfo); // For players set spell cooldown if need - uint32 cooldown = 0; + Milliseconds cooldown = Milliseconds::zero(); if (prepare && GetTypeId() == TYPEID_PLAYER && i->spellProcEvent && i->spellProcEvent->cooldown) - cooldown = i->spellProcEvent->cooldown; + cooldown = Seconds(i->spellProcEvent->cooldown); // Note: must SetCantProc(false) before return if (spellInfo->HasAttribute(SPELL_ATTR3_DISABLE_PROC)) @@ -14331,9 +13886,9 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u bool handled = i->aura->CallScriptProcHandlers(aurApp, eventInfo); // "handled" is needed as long as proc can be handled in multiple places - if (!handled && HandleAuraProc(target, damage, i->aura, procSpell, procFlag, procExtra, cooldown, &handled)) + if (!handled && HandleAuraProc(target, damage, i->aura, procSpell, procFlag, procExtra, &handled)) { - TC_LOG_DEBUG("spells", "ProcDamageAndSpell: casting spell %u (triggered with value by %s aura of spell %u)", spellInfo->Id, (isVictim?"a victim's":"an attacker's"), Id); + TC_LOG_DEBUG("spells", "ProcDamageAndSpell: casting spell %u (triggered with value by %s aura of spell %u)", spellInfo->Id, (isVictim ? "a victim's" : "an attacker's"), Id); takeCharges = true; } @@ -14341,7 +13896,7 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u { for (uint8 effIndex = 0; effIndex < MAX_SPELL_EFFECTS; ++effIndex) { - if (!(i->effMask & (1<<effIndex))) + if (!(i->effMask & (1 << effIndex))) continue; AuraEffect* triggeredByAura = i->aura->GetEffect(effIndex); @@ -14358,9 +13913,10 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u { case SPELL_AURA_PROC_TRIGGER_SPELL: { - TC_LOG_DEBUG("spells", "ProcDamageAndSpell: casting spell %u (triggered by %s aura of spell %u)", spellInfo->Id, (isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId()); + TC_LOG_DEBUG("spells", "ProcDamageAndSpell: casting spell %u (triggered by %s aura of spell %u)", + spellInfo->Id, (isVictim ? "a victim's" : "an attacker's"), triggeredByAura->GetId()); // Don`t drop charge or add cooldown for not started trigger - if (HandleProcTriggerSpell(target, damage, triggeredByAura, procSpell, procFlag, procExtra, cooldown)) + if (HandleProcTriggerSpell(target, damage, triggeredByAura, procSpell, procFlag, procExtra)) takeCharges = true; break; } @@ -14377,7 +13933,8 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u case SPELL_AURA_MANA_SHIELD: case SPELL_AURA_DUMMY: { - TC_LOG_DEBUG("spells", "ProcDamageAndSpell: casting spell id %u (triggered by %s dummy aura of spell %u)", spellInfo->Id, (isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId()); + TC_LOG_DEBUG("spells", "ProcDamageAndSpell: casting spell id %u (triggered by %s dummy aura of spell %u)", + spellInfo->Id, (isVictim ? "a victim's" : "an attacker's"), triggeredByAura->GetId()); if (HandleDummyAuraProc(target, damage, triggeredByAura, procSpell, procFlag, procExtra, cooldown)) takeCharges = true; break; @@ -14386,20 +13943,22 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u case SPELL_AURA_MOD_SPELL_CRIT_CHANCE: case SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN: case SPELL_AURA_MOD_MELEE_HASTE: - TC_LOG_DEBUG("spells", "ProcDamageAndSpell: casting spell id %u (triggered by %s aura of spell %u)", spellInfo->Id, isVictim ? "a victim's" : "an attacker's", triggeredByAura->GetId()); + TC_LOG_DEBUG("spells", "ProcDamageAndSpell: casting spell id %u (triggered by %s aura of spell %u)", + spellInfo->Id, isVictim ? "a victim's" : "an attacker's", triggeredByAura->GetId()); takeCharges = true; break; case SPELL_AURA_OVERRIDE_CLASS_SCRIPTS: { - TC_LOG_DEBUG("spells", "ProcDamageAndSpell: casting spell id %u (triggered by %s aura of spell %u)", spellInfo->Id, (isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId()); - if (HandleOverrideClassScriptAuraProc(target, damage, triggeredByAura, procSpell, cooldown)) + TC_LOG_DEBUG("spells", "ProcDamageAndSpell: casting spell id %u (triggered by %s aura of spell %u)", + spellInfo->Id, (isVictim ? "a victim's" : "an attacker's"), triggeredByAura->GetId()); + if (HandleOverrideClassScriptAuraProc(target, damage, triggeredByAura, procSpell)) takeCharges = true; break; } case SPELL_AURA_RAID_PROC_FROM_CHARGE_WITH_VALUE: { TC_LOG_DEBUG("spells", "ProcDamageAndSpell: casting mending (triggered by %s dummy aura of spell %u)", - (isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId()); + (isVictim ? "a victim's" : "an attacker's"), triggeredByAura->GetId()); HandleAuraRaidProcFromChargeWithValue(triggeredByAura); takeCharges = true; @@ -14408,7 +13967,7 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u case SPELL_AURA_RAID_PROC_FROM_CHARGE: { TC_LOG_DEBUG("spells", "ProcDamageAndSpell: casting mending (triggered by %s dummy aura of spell %u)", - (isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId()); + (isVictim ? "a victim's" : "an attacker's"), triggeredByAura->GetId()); HandleAuraRaidProcFromCharge(triggeredByAura); takeCharges = true; @@ -14416,9 +13975,10 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u } case SPELL_AURA_PROC_TRIGGER_SPELL_WITH_VALUE: { - TC_LOG_DEBUG("spells", "ProcDamageAndSpell: casting spell %u (triggered with value by %s aura of spell %u)", spellInfo->Id, (isVictim?"a victim's":"an attacker's"), triggeredByAura->GetId()); + TC_LOG_DEBUG("spells", "ProcDamageAndSpell: casting spell %u (triggered with value by %s aura of spell %u)", + spellInfo->Id, (isVictim ? "a victim's" : "an attacker's"), triggeredByAura->GetId()); - if (HandleProcTriggerSpell(target, damage, triggeredByAura, procSpell, procFlag, procExtra, cooldown)) + if (HandleProcTriggerSpell(target, damage, triggeredByAura, procSpell, procFlag, procExtra)) takeCharges = true; break; } @@ -14503,6 +14063,9 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u } // for (uint8 effIndex = 0; effIndex < MAX_SPELL_EFFECTS; ++effIndex) } // if (!handled) + if (prepare && takeCharges && cooldown != Milliseconds::zero()) + i->aura->AddProcCooldown(now + cooldown); + // Remove charge (aura can be removed by triggers) if (prepare && useCharges && takeCharges) { @@ -14531,6 +14094,8 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u void Unit::GetProcAurasTriggeredOnEvent(std::list<AuraApplication*>& aurasTriggeringProc, std::list<AuraApplication*>* procAuras, ProcEventInfo eventInfo) { + std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now(); + // use provided list of auras which can proc if (procAuras) { @@ -14538,9 +14103,9 @@ void Unit::GetProcAurasTriggeredOnEvent(std::list<AuraApplication*>& aurasTrigge { ASSERT((*itr)->GetTarget() == this); if (!(*itr)->GetRemoveMode()) - if ((*itr)->GetBase()->IsProcTriggeredOnEvent(*itr, eventInfo)) + if ((*itr)->GetBase()->IsProcTriggeredOnEvent(*itr, eventInfo, now)) { - (*itr)->GetBase()->PrepareProcToTrigger(*itr, eventInfo); + (*itr)->GetBase()->PrepareProcToTrigger(*itr, eventInfo, now); aurasTriggeringProc.push_back(*itr); } } @@ -14550,9 +14115,9 @@ void Unit::GetProcAurasTriggeredOnEvent(std::list<AuraApplication*>& aurasTrigge { for (AuraApplicationMap::iterator itr = GetAppliedAuras().begin(); itr!= GetAppliedAuras().end(); ++itr) { - if (itr->second->GetBase()->IsProcTriggeredOnEvent(itr->second, eventInfo)) + if (itr->second->GetBase()->IsProcTriggeredOnEvent(itr->second, eventInfo, now)) { - itr->second->GetBase()->PrepareProcToTrigger(itr->second, eventInfo); + itr->second->GetBase()->PrepareProcToTrigger(itr->second, eventInfo, now); aurasTriggeringProc.push_back(itr->second); } } @@ -15174,23 +14739,23 @@ bool Unit::InitTamedPet(Pet* pet, uint8 level, uint32 spell_id) return true; } -bool Unit::IsTriggeredAtSpellProcEvent(Unit* victim, Aura* aura, SpellInfo const* procSpell, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, bool isVictim, bool active, SpellProcEventEntry const* & spellProcEvent) +bool Unit::IsTriggeredAtSpellProcEvent(Unit* victim, Aura* aura, SpellInfo const* procSpell, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, bool isVictim, bool active, SpellProcEventEntry const*& spellProcEvent) { - SpellInfo const* spellProto = aura->GetSpellInfo(); + SpellInfo const* spellInfo = aura->GetSpellInfo(); // let the aura be handled by new proc system if it has new entry - if (sSpellMgr->GetSpellProcEntry(spellProto->Id)) + if (sSpellMgr->GetSpellProcEntry(spellInfo->Id)) return false; // Get proc Event Entry - spellProcEvent = sSpellMgr->GetSpellProcEvent(spellProto->Id); + spellProcEvent = sSpellMgr->GetSpellProcEvent(spellInfo->Id); // Get EventProcFlag uint32 EventProcFlag; if (spellProcEvent && spellProcEvent->procFlags) // if exist get custom spellProcEvent->procFlags EventProcFlag = spellProcEvent->procFlags; else - EventProcFlag = spellProto->ProcFlags; // else get from spell proto + EventProcFlag = spellInfo->ProcFlags; // else get from spell proto // Continue if no trigger exist if (!EventProcFlag) return false; @@ -15198,12 +14763,12 @@ bool Unit::IsTriggeredAtSpellProcEvent(Unit* victim, Aura* aura, SpellInfo const // Additional checks for triggered spells (ignore trap casts) if (procExtra & PROC_EX_INTERNAL_TRIGGERED && !(procFlag & PROC_FLAG_DONE_TRAP_ACTIVATION)) { - if (!spellProto->HasAttribute(SPELL_ATTR3_CAN_PROC_WITH_TRIGGERED)) + if (!spellInfo->HasAttribute(SPELL_ATTR3_CAN_PROC_WITH_TRIGGERED)) return false; } // Check spellProcEvent data requirements - if (!sSpellMgr->IsSpellProcEventCanTriggeredBy(spellProto, spellProcEvent, EventProcFlag, procSpell, procFlag, procExtra, active)) + if (!sSpellMgr->IsSpellProcEventCanTriggeredBy(spellInfo, spellProcEvent, EventProcFlag, procSpell, procFlag, procExtra, active)) return false; // In most cases req get honor or XP from kill if (EventProcFlag & PROC_FLAG_KILL && GetTypeId() == TYPEID_PLAYER) @@ -15221,15 +14786,15 @@ bool Unit::IsTriggeredAtSpellProcEvent(Unit* victim, Aura* aura, SpellInfo const } // Aura added by spell can`t trigger from self (prevent drop charges/do triggers) // But except periodic and kill triggers (can triggered from self) - if (procSpell && procSpell->Id == spellProto->Id - && !(spellProto->ProcFlags&(PROC_FLAG_TAKEN_PERIODIC | PROC_FLAG_KILL))) + if (procSpell && procSpell->Id == spellInfo->Id + && !(spellInfo->ProcFlags&(PROC_FLAG_TAKEN_PERIODIC | PROC_FLAG_KILL))) return false; // Check if current equipment allows aura to proc if (!isVictim && GetTypeId() == TYPEID_PLAYER) { Player* player = ToPlayer(); - if (spellProto->EquippedItemClass == ITEM_CLASS_WEAPON) + if (spellInfo->EquippedItemClass == ITEM_CLASS_WEAPON) { Item* item = NULL; if (attType == BASE_ATTACK) @@ -15242,19 +14807,26 @@ bool Unit::IsTriggeredAtSpellProcEvent(Unit* victim, Aura* aura, SpellInfo const if (player->IsInFeralForm()) return false; - if (!item || item->IsBroken() || item->GetTemplate()->Class != ITEM_CLASS_WEAPON || !((1<<item->GetTemplate()->SubClass) & spellProto->EquippedItemSubClassMask)) + if (!item || item->IsBroken() || item->GetTemplate()->Class != ITEM_CLASS_WEAPON || !((1<<item->GetTemplate()->SubClass) & spellInfo->EquippedItemSubClassMask)) return false; } - else if (spellProto->EquippedItemClass == ITEM_CLASS_ARMOR) + else if (spellInfo->EquippedItemClass == ITEM_CLASS_ARMOR) { // Check if player is wearing shield Item* item = player->GetUseableItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_OFFHAND); - if (!item || item->IsBroken() || item->GetTemplate()->Class != ITEM_CLASS_ARMOR || !((1<<item->GetTemplate()->SubClass) & spellProto->EquippedItemSubClassMask)) + if (!item || item->IsBroken() || item->GetTemplate()->Class != ITEM_CLASS_ARMOR || !((1<<item->GetTemplate()->SubClass) & spellInfo->EquippedItemSubClassMask)) return false; } } + + return true; +} + +bool Unit::RollProcResult(Unit* victim, Aura* aura, WeaponAttackType attType, bool isVictim, SpellProcEventEntry const* spellProcEvent) +{ + SpellInfo const* spellInfo = aura->GetSpellInfo(); // Get chance from spell - float chance = float(spellProto->ProcChance); + float chance = float(spellInfo->ProcChance); // If in spellProcEvent exist custom chance, chance = spellProcEvent->customChance; if (spellProcEvent && spellProcEvent->customChance) chance = spellProcEvent->customChance; @@ -15264,19 +14836,18 @@ bool Unit::IsTriggeredAtSpellProcEvent(Unit* victim, Aura* aura, SpellInfo const if (!isVictim) { uint32 weaponSpeed = GetAttackTime(attType); - chance = GetPPMProcChance(weaponSpeed, spellProcEvent->ppmRate, spellProto); + chance = GetPPMProcChance(weaponSpeed, spellProcEvent->ppmRate, spellInfo); } else if (victim) { uint32 weaponSpeed = victim->GetAttackTime(attType); - chance = victim->GetPPMProcChance(weaponSpeed, spellProcEvent->ppmRate, spellProto); + chance = victim->GetPPMProcChance(weaponSpeed, spellProcEvent->ppmRate, spellInfo); } } // Apply chance modifer aura if (Player* modOwner = GetSpellModOwner()) - { - modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_CHANCE_OF_SUCCESS, chance); - } + modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_CHANCE_OF_SUCCESS, chance); + return roll_chance_f(chance); } @@ -16007,7 +15578,11 @@ bool Unit::SetCharmedBy(Unit* charmer, CharmType type, AuraApplication const* au { // change AI to charmed AI on next Update tick NeedChangeAI = true; - IsAIEnabled = false; + if (IsAIEnabled) + { + IsAIEnabled = false; + player->AI()->OnCharmed(true); + } } player->SetClientControl(this, false); } @@ -16039,7 +15614,7 @@ bool Unit::SetCharmedBy(Unit* charmer, CharmType type, AuraApplication const* au case CHARM_TYPE_POSSESS: AddUnitState(UNIT_STATE_POSSESSED); SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED); - charmer->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + charmer->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL); playerCharmer->SetClientControl(this, true); playerCharmer->PossessSpellInitialize(); break; @@ -16142,7 +15717,7 @@ void Unit::RemoveCharmedBy(Unit* charmer) case CHARM_TYPE_POSSESS: playerCharmer->SetClientControl(this, false); playerCharmer->SetClientControl(charmer, true); - charmer->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + charmer->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL); RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED); ClearUnitState(UNIT_STATE_POSSESSED); break; @@ -16282,8 +15857,8 @@ bool Unit::IsInPartyWith(Unit const* unit) const if (u1->GetTypeId() == TYPEID_PLAYER && u2->GetTypeId() == TYPEID_PLAYER) return u1->ToPlayer()->IsInSameGroupWith(u2->ToPlayer()); - else if ((u2->GetTypeId() == TYPEID_PLAYER && u1->GetTypeId() == TYPEID_UNIT && u1->ToCreature()->GetCreatureTemplate()->type_flags & CREATURE_TYPEFLAGS_PARTY_MEMBER) || - (u1->GetTypeId() == TYPEID_PLAYER && u2->GetTypeId() == TYPEID_UNIT && u2->ToCreature()->GetCreatureTemplate()->type_flags & CREATURE_TYPEFLAGS_PARTY_MEMBER)) + else if ((u2->GetTypeId() == TYPEID_PLAYER && u1->GetTypeId() == TYPEID_UNIT && u1->ToCreature()->GetCreatureTemplate()->type_flags & CREATURE_TYPE_FLAG_TREAT_AS_RAID_UNIT) || + (u1->GetTypeId() == TYPEID_PLAYER && u2->GetTypeId() == TYPEID_UNIT && u2->ToCreature()->GetCreatureTemplate()->type_flags & CREATURE_TYPE_FLAG_TREAT_AS_RAID_UNIT)) return true; else return false; @@ -16301,8 +15876,8 @@ bool Unit::IsInRaidWith(Unit const* unit) const if (u1->GetTypeId() == TYPEID_PLAYER && u2->GetTypeId() == TYPEID_PLAYER) return u1->ToPlayer()->IsInSameRaidWith(u2->ToPlayer()); - else if ((u2->GetTypeId() == TYPEID_PLAYER && u1->GetTypeId() == TYPEID_UNIT && u1->ToCreature()->GetCreatureTemplate()->type_flags & CREATURE_TYPEFLAGS_PARTY_MEMBER) || - (u1->GetTypeId() == TYPEID_PLAYER && u2->GetTypeId() == TYPEID_UNIT && u2->ToCreature()->GetCreatureTemplate()->type_flags & CREATURE_TYPEFLAGS_PARTY_MEMBER)) + else if ((u2->GetTypeId() == TYPEID_PLAYER && u1->GetTypeId() == TYPEID_UNIT && u1->ToCreature()->GetCreatureTemplate()->type_flags & CREATURE_TYPE_FLAG_TREAT_AS_RAID_UNIT) || + (u1->GetTypeId() == TYPEID_PLAYER && u2->GetTypeId() == TYPEID_UNIT && u2->ToCreature()->GetCreatureTemplate()->type_flags & CREATURE_TYPE_FLAG_TREAT_AS_RAID_UNIT)) return true; else return false; @@ -17647,7 +17222,7 @@ void Unit::SetFacingToObject(WorldObject const* object) /// @todo figure out under what conditions creature will move towards object instead of facing it where it currently is. Movement::MoveSplineInit init(this); - init.MoveTo(GetPositionX(), GetPositionY(), GetPositionZMinusOffset()); + init.MoveTo(GetPositionX(), GetPositionY(), GetPositionZMinusOffset(), false); init.SetFacing(GetAngle(object)); // when on transport, GetAngle will still return global coordinates (and angle) that needs transforming init.Launch(); } diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index a0973aac279..b23aff3ed8e 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -76,6 +76,7 @@ enum SpellAuraInterruptFlags AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT = 0x00800000, // 23 removed by entering pvp combat AURA_INTERRUPT_FLAG_DIRECT_DAMAGE = 0x01000000, // 24 removed by any direct damage AURA_INTERRUPT_FLAG_LANDING = 0x02000000, // 25 removed by hitting the ground + AURA_INTERRUPT_FLAG_LEAVE_COMBAT = 0x80000000, // 31 removed by leaving combat AURA_INTERRUPT_FLAG_NOT_VICTIM = (AURA_INTERRUPT_FLAG_HITBYSPELL | AURA_INTERRUPT_FLAG_TAKE_DAMAGE | AURA_INTERRUPT_FLAG_DIRECT_DAMAGE) }; @@ -614,7 +615,7 @@ enum UnitFlags : uint32 { UNIT_FLAG_SERVER_CONTROLLED = 0x00000001, // set only when unit movement is controlled by server - by SPLINE/MONSTER_MOVE packets, together with UNIT_FLAG_STUNNED; only set to units controlled by client; client function CGUnit_C::IsClientControlled returns false when set for owner UNIT_FLAG_NON_ATTACKABLE = 0x00000002, // not attackable - UNIT_FLAG_DISABLE_MOVE = 0x00000004, + UNIT_FLAG_REMOVE_CLIENT_CONTROL = 0x00000004, // This is a legacy flag used to disable movement player's movement while controlling other units, SMSG_CLIENT_CONTROL replaces this functionality clientside now. CONFUSED and FLEEING flags have the same effect on client movement asDISABLE_MOVE_CONTROL in addition to preventing spell casts/autoattack (they all allow climbing steeper hills and emotes while moving) UNIT_FLAG_PVP_ATTACKABLE = 0x00000008, // allow apply pvp rules to attackable state in addition to faction dependent state UNIT_FLAG_RENAME = 0x00000010, UNIT_FLAG_PREPARATION = 0x00000020, // don't take reagents for spells with SPELL_ATTR5_NO_REAGENT_WHILE_PREP @@ -626,7 +627,7 @@ enum UnitFlags : uint32 UNIT_FLAG_PET_IN_COMBAT = 0x00000800, // in combat?, 2.0.8 UNIT_FLAG_PVP = 0x00001000, // changed in 3.0.3 UNIT_FLAG_SILENCED = 0x00002000, // silenced, 2.1.1 - UNIT_FLAG_UNK_14 = 0x00004000, // 2.0.8 + UNIT_FLAG_CANNOT_SWIM = 0x00004000, // 2.0.8 UNIT_FLAG_UNK_15 = 0x00008000, UNIT_FLAG_UNK_16 = 0x00010000, UNIT_FLAG_PACIFIED = 0x00020000, // 3.0.3 ok @@ -1755,6 +1756,7 @@ class TC_GAME_API Unit : public WorldObject void RemoveAreaAurasDueToLeaveWorld(); void RemoveAllAuras(); void RemoveArenaAuras(); + void RemoveAurasOnEvade(); void RemoveAllAurasOnDeath(); void RemoveAllAurasRequiringDeadTarget(); void RemoveAllAurasExceptType(AuraType type); @@ -1856,6 +1858,9 @@ class TC_GAME_API Unit : public WorldObject Spell* FindCurrentSpellBySpellId(uint32 spell_id) const; int32 GetCurrentSpellCastTime(uint32 spell_id) const; + // Check if our current channel spell has attribute SPELL_ATTR5_CAN_CHANNEL_WHEN_MOVING + bool CanMoveDuringChannel() const; + SpellHistory* GetSpellHistory() { return m_spellHistory; } SpellHistory const* GetSpellHistory() const { return m_spellHistory; } @@ -2166,11 +2171,11 @@ class TC_GAME_API Unit : public WorldObject virtual void Yell(std::string const& text, Language language, WorldObject const* target = nullptr); virtual void TextEmote(std::string const& text, WorldObject const* target = nullptr, bool isBossEmote = false); virtual void Whisper(std::string const& text, Language language, Player* target, bool isBossWhisper = false); - void Talk(uint32 textId, ChatMsg msgType, float textRange, WorldObject const* target); - void Say(uint32 textId, WorldObject const* target = nullptr); - void Yell(uint32 textId, WorldObject const* target = nullptr); - void TextEmote(uint32 textId, WorldObject const* target = nullptr, bool isBossEmote = false); - void Whisper(uint32 textId, Player* target, bool isBossWhisper = false); + virtual void Talk(uint32 textId, ChatMsg msgType, float textRange, WorldObject const* target); + virtual void Say(uint32 textId, WorldObject const* target = nullptr); + virtual void Yell(uint32 textId, WorldObject const* target = nullptr); + virtual void TextEmote(uint32 textId, WorldObject const* target = nullptr, bool isBossEmote = false); + virtual void Whisper(uint32 textId, Player* target, bool isBossWhisper = false); protected: explicit Unit (bool isWorldObject); @@ -2250,11 +2255,12 @@ class TC_GAME_API Unit : public WorldObject void DisableSpline(); private: - bool IsTriggeredAtSpellProcEvent(Unit* victim, Aura* aura, SpellInfo const* procSpell, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, bool isVictim, bool active, SpellProcEventEntry const* & spellProcEvent); - bool HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown); - bool HandleAuraProc(Unit* victim, uint32 damage, Aura* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown, bool * handled); - bool HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown); - bool HandleOverrideClassScriptAuraProc(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 cooldown); + bool IsTriggeredAtSpellProcEvent(Unit* victim, Aura* aura, SpellInfo const* procSpell, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, bool isVictim, bool active, SpellProcEventEntry const*& spellProcEvent); + bool RollProcResult(Unit* victim, Aura* aura, WeaponAttackType attType, bool isVictim, SpellProcEventEntry const* spellProcEvent); + bool HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx, Milliseconds& cooldown); + bool HandleAuraProc(Unit* victim, uint32 damage, Aura* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx, bool* handled); + bool HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell, uint32 procFlag, uint32 procEx); + bool HandleOverrideClassScriptAuraProc(Unit* victim, uint32 damage, AuraEffect* triggeredByAura, SpellInfo const* procSpell); bool HandleAuraRaidProcFromChargeWithValue(AuraEffect* triggeredByAura); bool HandleAuraRaidProcFromCharge(AuraEffect* triggeredByAura); diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 3efeb1ca273..33a0325851a 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -473,7 +473,7 @@ void ObjectMgr::LoadCreatureTemplate(Field* fields) creatureTemplate.unit_flags = fields[29].GetUInt32(); creatureTemplate.unit_flags2 = fields[30].GetUInt32(); creatureTemplate.dynamicflags = fields[31].GetUInt32(); - creatureTemplate.family = fields[32].GetUInt8(); + creatureTemplate.family = CreatureFamily(fields[32].GetUInt8()); creatureTemplate.trainer_type = fields[33].GetUInt8(); creatureTemplate.trainer_spell = fields[34].GetUInt32(); creatureTemplate.trainer_class = fields[35].GetUInt8(); @@ -487,7 +487,7 @@ void ObjectMgr::LoadCreatureTemplate(Field* fields) for (uint8 i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i) creatureTemplate.resistance[i] = fields[42 + i - 1].GetInt16(); - for (uint8 i = 0; i < CREATURE_MAX_SPELLS; ++i) + for (uint8 i = 0; i < MAX_CREATURE_SPELLS; ++i) creatureTemplate.spells[i] = fields[48 + i].GetUInt32(); creatureTemplate.PetSpellDataId = fields[56].GetUInt32(); @@ -833,7 +833,7 @@ void ObjectMgr::CheckCreatureTemplate(CreatureTemplate const* cInfo) if (!displayScaleEntry) TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) does not have any existing display id in Modelid1/Modelid2/Modelid3/Modelid4.", cInfo->Entry); - for (int k = 0; k < MAX_KILL_CREDIT; ++k) + for (uint8 k = 0; k < MAX_KILL_CREDIT; ++k) { if (cInfo->KillCredit[k]) { @@ -888,7 +888,7 @@ void ObjectMgr::CheckCreatureTemplate(CreatureTemplate const* cInfo) if (cInfo->family && !sCreatureFamilyStore.LookupEntry(cInfo->family) && cInfo->family != CREATURE_FAMILY_HORSE_CUSTOM) { TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) has invalid creature family (%u) in `family`.", cInfo->Entry, cInfo->family); - const_cast<CreatureTemplate*>(cInfo)->family = 0; + const_cast<CreatureTemplate*>(cInfo)->family = CREATURE_FAMILY_NONE; } if (cInfo->InhabitType <= 0 || cInfo->InhabitType > INHABIT_ANYWHERE) @@ -920,7 +920,7 @@ void ObjectMgr::CheckCreatureTemplate(CreatureTemplate const* cInfo) TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) has non-existing PetSpellDataId (%u).", cInfo->Entry, cInfo->PetSpellDataId); } - for (uint8 j = 0; j < CREATURE_MAX_SPELLS; ++j) + for (uint8 j = 0; j < MAX_CREATURE_SPELLS; ++j) { if (cInfo->spells[j] && !sSpellMgr->GetSpellInfo(cInfo->spells[j])) { @@ -5946,14 +5946,14 @@ void ObjectMgr::LoadGraveyardZones() { uint32 oldMSTime = getMSTime(); - GraveYardStore.clear(); // need for reload case + GraveYardStore.clear(); // need for reload case - // 0 1 2 - QueryResult result = WorldDatabase.Query("SELECT id, ghost_zone, faction FROM game_graveyard_zone"); + // 0 1 2 + QueryResult result = WorldDatabase.Query("SELECT ID, GhostZone, Faction FROM graveyard_zone"); if (!result) { - TC_LOG_INFO("server.loading", ">> Loaded 0 graveyard-zone links. DB table `game_graveyard_zone` is empty."); + TC_LOG_INFO("server.loading", ">> Loaded 0 graveyard-zone links. DB table `graveyard_zone` is empty."); return; } @@ -5972,31 +5972,31 @@ void ObjectMgr::LoadGraveyardZones() WorldSafeLocsEntry const* entry = sWorldSafeLocsStore.LookupEntry(safeLocId); if (!entry) { - TC_LOG_ERROR("sql.sql", "Table `game_graveyard_zone` has a record for not existing graveyard (WorldSafeLocs.dbc id) %u, skipped.", safeLocId); + TC_LOG_ERROR("sql.sql", "Table `graveyard_zone` has a record for non-existing graveyard (WorldSafeLocsID: %u), skipped.", safeLocId); continue; } AreaTableEntry const* areaEntry = sAreaTableStore.LookupEntry(zoneId); if (!areaEntry) { - TC_LOG_ERROR("sql.sql", "Table `game_graveyard_zone` has a record for not existing zone id (%u), skipped.", zoneId); + TC_LOG_ERROR("sql.sql", "Table `graveyard_zone` has a record for non-existing Zone (ID: %u), skipped.", zoneId); continue; } if (areaEntry->zone != 0) { - TC_LOG_ERROR("sql.sql", "Table `game_graveyard_zone` has a record for subzone id (%u) instead of zone, skipped.", zoneId); + TC_LOG_ERROR("sql.sql", "Table `graveyard_zone` has a record for SubZone (ID: %u) instead of zone, skipped.", zoneId); continue; } if (team != 0 && team != HORDE && team != ALLIANCE) { - TC_LOG_ERROR("sql.sql", "Table `game_graveyard_zone` has a record for non player faction (%u), skipped.", team); + TC_LOG_ERROR("sql.sql", "Table `graveyard_zone` has a record for non player faction (%u), skipped.", team); continue; } if (!AddGraveYardLink(safeLocId, zoneId, team, false)) - TC_LOG_ERROR("sql.sql", "Table `game_graveyard_zone` has a duplicate record for Graveyard (ID: %u) and Zone (ID: %u), skipped.", safeLocId, zoneId); + TC_LOG_ERROR("sql.sql", "Table `graveyard_zone` has a duplicate record for Graveyard (ID: %u) and Zone (ID: %u), skipped.", safeLocId, zoneId); } while (result->NextRow()); TC_LOG_INFO("server.loading", ">> Loaded %u graveyard-zone links in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); @@ -6045,7 +6045,7 @@ WorldSafeLocsEntry const* ObjectMgr::GetClosestGraveYard(float x, float y, float if (range.first == range.second && !map->IsBattlegroundOrArena()) { if (zoneId != 0) // zone == 0 can't be fixed, used by bliz for bugged zones - TC_LOG_ERROR("sql.sql", "Table `game_graveyard_zone` incomplete: Zone %u Team %u does not have a linked graveyard.", zoneId, team); + TC_LOG_ERROR("sql.sql", "Table `graveyard_zone` incomplete: Zone %u Team %u does not have a linked graveyard.", zoneId, team); return GetDefaultGraveYard(team); } @@ -6071,7 +6071,7 @@ WorldSafeLocsEntry const* ObjectMgr::GetClosestGraveYard(float x, float y, float WorldSafeLocsEntry const* entry = sWorldSafeLocsStore.LookupEntry(data.safeLocId); if (!entry) { - TC_LOG_ERROR("sql.sql", "Table `game_graveyard_zone` has record for not existing graveyard (WorldSafeLocs.dbc id) %u, skipped.", data.safeLocId); + TC_LOG_ERROR("sql.sql", "Table `graveyard_zone` has record for not existing graveyard (WorldSafeLocsID %u), skipped.", data.safeLocId); continue; } @@ -6186,7 +6186,7 @@ void ObjectMgr::RemoveGraveYardLink(uint32 id, uint32 zoneId, uint32 team, bool GraveYardMapBoundsNonConst range = GraveYardStore.equal_range(zoneId); if (range.first == range.second) { - //TC_LOG_ERROR("sql.sql", "Table `game_graveyard_zone` incomplete: Zone %u Team %u does not have a linked graveyard.", zoneId, team); + //TC_LOG_ERROR("sql.sql", "Table `graveyard_zone` incomplete: Zone %u Team %u does not have a linked graveyard.", zoneId, team); return; } diff --git a/src/server/game/Grids/Notifiers/GridNotifiers.h b/src/server/game/Grids/Notifiers/GridNotifiers.h index 84aa29f96b7..1d2b0bd33cf 100644 --- a/src/server/game/Grids/Notifiers/GridNotifiers.h +++ b/src/server/game/Grids/Notifiers/GridNotifiers.h @@ -1237,7 +1237,7 @@ namespace Trinity AllGameObjectsWithEntryInRange(const WorldObject* object, uint32 entry, float maxRange) : m_pObject(object), m_uiEntry(entry), m_fRange(maxRange) { } bool operator() (GameObject* go) { - if (go->GetEntry() == m_uiEntry && m_pObject->IsWithinDist(go, m_fRange, false)) + if ((!m_uiEntry || go->GetEntry() == m_uiEntry) && m_pObject->IsWithinDist(go, m_fRange, false)) return true; return false; @@ -1254,7 +1254,7 @@ namespace Trinity AllCreaturesOfEntryInRange(const WorldObject* object, uint32 entry, float maxRange) : m_pObject(object), m_uiEntry(entry), m_fRange(maxRange) { } bool operator() (Unit* unit) { - if (unit->GetEntry() == m_uiEntry && m_pObject->IsWithinDist(unit, m_fRange, false)) + if ((!m_uiEntry || unit->GetEntry() == m_uiEntry) && m_pObject->IsWithinDist(unit, m_fRange, false)) return true; return false; diff --git a/src/server/game/Guilds/Guild.cpp b/src/server/game/Guilds/Guild.cpp index 87494e78a28..121afc014ce 100644 --- a/src/server/game/Guilds/Guild.cpp +++ b/src/server/game/Guilds/Guild.cpp @@ -1443,17 +1443,17 @@ void Guild::HandleSetBankTabInfo(WorldSession* session, uint8 tabId, std::string _BroadcastEvent(GE_BANK_TAB_UPDATED, ObjectGuid::Empty, aux, name.c_str(), icon.c_str()); } -void Guild::HandleSetMemberNote(WorldSession* session, std::string const& name, std::string const& note, bool isPublic) +void Guild::HandleSetMemberNote(WorldSession* session, std::string const& name, std::string const& note, bool officer) { // Player must have rights to set public/officer note - if (!_HasRankRight(session->GetPlayer(), isPublic ? GR_RIGHT_EPNOTE : GR_RIGHT_EOFFNOTE)) + if (!_HasRankRight(session->GetPlayer(), officer ? GR_RIGHT_EOFFNOTE : GR_RIGHT_EPNOTE)) SendCommandResult(session, GUILD_COMMAND_PUBLIC_NOTE, ERR_GUILD_PERMISSIONS); else if (Member* member = GetMember(name)) { - if (isPublic) - member->SetPublicNote(note); - else + if (officer) member->SetOfficerNote(note); + else + member->SetPublicNote(note); HandleRoster(session); } diff --git a/src/server/game/Handlers/GroupHandler.cpp b/src/server/game/Handlers/GroupHandler.cpp index 84cbb86345d..1c1982600ca 100644 --- a/src/server/game/Handlers/GroupHandler.cpp +++ b/src/server/game/Handlers/GroupHandler.cpp @@ -488,9 +488,7 @@ void WorldSession::HandleMinimapPingOpcode(WorldPacket& recvData) void WorldSession::HandleRandomRollOpcode(WorldPacket& recvData) { - TC_LOG_DEBUG("network", "WORLD: Received MSG_RANDOM_ROLL"); - - uint32 minimum, maximum, roll; + uint32 minimum, maximum; recvData >> minimum; recvData >> maximum; @@ -499,20 +497,7 @@ void WorldSession::HandleRandomRollOpcode(WorldPacket& recvData) return; /********************/ - // everything's fine, do it - roll = urand(minimum, maximum); - - //TC_LOG_DEBUG("ROLL: MIN: %u, MAX: %u, ROLL: %u", minimum, maximum, roll); - - WorldPacket data(MSG_RANDOM_ROLL, 4+4+4+8); - data << uint32(minimum); - data << uint32(maximum); - data << uint32(roll); - data << uint64(GetPlayer()->GetGUID()); - if (GetPlayer()->GetGroup()) - GetPlayer()->GetGroup()->BroadcastPacket(&data, false); - else - SendPacket(&data); + GetPlayer()->DoRandomRoll(minimum, maximum); } void WorldSession::HandleRaidTargetUpdateOpcode(WorldPacket& recvData) diff --git a/src/server/game/Handlers/GuildHandler.cpp b/src/server/game/Handlers/GuildHandler.cpp index e8f8372d679..3801e974dba 100644 --- a/src/server/game/Handlers/GuildHandler.cpp +++ b/src/server/game/Handlers/GuildHandler.cpp @@ -178,7 +178,7 @@ void WorldSession::HandleGuildSetPublicNoteOpcode(WorldPacket& recvPacket) if (normalizePlayerName(playerName)) if (Guild* guild = GetPlayer()->GetGuild()) - guild->HandleSetMemberNote(this, playerName, note, true); + guild->HandleSetMemberNote(this, playerName, note, false); } void WorldSession::HandleGuildSetOfficerNoteOpcode(WorldPacket& recvPacket) @@ -192,7 +192,7 @@ void WorldSession::HandleGuildSetOfficerNoteOpcode(WorldPacket& recvPacket) if (normalizePlayerName(playerName)) if (Guild* guild = GetPlayer()->GetGuild()) - guild->HandleSetMemberNote(this, playerName, note, false); + guild->HandleSetMemberNote(this, playerName, note, true); } void WorldSession::HandleGuildRankOpcode(WorldPacket& recvPacket) diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp index 467d3730ab2..52b36d80202 100644 --- a/src/server/game/Handlers/MiscHandler.cpp +++ b/src/server/game/Handlers/MiscHandler.cpp @@ -884,15 +884,15 @@ void WorldSession::HandleAreaTriggerOpcode(WorldPacket& recvData) player->SendTransferAborted(entry->MapID, TRANSFER_ABORT_DIFFICULTY, player->GetDifficulty(entry->IsRaid())); break; case Map::CANNOT_ENTER_NOT_IN_RAID: - if (MapEntry const* entry = sMapStore.LookupEntry(at->target_mapId)) - { - char const* mapName = entry->name[player->GetSession()->GetSessionDbcLocale()]; - TC_LOG_DEBUG("maps", "MAP: Player '%s' must be in a raid group to enter instance '%s'", player->GetName().c_str(), mapName); - // probably there must be special opcode, because client has this string constant in GlobalStrings.lua - player->GetSession()->SendAreaTriggerMessage(player->GetSession()->GetTrinityString(LANG_INSTANCE_RAID_GROUP_ONLY), mapName); - } + { + WorldPacket data(SMSG_RAID_GROUP_ONLY, 4 + 4); + data << uint32(0); + data << uint32(2); // You must be in a raid group to enter this instance. + player->GetSession()->SendPacket(&data); + TC_LOG_DEBUG("maps", "MAP: Player '%s' must be in a raid group to enter instance map %d", player->GetName().c_str(), at->target_mapId); reviveAtTrigger = true; break; + } case Map::CANNOT_ENTER_CORPSE_IN_DIFFERENT_INSTANCE: { WorldPacket data(SMSG_CORPSE_NOT_IN_INSTANCE); @@ -1057,13 +1057,13 @@ void WorldSession::HandleSetActionButtonOpcode(WorldPacket& recvData) void WorldSession::HandleCompleteCinematic(WorldPacket& /*recvData*/) { // If player has sight bound to visual waypoint NPC we should remove it - GetPlayer()->EndCinematic(); + GetPlayer()->GetCinematicMgr()->EndCinematic(); } void WorldSession::HandleNextCinematicCamera(WorldPacket& /*recvData*/) { // Sent by client when cinematic actually begun. So we begin the server side process - GetPlayer()->BeginCinematic(); + GetPlayer()->GetCinematicMgr()->BeginCinematic(); } void WorldSession::HandleMoveTimeSkippedOpcode(WorldPacket& recvData) diff --git a/src/server/game/Handlers/QueryHandler.cpp b/src/server/game/Handlers/QueryHandler.cpp index ebc9ebde994..1eee9e0d9fe 100644 --- a/src/server/game/Handlers/QueryHandler.cpp +++ b/src/server/game/Handlers/QueryHandler.cpp @@ -133,10 +133,10 @@ void WorldSession::HandleCreatureQueryOpcode(WorldPacket& recvData) CreatureQuestItemList const* items = sObjectMgr->GetCreatureQuestItemList(entry); if (items) - for (size_t i = 0; i < MAX_CREATURE_QUEST_ITEMS; ++i) + for (uint32 i = 0; i < MAX_CREATURE_QUEST_ITEMS; ++i) data << (i < items->size() ? uint32((*items)[i]) : uint32(0)); else - for (size_t i = 0; i < MAX_CREATURE_QUEST_ITEMS; ++i) + for (uint32 i = 0; i < MAX_CREATURE_QUEST_ITEMS; ++i) data << uint32(0); data << uint32(ci->movementId); // CreatureMovementInfo.dbc diff --git a/src/server/game/Loot/LootMgr.cpp b/src/server/game/Loot/LootMgr.cpp index 5cede9a32d5..390b636bb5e 100644 --- a/src/server/game/Loot/LootMgr.cpp +++ b/src/server/game/Loot/LootMgr.cpp @@ -704,7 +704,7 @@ void Loot::DeleteLootItemFromContainerItemDB(uint32 itemID) if (_itr->itemid != itemID) continue; - _itr->canSave = true; + _itr->canSave = false; break; } } diff --git a/src/server/game/Maps/MapManager.h b/src/server/game/Maps/MapManager.h index a7fdc37d324..91a26c29150 100644 --- a/src/server/game/Maps/MapManager.h +++ b/src/server/game/Maps/MapManager.h @@ -126,9 +126,9 @@ class TC_GAME_API MapManager template<typename Worker> void DoForAllMapsWithMapId(uint32 mapId, Worker&& worker); - uint32 IncreaseScheduledScriptsCount() { return ++_scheduledScripts; } - uint32 DecreaseScheduledScriptCount() { return --_scheduledScripts; } - uint32 DecreaseScheduledScriptCount(size_t count) { return _scheduledScripts -= count; } + void IncreaseScheduledScriptsCount() { ++_scheduledScripts; } + void DecreaseScheduledScriptCount() { --_scheduledScripts; } + void DecreaseScheduledScriptCount(std::size_t count) { _scheduledScripts -= count; } bool IsScriptScheduled() const { return _scheduledScripts > 0; } private: @@ -157,7 +157,7 @@ class TC_GAME_API MapManager MapUpdater m_updater; // atomic op counter for active scripts amount - std::atomic<uint32> _scheduledScripts; + std::atomic<std::size_t> _scheduledScripts; }; template<typename Worker> diff --git a/src/server/game/Miscellaneous/Language.h b/src/server/game/Miscellaneous/Language.h index ca63137ac93..d6af5d81432 100644 --- a/src/server/game/Miscellaneous/Language.h +++ b/src/server/game/Miscellaneous/Language.h @@ -1063,7 +1063,7 @@ enum TrinityStrings LANG_COMMAND_NO_FROZEN_PLAYERS = 5004, LANG_COMMAND_LIST_FREEZE = 5005, LANG_COMMAND_PERMA_FROZEN_PLAYER = 5006, - LANG_INSTANCE_RAID_GROUP_ONLY = 5007, + // = 5007, unused LANG_INSTANCE_CLOSED = 5008, LANG_COMMAND_PLAYED_TO_ALL = 5009, LANG_NPCINFO_LINKGUID = 5010, @@ -1212,6 +1212,8 @@ enum TrinityStrings LANG_CREATURE_NO_INTERIOR_POINT_FOUND = 11011, LANG_CREATURE_MOVEMENT_NOT_BOUNDED = 11012, LANG_CREATURE_MOVEMENT_MAYBE_UNBOUNDED = 11013, - LANG_INSTANCE_BIND_MISMATCH = 11014 + LANG_INSTANCE_BIND_MISMATCH = 11014, + LANG_CREATURE_NOT_AI_ENABLED = 11015, + LANG_SELECT_PLAYER_OR_PET = 11016, }; #endif diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h index aa45c5024e6..b9df9e3accc 100644 --- a/src/server/game/Miscellaneous/SharedDefines.h +++ b/src/server/game/Miscellaneous/SharedDefines.h @@ -456,7 +456,7 @@ enum SpellAttr4 enum SpellAttr5 { - SPELL_ATTR5_UNK0 = 0x00000001, // 0 + SPELL_ATTR5_CAN_CHANNEL_WHEN_MOVING = 0x00000001, // 0 available casting channel spell when moving SPELL_ATTR5_NO_REAGENT_WHILE_PREP = 0x00000002, // 1 not need reagents if UNIT_FLAG_PREPARATION SPELL_ATTR5_UNK2 = 0x00000004, // 2 SPELL_ATTR5_USABLE_WHILE_STUNNED = 0x00000008, // 3 usable while stunned @@ -828,7 +828,7 @@ enum SpellEffects SPELL_EFFECT_CREATE_ITEM_2 = 157, SPELL_EFFECT_MILLING = 158, SPELL_EFFECT_ALLOW_RENAME_PET = 159, - SPELL_EFFECT_160 = 160, + SPELL_EFFECT_FORCE_CAST_2 = 160, SPELL_EFFECT_TALENT_SPEC_COUNT = 161, SPELL_EFFECT_TALENT_SPEC_SELECT = 162, SPELL_EFFECT_163 = 163, @@ -2531,6 +2531,7 @@ uint32 const CREATURE_TYPEMASK_MECHANICAL_OR_ELEMENTAL = (1 << (CREATURE_TYPE_ME // CreatureFamily.dbc enum CreatureFamily { + CREATURE_FAMILY_NONE = 0, CREATURE_FAMILY_WOLF = 1, CREATURE_FAMILY_CAT = 2, CREATURE_FAMILY_SPIDER = 3, @@ -2576,38 +2577,38 @@ enum CreatureFamily enum CreatureTypeFlags { - CREATURE_TYPEFLAGS_TAMEABLE = 0x00000001, // Tameable by any hunter - CREATURE_TYPEFLAGS_GHOST = 0x00000002, // Creature are also visible for not alive player. Allow gossip interaction if npcflag allow? - CREATURE_TYPEFLAGS_BOSS = 0x00000004, - CREATURE_TYPEFLAGS_UNK3 = 0x00000008, - CREATURE_TYPEFLAGS_UNK4 = 0x00000010, - CREATURE_TYPEFLAGS_UNK5 = 0x00000020, - CREATURE_TYPEFLAGS_UNK6 = 0x00000040, - CREATURE_TYPEFLAGS_DEAD_INTERACT = 0x00000080, // Player can interact with the creature if its dead (not player dead) - CREATURE_TYPEFLAGS_HERBLOOT = 0x00000100, // Can be looted by herbalist - CREATURE_TYPEFLAGS_MININGLOOT = 0x00000200, // Can be looted by miner - CREATURE_TYPEFLAGS_DONT_LOG_DEATH = 0x00000400, // Death event will not show up in combat log - CREATURE_TYPEFLAGS_MOUNTED_COMBAT = 0x00000800, // Creature can remain mounted when entering combat - CREATURE_TYPEFLAGS_AID_PLAYERS = 0x00001000, // ? Can aid any player in combat if in range? - CREATURE_TYPEFLAGS_UNK13 = 0x00002000, - CREATURE_TYPEFLAGS_UNK14 = 0x00004000, // ? Possibly not in use - CREATURE_TYPEFLAGS_ENGINEERLOOT = 0x00008000, // Can be looted by engineer - CREATURE_TYPEFLAGS_EXOTIC = 0x00010000, // Can be tamed by hunter as exotic pet - CREATURE_TYPEFLAGS_UNK17 = 0x00020000, // ? Related to vehicles/pvp? - CREATURE_TYPEFLAGS_UNK18 = 0x00040000, // ? Related to vehicle/siege weapons? - CREATURE_TYPEFLAGS_PROJECTILE_COLLISION = 0x00080000, // Projectiles can collide with this creature - interacts with TARGET_DEST_TRAJ - CREATURE_TYPEFLAGS_UNK20 = 0x00100000, - CREATURE_TYPEFLAGS_UNK21 = 0x00200000, - CREATURE_TYPEFLAGS_UNK22 = 0x00400000, - CREATURE_TYPEFLAGS_UNK23 = 0x00800000, // ? First seen in 3.2.2. Related to banner/backpack of creature/companion? - CREATURE_TYPEFLAGS_UNK24 = 0x01000000, - CREATURE_TYPEFLAGS_UNK25 = 0x02000000, - CREATURE_TYPEFLAGS_PARTY_MEMBER = 0x04000000, //! Creature can be targeted by spells that require target to be in caster's party/raid - CREATURE_TYPEFLAGS_UNK27 = 0x08000000, - CREATURE_TYPEFLAGS_UNK28 = 0x10000000, - CREATURE_TYPEFLAGS_UNK29 = 0x20000000, - CREATURE_TYPEFLAGS_UNK30 = 0x40000000, - CREATURE_TYPEFLAGS_UNK31 = 0x80000000 + CREATURE_TYPE_FLAG_TAMEABLE_PET = 0x00000001, // Makes the mob tameable (must also be a beast and have family set) + CREATURE_TYPE_FLAG_GHOST_VISIBLE = 0x00000002, // Creature are also visible for not alive player. Allow gossip interaction if npcflag allow? + CREATURE_TYPE_FLAG_BOSS_MOB = 0x00000004, // Changes creature's visible level to "??" in the creature's portrait - Immune Knockback. + CREATURE_TYPE_FLAG_DO_NOT_PLAY_WOUND_PARRY_ANIMATION = 0x00000008, + CREATURE_TYPE_FLAG_HIDE_FACTION_TOOLTIP = 0x00000010, + CREATURE_TYPE_FLAG_UNK5 = 0x00000020, // Sound related + CREATURE_TYPE_FLAG_SPELL_ATTACKABLE = 0x00000040, + CREATURE_TYPE_FLAG_CAN_INTERACT_WHILE_DEAD = 0x00000080, // Player can interact with the creature if its dead (not player dead) + CREATURE_TYPE_FLAG_HERB_SKINNING_SKILL = 0x00000100, // Can be looted by herbalist + CREATURE_TYPE_FLAG_MINING_SKINNING_SKILL = 0x00000200, // Can be looted by miner + CREATURE_TYPE_FLAG_DO_NOT_LOG_DEATH = 0x00000400, // Death event will not show up in combat log + CREATURE_TYPE_FLAG_MOUNTED_COMBAT_ALLOWED = 0x00000800, // Creature can remain mounted when entering combat + CREATURE_TYPE_FLAG_CAN_ASSIST = 0x00001000, // ? Can aid any player in combat if in range? + CREATURE_TYPE_FLAG_IS_PET_BAR_USED = 0x00002000, + CREATURE_TYPE_FLAG_MASK_UID = 0x00004000, + CREATURE_TYPE_FLAG_ENGINEERING_SKINNING_SKILL = 0x00008000, // Can be looted by engineer + CREATURE_TYPE_FLAG_EXOTIC_PET = 0x00010000, // Can be tamed by hunter as exotic pet + CREATURE_TYPE_FLAG_USE_DEFAULT_COLLISION_BOX = 0x00020000, // Collision related. (always using default collision box?) + CREATURE_TYPE_FLAG_IS_SIEGE_WEAPON = 0x00040000, + CREATURE_TYPE_FLAG_CAN_COLLIDE_WITH_MISSILES = 0x00080000, // Projectiles can collide with this creature - interacts with TARGET_DEST_TRAJ + CREATURE_TYPE_FLAG_HIDE_NAME_PLATE = 0x00100000, + CREATURE_TYPE_FLAG_DO_NOT_PLAY_MOUNTED_ANIMATIONS = 0x00200000, + CREATURE_TYPE_FLAG_IS_LINK_ALL = 0x00400000, + CREATURE_TYPE_FLAG_INTERACT_ONLY_WITH_CREATOR = 0x00800000, + CREATURE_TYPE_FLAG_DO_NOT_PLAY_UNIT_EVENT_SOUNDS = 0x01000000, + CREATURE_TYPE_FLAG_HAS_NO_SHADOW_BLOB = 0x02000000, + CREATURE_TYPE_FLAG_TREAT_AS_RAID_UNIT = 0x04000000, // ! Creature can be targeted by spells that require target to be in caster's party/raid + CREATURE_TYPE_FLAG_FORCE_GOSSIP = 0x08000000, // Allows the creature to display a single gossip option. + CREATURE_TYPE_FLAG_DO_NOT_SHEATHE = 0x10000000, + CREATURE_TYPE_FLAG_DO_NOT_TARGET_ON_INTERACTION = 0x20000000, + CREATURE_TYPE_FLAG_DO_NOT_RENDER_OBJECT_NAME = 0x40000000, + CREATURE_TYPE_FLAG_UNIT_IS_QUEST_BOSS = 0x80000000 // Not verified }; enum CreatureEliteType diff --git a/src/server/game/Movement/MotionMaster.cpp b/src/server/game/Movement/MotionMaster.cpp index f27e47fba21..6f7dae1d4f2 100644 --- a/src/server/game/Movement/MotionMaster.cpp +++ b/src/server/game/Movement/MotionMaster.cpp @@ -241,7 +241,7 @@ void MotionMaster::MoveConfused() void MotionMaster::MoveChase(Unit* target, float dist, float angle) { // ignore movement request if target not exist - if (!target || target == _owner || _owner->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE)) + if (!target || target == _owner) return; //_owner->ClearUnitState(UNIT_STATE_FOLLOW); @@ -266,7 +266,7 @@ void MotionMaster::MoveChase(Unit* target, float dist, float angle) void MotionMaster::MoveFollow(Unit* target, float dist, float angle, MovementSlot slot) { // ignore movement request if target not exist - if (!target || target == _owner || _owner->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE)) + if (!target || target == _owner) return; //_owner->AddUnitState(UNIT_STATE_FOLLOW); diff --git a/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp index 108276c951a..6f6a8037d47 100755 --- a/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp @@ -23,11 +23,6 @@ #include "MoveSpline.h" #include "Player.h" -#ifdef MAP_BASED_RAND_GEN -#define rand_norm() unit.rand_norm() -#define urand(a, b) unit.urand(a, b) -#endif - template<class T> void ConfusedMovementGenerator<T>::DoInitialize(T* unit) { diff --git a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp index 2e013c44ae8..421678ded17 100644 --- a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp @@ -26,10 +26,6 @@ #define RUNNING_CHANCE_RANDOMMV 20 //will be "1 / RUNNING_CHANCE_RANDOMMV" -#ifdef MAP_BASED_RAND_GEN -#define rand_norm() creature.rand_norm() -#endif - template<> void RandomMovementGenerator<Creature>::_setRandomLocation(Creature* creature) { diff --git a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp index d3c6c70c4ed..3fd3b702ba5 100644 --- a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp @@ -36,8 +36,14 @@ void TargetedMovementGeneratorMedium<T, D>::_setTargetLocation(T* owner, bool up if (owner->HasUnitState(UNIT_STATE_NOT_MOVE)) return; + if (owner->HasUnitState(UNIT_STATE_CASTING) && !owner->CanMoveDuringChannel()) + return; + if (owner->GetTypeId() == TYPEID_UNIT && !i_target->isInAccessiblePlaceFor(owner->ToCreature())) + { + owner->ToCreature()->SetCannotReachTarget(true); return; + } if (owner->GetTypeId() == TYPEID_UNIT && owner->ToCreature()->IsFocusing(nullptr, true)) return; @@ -48,6 +54,9 @@ void TargetedMovementGeneratorMedium<T, D>::_setTargetLocation(T* owner, bool up { if (!i_offset) { + if (i_target->IsWithinDistInMap(owner, CONTACT_DISTANCE)) + return; + // to nearest contact position i_target->GetContactPoint(owner, x, y, z); } @@ -99,8 +108,10 @@ void TargetedMovementGeneratorMedium<T, D>::_setTargetLocation(T* owner, bool up bool result = i_path->CalculatePath(x, y, z, forceDest); if (!result || (i_path->GetPathType() & PATHFIND_NOPATH)) { - // Cant reach target + // can't reach target i_recalculateTravel = true; + if (owner->GetTypeId() == TYPEID_UNIT) + owner->ToCreature()->SetCannotReachTarget(true); return; } @@ -108,6 +119,8 @@ void TargetedMovementGeneratorMedium<T, D>::_setTargetLocation(T* owner, bool up i_targetReached = false; i_recalculateTravel = false; owner->AddUnitState(UNIT_STATE_CHASE); + if (owner->GetTypeId() == TYPEID_UNIT) + owner->ToCreature()->SetCannotReachTarget(false); Movement::MoveSplineInit init(owner); init.MovebyPath(i_path->GetPath()); @@ -136,7 +149,7 @@ bool TargetedMovementGeneratorMedium<T, D>::DoUpdate(T* owner, uint32 time_diff) } // prevent movement while casting spells with cast time or channel time - if (owner->HasUnitState(UNIT_STATE_CASTING)) + if (owner->HasUnitState(UNIT_STATE_CASTING) && !owner->CanMoveDuringChannel()) { if (!owner->IsStopped()) owner->StopMoving(); @@ -198,6 +211,8 @@ void ChaseMovementGenerator<T>::_reachTarget(T* owner) { if (owner->IsWithinMeleeRange(this->i_target.getTarget())) owner->Attack(this->i_target.getTarget(), true); + if (owner->GetTypeId() == TYPEID_UNIT) + owner->ToCreature()->SetCannotReachTarget(false); } template<> diff --git a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp index 48d29b3259b..2ffa1a644eb 100755 --- a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp @@ -213,7 +213,7 @@ bool WaypointMovementGenerator<Creature>::DoUpdate(Creature* creature, uint32 di creature->SetHomePosition(creature->GetPosition()); if (creature->IsStopped()) - Stop(STOP_TIME_FOR_PLAYER); + Stop(sWorld->getIntConfig(CONFIG_CREATURE_STOP_FOR_PLAYER)); else if (creature->movespline->Finalized()) { OnArrived(creature); @@ -315,7 +315,7 @@ void FlightPathMovementGenerator::DoFinalize(Player* player) player->ClearUnitState(UNIT_STATE_IN_FLIGHT); player->Dismount(); - player->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_TAXI_FLIGHT); + player->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL | UNIT_FLAG_TAXI_FLIGHT); if (player->m_taxi.empty()) { @@ -335,7 +335,7 @@ void FlightPathMovementGenerator::DoReset(Player* player) { player->getHostileRefManager().setOnlineOfflineState(false); player->AddUnitState(UNIT_STATE_IN_FLIGHT); - player->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_TAXI_FLIGHT); + player->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL | UNIT_FLAG_TAXI_FLIGHT); Movement::MoveSplineInit init(player); uint32 end = GetPathAtMapEnd(); diff --git a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h index 1dd4611d53b..72309822dab 100755 --- a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h @@ -28,9 +28,9 @@ #include "MovementGenerator.h" #include "WaypointManager.h" #include "Player.h" +#include "World.h" #define FLIGHT_TRAVEL_UPDATE 100 -#define STOP_TIME_FOR_PLAYER 3 * MINUTE * IN_MILLISECONDS // 3 Minutes #define TIMEDIFF_NEXT_WP 250 template<class T, class P> diff --git a/src/server/game/Scripting/ScriptMgr.cpp b/src/server/game/Scripting/ScriptMgr.cpp index ca1cd71363e..ac440da3f24 100644 --- a/src/server/game/Scripting/ScriptMgr.cpp +++ b/src/server/game/Scripting/ScriptMgr.cpp @@ -368,6 +368,8 @@ class CreatureGameObjectScriptRegistrySwapHooks // Hook which is called before a creature is swapped static void UnloadStage1(Creature* creature) { + creature->m_Events.KillAllEvents(true); + if (creature->IsCharmed()) creature->RemoveCharmedBy(nullptr); diff --git a/src/server/game/Scripting/ScriptReloadMgr.cpp b/src/server/game/Scripting/ScriptReloadMgr.cpp index 8b14ca8aeeb..d13fa9c30f0 100644 --- a/src/server/game/Scripting/ScriptReloadMgr.cpp +++ b/src/server/game/Scripting/ScriptReloadMgr.cpp @@ -56,6 +56,7 @@ ScriptReloadMgr* ScriptReloadMgr::instance() #include "Config.h" #include "BuiltInConfig.h" #include "ScriptMgr.h" +#include "SHA1.h" #include "StartProcess.h" #include "MPSCQueue.h" #include "GitRevision.h" @@ -64,8 +65,10 @@ namespace fs = boost::filesystem; #ifdef _WIN32 #include <windows.h> + #define HOTSWAP_PLATFORM_REQUIRES_CACHING #else // Posix #include <dlfcn.h> + // #define HOTSWAP_PLATFORM_REQUIRES_CACHING #endif // Promote the sScriptReloadMgr to a HotSwapScriptReloadMgr @@ -99,13 +102,25 @@ typedef HMODULE HandleType; typedef void* HandleType; #endif +static fs::path GetDirectoryOfExecutable() +{ + ASSERT((!sConfigMgr->GetArguments().empty()), + "Expected the arguments to contain at least 1 element!"); + + fs::path path(sConfigMgr->GetArguments()[0]); + if (path.is_absolute()) + return path.parent_path(); + else + return fs::absolute(path).parent_path(); +} + class SharedLibraryUnloader { public: - SharedLibraryUnloader() - : _path() { } - explicit SharedLibraryUnloader(fs::path const& path) - : _path(path) { } + explicit SharedLibraryUnloader(fs::path path) + : path_(std::move(path)) { } + SharedLibraryUnloader(fs::path path, Optional<fs::path> cache_path) + : path_(std::move(path)), cache_path_(std::move(cache_path)) { } void operator() (HandleType handle) const { @@ -119,26 +134,37 @@ public: if (!success) { TC_LOG_ERROR("scripts.hotswap", "Failed to unload (syscall) the shared library \"%s\".", - _path.generic_string().c_str()); + path_.generic_string().c_str()); return; } - boost::system::error_code error; - if (fs::remove(_path, error)) + /// When the shared library was cached delete it's shared version + if (cache_path_) { - TC_LOG_TRACE("scripts.hotswap", "Lazy unloaded and deleted the shared library \"%s\".", - _path.generic_string().c_str()); + boost::system::error_code error; + if (!fs::remove(*cache_path_, error)) + { + TC_LOG_ERROR("scripts.hotswap", "Failed to delete the cached shared library \"%s\" (%s).", + cache_path_->generic_string().c_str(), error.message().c_str()); + + return; + } + + TC_LOG_TRACE("scripts.hotswap", "Lazy unloaded the shared library \"%s\" " + "and deleted it's cached version at \"%s\"", + path_.generic_string().c_str(), cache_path_->generic_string().c_str()); } else { - TC_LOG_ERROR("scripts.hotswap", "Failed to delete the shared library \"%s\" (%s).", - _path.generic_string().c_str(), error.message().c_str()); + TC_LOG_TRACE("scripts.hotswap", "Lazy unloaded the shared library \"%s\".", + path_.generic_string().c_str()); } } private: - fs::path _path; + fs::path const path_; + Optional<fs::path> const cache_path_; }; typedef std::unique_ptr<typename std::remove_pointer<HandleType>::type, SharedLibraryUnloader> HandleHolder; @@ -165,7 +191,8 @@ public: ScriptModule& operator= (ScriptModule const&) = delete; ScriptModule& operator= (ScriptModule&& right) = delete; - static Optional<std::shared_ptr<ScriptModule>> CreateFromPath(fs::path const& path); + static Optional<std::shared_ptr<ScriptModule>> + CreateFromPath(fs::path const& path, Optional<fs::path> cache_path); char const* GetScriptModuleRevisionHash() const override { @@ -215,23 +242,41 @@ static bool GetFunctionFromSharedLibrary(HandleType handle, std::string const& n } // Load a shared library from the given path. -Optional<std::shared_ptr<ScriptModule>> ScriptModule::CreateFromPath(fs::path const& path) +Optional<std::shared_ptr<ScriptModule>> + ScriptModule::CreateFromPath(fs::path const& path, Optional<fs::path> cache_path) { + auto const load_path = [&] () -> fs::path { + if (cache_path) + return *cache_path; + else + return path; + }(); + #ifdef _WIN32 - HandleType handle = LoadLibrary(path.generic_string().c_str()); + HandleType handle = LoadLibrary(load_path.generic_string().c_str()); #else // Posix - HandleType handle = dlopen(path.c_str(), RTLD_LAZY); + HandleType handle = dlopen(load_path.generic_string().c_str(), RTLD_LAZY); #endif if (!handle) { - TC_LOG_ERROR("scripts.hotswap", "Could not load the shared library \"%s\" for reading.", - path.generic_string().c_str()); + if (cache_path) + { + TC_LOG_ERROR("scripts.hotswap", "Could not dynamic load the shared library \"%s\" " + "(the library is cached at %s)", + path.generic_string().c_str(), cache_path->generic_string().c_str()); + } + else + { + TC_LOG_ERROR("scripts.hotswap", "Could not dynamic load the shared library \"%s\".", + path.generic_string().c_str()); + } + return boost::none; } // Use RAII to release the library on failure. - HandleHolder holder(handle, SharedLibraryUnloader(path)); + HandleHolder holder(handle, SharedLibraryUnloader(path, std::move(cache_path))); GetScriptModuleRevisionHashType getScriptModuleRevisionHash; AddScriptsType addScripts; @@ -357,7 +402,7 @@ static bool IsDebuggerBlockingRebuild() /// /// This class manages shared library loading/unloading through watching /// the script module directory. Loaded shared libraries are mirrored -/// into a .cache subdirectory to allow lazy unloading as long as +/// into a cache subdirectory to allow lazy unloading as long as /// the shared library is still used which is useful for scripts /// which can't be instantly replaced like spells or instances. /// Several modules which reference different versions can be kept loaded @@ -400,6 +445,8 @@ class HotSwapScriptReloadMgr final // like "Release" or "Debug". The build directive from the // previous same module is used if there was any. std::string script_module_build_directive_; + // The time where the build job started + uint32 start_time_; // Type of the current running job BuildJobType type_; @@ -412,7 +459,7 @@ class HotSwapScriptReloadMgr final : script_module_name_(std::move(script_module_name)), script_module_project_name_(std::move(script_module_project_name)), script_module_build_directive_(std::move(script_module_build_directive)), - type_(BuildJobType::BUILD_JOB_NONE) { } + start_time_(getMSTime()), type_(BuildJobType::BUILD_JOB_NONE) { } bool IsValid() const { @@ -425,6 +472,8 @@ class HotSwapScriptReloadMgr final std::string const& GetBuildDirective() const { return script_module_build_directive_; } + uint32 GetTimeFromStart() const { return GetMSTimeDiffToNow(start_time_); } + BuildJobType GetType() const { return type_; } std::shared_ptr<Trinity::AsyncProcessResult> const& GetProcess() const @@ -500,7 +549,13 @@ public: /// Returns the absolute path to the script module directory static fs::path GetLibraryDirectory() { - return fs::absolute(sConfigMgr->GetStringDefault("HotSwap.ScriptDir", "scripts")); + // When an absolute path is given in the config use it, + // otherwise interpret paths relative to the executable. + fs::path path(sConfigMgr->GetStringDefault("HotSwap.ScriptDir", "scripts")); + if (path.is_absolute()) + return path; + else + return fs::absolute(path, GetDirectoryOfExecutable()); } /// Returns the absolute path to the scripts directory in the source tree. @@ -541,28 +596,28 @@ public: } } - // Get the cache directory path - fs::path const cache_path = [] - { - auto path = fs::absolute(sScriptReloadMgr->GetLibraryDirectory()); - path /= ".cache"; - return path; - }(); + #ifdef HOTSWAP_PLATFORM_REQUIRES_CACHING + + temporary_cache_path_ = CalculateTemporaryCachePath(); // We use the boost filesystem function versions which accept // an error code to prevent it from throwing exceptions. boost::system::error_code code; - if ((!fs::exists(cache_path, code) || (fs::remove_all(cache_path, code) > 0)) && - !fs::create_directory(cache_path, code)) + if ((!fs::exists(temporary_cache_path_, code) + || (fs::remove_all(temporary_cache_path_, code) > 0)) && + !fs::create_directory(temporary_cache_path_, code)) { - TC_LOG_ERROR("scripts.hotswap", "Couldn't create the cache directory \"%s\".", - cache_path.generic_string().c_str()); + TC_LOG_ERROR("scripts.hotswap", "Couldn't create the cache directory at \"%s\".", + temporary_cache_path_.generic_string().c_str()); + return; } // Used to silent compiler warnings (void)code; + #endif // #ifdef HOTSWAP_PLATFORM_REQUIRES_CACHING + // Correct the CMake prefix when needed if (sWorld->getBoolConfig(CONFIG_HOTSWAP_PREFIX_CORRECTION_ENABLED)) DoCMakePrefixCorrectionIfNeeded(); @@ -694,6 +749,31 @@ private: _fileWatcher.watch(); } + static fs::path CalculateTemporaryCachePath() + { + auto path = fs::temp_directory_path(); + path /= Trinity::StringFormat("tc_script_cache_%s_%s", + GitRevision::GetBranch(), + CalculateSHA1Hash(sConfigMgr->GetFilename()).c_str()); + + return path; + } + + fs::path GenerateUniquePathForLibraryInCache(fs::path path) + { + ASSERT(!temporary_cache_path_.empty(), + "The temporary cache path wasn't set!"); + + // Create the cache path and increment the library counter to use an unique name for each library + auto cache_path = temporary_cache_path_; + cache_path /= Trinity::StringFormat("%s.%u%s", + path.stem().generic_string().c_str(), + _unique_library_name_counter++, + path.extension().generic_string().c_str()); + + return cache_path; + } + /// Updates the current state of the given source path void UpdateSourceChangeRequest(std::string const& module_name, fs::path const& path, @@ -774,31 +854,37 @@ private: ASSERT(_running_script_module_names.find(path) == _running_script_module_names.end(), "Can't load a module which is running already!"); - // Create the cache path and increment the library counter to use an unique name for each library - fs::path cache_path = fs::absolute(sScriptReloadMgr->GetLibraryDirectory()); - cache_path /= ".cache"; - cache_path /= Trinity::StringFormat("%s.%u%s", - path.stem().generic_string().c_str(), - _unique_library_name_counter++, - path.extension().generic_string().c_str()); + Optional<fs::path> cache_path; + + #ifdef HOTSWAP_PLATFORM_REQUIRES_CACHING + + // Copy the shared library into a cache on platforms which lock files on use (windows). + cache_path = GenerateUniquePathForLibraryInCache(path); - boost::system::error_code code; - fs::copy_file(path, cache_path, fs::copy_option::fail_if_exists, code); - if (code) { - TC_LOG_FATAL("scripts.hotswap", ">> Failed to create cache entry for module " - "\"%s\" at \"%s\" with reason (\"%s\")!", - path.filename().generic_string().c_str(), cache_path.generic_string().c_str(), - code.message().c_str()); + boost::system::error_code code; + fs::copy_file(path, *cache_path, fs::copy_option::fail_if_exists, code); + if (code) + { + TC_LOG_FATAL("scripts.hotswap", ">> Failed to create cache entry for module " + "\"%s\" at \"%s\" with reason (\"%s\")!", + path.filename().generic_string().c_str(), cache_path->generic_string().c_str(), + code.message().c_str()); + + // Find a better solution for this but it's much better + // to start the core without scripts + std::this_thread::sleep_for(std::chrono::seconds(5)); + ABORT(); + return; + } - // Find a better solution for this but it's much better - // to start the core without scripts - std::this_thread::sleep_for(std::chrono::seconds(5)); - ABORT(); - return; + TC_LOG_TRACE("scripts.hotswap", ">> Copied the shared library \"%s\" to \"%s\" for caching.", + path.filename().generic_string().c_str(), cache_path->generic_string().c_str()); } - auto module = ScriptModule::CreateFromPath(cache_path); + #endif // #ifdef HOTSWAP_PLATFORM_REQUIRES_CACHING + + auto module = ScriptModule::CreateFromPath(path, cache_path); if (!module) { TC_LOG_FATAL("scripts.hotswap", ">> Failed to load script module \"%s\"!", @@ -1116,8 +1202,9 @@ private: if (!error) { // Installation was successful - TC_LOG_INFO("scripts.hotswap", ">> Successfully installed module %s.", - _build_job->GetModuleName().c_str()); + TC_LOG_INFO("scripts.hotswap", ">> Successfully installed module %s in %us", + _build_job->GetModuleName().c_str(), + _build_job->GetTimeFromStart() / IN_MILLISECONDS); } else { @@ -1246,7 +1333,7 @@ private: #ifndef _WIN32 // The worldserver location is ${CMAKE_INSTALL_PREFIX}/bin // on all other platforms then windows - current_path = current_path.remove_leaf(); + current_path = current_path.parent_path(); #endif if (value != current_path) @@ -1262,7 +1349,7 @@ private: if (base == branch) return true; - branch = branch.remove_leaf(); + branch = branch.parent_path(); } return false; @@ -1343,6 +1430,9 @@ private: // Is true when the build job dispatcher should stop after // the current job has finished bool terminate_early; + + // The path to the tc_scripts temporary cache + fs::path temporary_cache_path_; }; /// Maps efsw actions to strings diff --git a/src/server/game/Server/Protocol/PacketLog.cpp b/src/server/game/Server/Protocol/PacketLog.cpp index 11a02828998..114b2ae0ecc 100644 --- a/src/server/game/Server/Protocol/PacketLog.cpp +++ b/src/server/game/Server/Protocol/PacketLog.cpp @@ -45,7 +45,7 @@ struct PacketHeader uint32 SocketPort; }; - char Direction[4]; + uint32 Direction; uint32 ConnectionId; uint32 ArrivalTicks; uint32 OptionalDataSize; @@ -109,7 +109,7 @@ void PacketLog::LogPacket(WorldPacket const& packet, Direction direction, boost: std::lock_guard<std::mutex> lock(_logPacketLock); PacketHeader header; - *reinterpret_cast<uint32*>(header.Direction) = direction == CLIENT_TO_SERVER ? 0x47534d43 : 0x47534d53; + header.Direction = direction == CLIENT_TO_SERVER ? 0x47534d43 : 0x47534d53; header.ConnectionId = 0; header.ArrivalTicks = getMSTime(); diff --git a/src/server/game/Server/WorldSocket.cpp b/src/server/game/Server/WorldSocket.cpp index e3c6179a34a..1c77283d812 100644 --- a/src/server/game/Server/WorldSocket.cpp +++ b/src/server/game/Server/WorldSocket.cpp @@ -344,11 +344,12 @@ WorldSocket::ReadDataHandlerResult WorldSocket::ReadDataHandler() default: { sessionGuard.lock(); + LogOpcodeText(opcode, sessionGuard); + if (!_worldSession) { TC_LOG_ERROR("network.opcode", "ProcessIncoming: Client not authed opcode = %u", uint32(opcode)); - CloseSocket(); return ReadDataHandlerResult::Error; } diff --git a/src/server/game/Spells/Auras/SpellAuraDefines.h b/src/server/game/Spells/Auras/SpellAuraDefines.h index e0daf59fcc2..02dd88e582a 100644 --- a/src/server/game/Spells/Auras/SpellAuraDefines.h +++ b/src/server/game/Spells/Auras/SpellAuraDefines.h @@ -348,7 +348,7 @@ enum AuraType SPELL_AURA_ABILITY_PERIODIC_CRIT = 286, SPELL_AURA_DEFLECT_SPELLS = 287, SPELL_AURA_IGNORE_HIT_DIRECTION = 288, - SPELL_AURA_289 = 289, + SPELL_AURA_PREVENT_DURABILITY_LOSS = 289, SPELL_AURA_MOD_CRIT_PCT = 290, SPELL_AURA_MOD_XP_QUEST_PCT = 291, SPELL_AURA_OPEN_STABLE = 292, diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 459f273b790..9b23caef9ab 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -346,7 +346,7 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]= &AuraEffect::HandleNoImmediateEffect, //286 SPELL_AURA_ABILITY_PERIODIC_CRIT implemented in AuraEffect::PeriodicTick &AuraEffect::HandleNoImmediateEffect, //287 SPELL_AURA_DEFLECT_SPELLS implemented in Unit::MagicSpellHitResult and Unit::MeleeSpellHitResult &AuraEffect::HandleNoImmediateEffect, //288 SPELL_AURA_IGNORE_HIT_DIRECTION implemented in Unit::MagicSpellHitResult and Unit::MeleeSpellHitResult Unit::RollMeleeOutcomeAgainst - &AuraEffect::HandleNULL, //289 unused (3.2.0) + &AuraEffect::HandleNoImmediateEffect, //289 SPELL_AURA_PREVENT_DURABILITY_LOSS implemented in Player::DurabilityPointsLoss &AuraEffect::HandleAuraModCritPct, //290 SPELL_AURA_MOD_CRIT_PCT &AuraEffect::HandleNoImmediateEffect, //291 SPELL_AURA_MOD_XP_QUEST_PCT implemented in Player::RewardQuest &AuraEffect::HandleAuraOpenStable, //292 SPELL_AURA_OPEN_STABLE @@ -4676,7 +4676,7 @@ void AuraEffect::HandleAuraDummy(AuraApplication const* aurApp, uint8 mode, bool case 71563: if (Aura* newAura = target->AddAura(71564, target)) newAura->SetStackAmount(newAura->GetSpellInfo()->StackAmount); - break; + break; } } // AT REMOVE @@ -5969,9 +5969,6 @@ void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) c caster->SendSpellNonMeleeDamageLog(target, GetId(), damage, GetSpellInfo()->GetSchoolMask(), absorb, resist, false, 0, crit); - if (target->GetHealth() < damage) - damage = uint32(target->GetHealth()); - // Set trigger flag uint32 procAttacker = PROC_FLAG_DONE_PERIODIC; uint32 procVictim = PROC_FLAG_TAKEN_PERIODIC; diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp index 1ca5df6b327..3d35e4039ba 100644 --- a/src/server/game/Spells/Auras/SpellAuras.cpp +++ b/src/server/game/Spells/Auras/SpellAuras.cpp @@ -337,7 +337,8 @@ m_spellInfo(spellproto), m_casterGuid(casterGUID ? casterGUID : caster->GetGUID( m_castItemGuid(castItem ? castItem->GetGUID() : ObjectGuid::Empty), m_applyTime(time(NULL)), m_owner(owner), m_timeCla(0), m_updateTargetMapInterval(0), m_casterLevel(caster ? caster->getLevel() : m_spellInfo->SpellLevel), m_procCharges(0), m_stackAmount(1), -m_isRemoved(false), m_isSingleTarget(false), m_isUsingCharges(false), m_dropEvent(nullptr) +m_isRemoved(false), m_isSingleTarget(false), m_isUsingCharges(false), m_dropEvent(nullptr), +m_procCooldown(std::chrono::steady_clock::time_point::min()) { if (m_spellInfo->ManaPerSecond || m_spellInfo->ManaPerSecondPerLevel) m_timeCla = 1 * IN_MILLISECONDS; @@ -789,7 +790,7 @@ uint8 Aura::CalcMaxCharges(Unit* caster) const { uint32 maxProcCharges = m_spellInfo->ProcCharges; if (SpellProcEntry const* procEntry = sSpellMgr->GetSpellProcEntry(GetId())) - maxProcCharges = procEntry->charges; + maxProcCharges = procEntry->Charges; if (caster) if (Player* modOwner = caster->GetSpellModOwner()) @@ -1851,22 +1852,17 @@ bool Aura::CanStackWith(Aura const* existingAura) const return true; } -bool Aura::IsProcOnCooldown() const +bool Aura::IsProcOnCooldown(std::chrono::steady_clock::time_point now) const { - /*if (m_procCooldown) - { - if (m_procCooldown > time(NULL)) - return true; - }*/ - return false; + return m_procCooldown > now; } -void Aura::AddProcCooldown(uint32 /*msec*/) +void Aura::AddProcCooldown(std::chrono::steady_clock::time_point cooldownEnd) { - //m_procCooldown = time(NULL) + msec; + m_procCooldown = cooldownEnd; } -void Aura::PrepareProcToTrigger(AuraApplication* aurApp, ProcEventInfo& eventInfo) +void Aura::PrepareProcToTrigger(AuraApplication* aurApp, ProcEventInfo& eventInfo, std::chrono::steady_clock::time_point now) { bool prepare = CallScriptPrepareProcHandlers(aurApp, eventInfo); if (!prepare) @@ -1884,10 +1880,10 @@ void Aura::PrepareProcToTrigger(AuraApplication* aurApp, ProcEventInfo& eventInf ASSERT(procEntry); // cooldowns should be added to the whole aura (see 51698 area aura) - AddProcCooldown(procEntry->cooldown); + AddProcCooldown(now + procEntry->Cooldown); } -bool Aura::IsProcTriggeredOnEvent(AuraApplication* aurApp, ProcEventInfo& eventInfo) const +bool Aura::IsProcTriggeredOnEvent(AuraApplication* aurApp, ProcEventInfo& eventInfo, std::chrono::steady_clock::time_point now) const { SpellProcEntry const* procEntry = sSpellMgr->GetSpellProcEntry(GetId()); // only auras with spell proc entry can trigger proc @@ -1899,7 +1895,7 @@ bool Aura::IsProcTriggeredOnEvent(AuraApplication* aurApp, ProcEventInfo& eventI return false; // check proc cooldown - if (IsProcOnCooldown()) + if (IsProcOnCooldown(now)) return false; /// @todo @@ -1963,16 +1959,16 @@ bool Aura::IsProcTriggeredOnEvent(AuraApplication* aurApp, ProcEventInfo& eventI float Aura::CalcProcChance(SpellProcEntry const& procEntry, ProcEventInfo& eventInfo) const { - float chance = procEntry.chance; + float chance = procEntry.Chance; // calculate chances depending on unit with caster's data // so talents modifying chances and judgements will have properly calculated proc chance if (Unit* caster = GetCaster()) { // calculate ppm chance if present and we're using weapon - if (eventInfo.GetDamageInfo() && procEntry.ratePerMinute != 0) + if (eventInfo.GetDamageInfo() && procEntry.ProcsPerMinute != 0) { uint32 WeaponSpeed = caster->GetAttackTime(eventInfo.GetDamageInfo()->GetAttackType()); - chance = caster->GetPPMProcChance(WeaponSpeed, procEntry.ratePerMinute, GetSpellInfo()); + chance = caster->GetPPMProcChance(WeaponSpeed, procEntry.ProcsPerMinute, GetSpellInfo()); } // apply chance modifer aura, applies also to ppm chance (see improved judgement of light spell) if (Player* modOwner = caster->GetSpellModOwner()) diff --git a/src/server/game/Spells/Auras/SpellAuras.h b/src/server/game/Spells/Auras/SpellAuras.h index 750110dc146..a147957f258 100644 --- a/src/server/game/Spells/Auras/SpellAuras.h +++ b/src/server/game/Spells/Auras/SpellAuras.h @@ -203,12 +203,12 @@ class TC_GAME_API Aura // this subsystem is not yet in use - the core of it is functional, but still some research has to be done // and some dependant problems fixed before it can replace old proc system (for example cooldown handling) // currently proc system functionality is implemented in Unit::ProcDamageAndSpell - bool IsProcOnCooldown() const; - void AddProcCooldown(uint32 msec); + bool IsProcOnCooldown(std::chrono::steady_clock::time_point now) const; + void AddProcCooldown(std::chrono::steady_clock::time_point cooldownEnd); bool IsUsingCharges() const { return m_isUsingCharges; } void SetUsingCharges(bool val) { m_isUsingCharges = val; } - void PrepareProcToTrigger(AuraApplication* aurApp, ProcEventInfo& eventInfo); - bool IsProcTriggeredOnEvent(AuraApplication* aurApp, ProcEventInfo& eventInfo) const; + void PrepareProcToTrigger(AuraApplication* aurApp, ProcEventInfo& eventInfo, std::chrono::steady_clock::time_point now); + bool IsProcTriggeredOnEvent(AuraApplication* aurApp, ProcEventInfo& eventInfo, std::chrono::steady_clock::time_point now) const; float CalcProcChance(SpellProcEntry const& procEntry, ProcEventInfo& eventInfo) const; void TriggerProcOnEvent(AuraApplication* aurApp, ProcEventInfo& eventInfo); @@ -269,6 +269,8 @@ class TC_GAME_API Aura ChargeDropEvent* m_dropEvent; + std::chrono::steady_clock::time_point m_procCooldown; + private: Unit::AuraApplicationList m_removedApplications; }; diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index fff69ae48df..5d96de1def9 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -979,14 +979,22 @@ void Spell::SelectImplicitChannelTargets(SpellEffIndex effIndex, SpellImplicitTa { CallScriptObjectTargetSelectHandlers(target, effIndex, targetType); if (target) - m_targets.SetDst(*target); + { + SpellDestination dest(*target); + CallScriptDestinationTargetSelectHandlers(dest, effIndex, targetType); + m_targets.SetDst(dest); + } } else TC_LOG_DEBUG("spells", "SPELL: cannot find channel spell destination for spell ID %u, effect %u", m_spellInfo->Id, effIndex); break; case TARGET_DEST_CHANNEL_CASTER: - m_targets.SetDst(*channeledSpell->GetCaster()); + { + SpellDestination dest(*channeledSpell->GetCaster()); + CallScriptDestinationTargetSelectHandlers(dest, effIndex, targetType); + m_targets.SetDst(dest); break; + } default: ASSERT(false && "Spell::SelectImplicitChannelTargets: received not implemented target type"); break; @@ -1042,7 +1050,11 @@ void Spell::SelectImplicitNearbyTargets(SpellEffIndex effIndex, SpellImplicitTar if (m_spellInfo->RequiresSpellFocus) { if (focusObject) - m_targets.SetDst(*focusObject); + { + SpellDestination dest(*focusObject); + CallScriptDestinationTargetSelectHandlers(dest, effIndex, targetType); + m_targets.SetDst(dest); + } return; } break; @@ -1068,7 +1080,6 @@ void Spell::SelectImplicitNearbyTargets(SpellEffIndex effIndex, SpellImplicitTar switch (targetType.GetObjectType()) { case TARGET_OBJECT_TYPE_UNIT: - { if (Unit* unit = target->ToUnit()) AddUnitTarget(unit, effMask, true, false); else @@ -1077,7 +1088,6 @@ void Spell::SelectImplicitNearbyTargets(SpellEffIndex effIndex, SpellImplicitTar return; } break; - } case TARGET_OBJECT_TYPE_GOBJ: if (GameObject* gobjTarget = target->ToGameObject()) AddGOTarget(gobjTarget, effMask); @@ -1088,8 +1098,12 @@ void Spell::SelectImplicitNearbyTargets(SpellEffIndex effIndex, SpellImplicitTar } break; case TARGET_OBJECT_TYPE_DEST: - m_targets.SetDst(*target); + { + SpellDestination dest(*target); + CallScriptDestinationTargetSelectHandlers(dest, effIndex, targetType); + m_targets.SetDst(dest); break; + } default: ASSERT(false && "Spell::SelectImplicitNearbyTargets: received not implemented target object type"); break; @@ -1288,18 +1302,30 @@ void Spell::SelectImplicitCasterDestTargets(SpellEffIndex effIndex, SpellImplici } default: { - float dist; + float dist = m_spellInfo->Effects[effIndex].CalcRadius(m_caster); float angle = targetType.CalcDirectionAngle(); float objSize = m_caster->GetObjectSize(); - if (targetType.GetTarget() == TARGET_DEST_CASTER_SUMMON) - dist = PET_FOLLOW_DIST; - else - dist = m_spellInfo->Effects[effIndex].CalcRadius(m_caster); if (dist < objSize) dist = objSize; - else if (targetType.GetTarget() == TARGET_DEST_CASTER_RANDOM) - dist = objSize + (dist - objSize) * float(rand_norm()); + + switch (targetType.GetTarget()) + { + case TARGET_DEST_CASTER_SUMMON: + dist = PET_FOLLOW_DIST; + break; + case TARGET_DEST_CASTER_RANDOM: + dist = objSize + (dist - objSize) * float(rand_norm()); + break; + case TARGET_DEST_CASTER_FRONT_LEFT: + case TARGET_DEST_CASTER_BACK_LEFT: + case TARGET_DEST_CASTER_FRONT_RIGHT: + case TARGET_DEST_CASTER_BACK_RIGHT: + dist = dist + objSize; + break; + default: + break; + } Position pos = dest._position; m_caster->MovePositionToFirstCollision(pos, dist, angle); @@ -1538,7 +1564,7 @@ void Spell::SelectImplicitTrajTargets(SpellEffIndex effIndex) if (Creature* creatureTarget = unit->ToCreature()) { - if (!(creatureTarget->GetCreatureTemplate()->type_flags & CREATURE_TYPEFLAGS_PROJECTILE_COLLISION)) + if (!(creatureTarget->GetCreatureTemplate()->type_flags & CREATURE_TYPE_FLAG_CAN_COLLIDE_WITH_MISSILES)) continue; } } @@ -2294,8 +2320,13 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target) } } + bool enablePvP = false; // need to check PvP state before spell effects, but act on it afterwards + if (spellHitTarget) { + // if target is flagged for pvp also flag caster if a player + if (unit->IsPvP() && m_caster->GetTypeId() == TYPEID_PLAYER) + enablePvP = true; // Decide on PvP flagging now, but act on it later. SpellMissInfo missInfo2 = DoSpellHitOnUnit(spellHitTarget, mask, target->scaleAura); if (missInfo2 != SPELL_MISS_NONE) { @@ -2448,8 +2479,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target) // Needs to be called after dealing damage/healing to not remove breaking on damage auras DoTriggersOnSpellHit(spellHitTarget, mask); - // if target is fallged for pvp also flag caster if a player - if (unit->IsPvP() && m_caster->GetTypeId() == TYPEID_PLAYER) + if (enablePvP) m_caster->ToPlayer()->UpdatePvP(true); CallScriptAfterHitHandlers(); @@ -2884,7 +2914,7 @@ void Spell::prepare(SpellCastTargets const* targets, AuraEffect const* triggered if (m_caster->GetTypeId() == TYPEID_PLAYER) m_caster->ToPlayer()->SetSpellModTakingSpell(this, true); - // Fill cost data (not use power for item casts + // Fill cost data (do not use power for item casts) m_powerCost = m_CastItem ? 0 : m_spellInfo->CalcPowerCost(m_caster, m_spellSchoolMask); if (m_caster->GetTypeId() == TYPEID_PLAYER) m_caster->ToPlayer()->SetSpellModTakingSpell(this, false); @@ -2960,12 +2990,17 @@ void Spell::prepare(SpellCastTargets const* targets, AuraEffect const* triggered } // don't allow channeled spells / spells with cast time to be cast while moving + // exception are only channeled spells that have no casttime and SPELL_ATTR5_CAN_CHANNEL_WHEN_MOVING // (even if they are interrupted on moving, spells with almost immediate effect get to have their effect processed before movement interrupter kicks in) - if ((m_spellInfo->IsChanneled() || m_casttime) && m_caster->GetTypeId() == TYPEID_PLAYER && m_caster->isMoving() && m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_MOVEMENT) + if ((m_spellInfo->IsChanneled() || m_casttime) && m_caster->GetTypeId() == TYPEID_PLAYER && (!m_caster->IsCharmed() || !m_caster->GetCharmerGUID().IsCreature()) && m_caster->isMoving() && m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_MOVEMENT) { - SendCastResult(SPELL_FAILED_MOVING); - finish(false); - return; + // 1. Is a channel spell, 2. Has no casttime, 3. And has flag to allow movement during channel + if (!(m_spellInfo->IsChanneled() && !m_casttime && m_spellInfo->HasAttribute(SPELL_ATTR5_CAN_CHANNEL_WHEN_MOVING))) + { + SendCastResult(SPELL_FAILED_MOVING); + finish(false); + return; + } } // set timer base at cast time @@ -3193,6 +3228,10 @@ void Spell::cast(bool skipCheck) return; } + if (m_spellInfo->HasAttribute(SPELL_ATTR1_DISMISS_PET)) + if (Creature* pet = ObjectAccessor::GetCreature(*m_caster, m_caster->GetPetGUID())) + pet->DespawnOrUnsummon(); + PrepareTriggersExecutedOnHit(); CallScriptOnCastHandlers(); @@ -3502,12 +3541,18 @@ void Spell::update(uint32 difftime) // check if the player caster has moved before the spell finished if ((m_caster->GetTypeId() == TYPEID_PLAYER && m_timer != 0) && - m_caster->isMoving() && (m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_MOVEMENT) && - (m_spellInfo->Effects[0].Effect != SPELL_EFFECT_STUCK || !m_caster->HasUnitMovementFlag(MOVEMENTFLAG_FALLING_FAR))) + m_caster->isMoving() && (m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_MOVEMENT && + (m_spellInfo->Effects[0].Effect != SPELL_EFFECT_STUCK || !m_caster->HasUnitMovementFlag(MOVEMENTFLAG_FALLING_FAR)))) { // don't cancel for melee, autorepeat, triggered and instant spells - if (!IsNextMeleeSwingSpell() && !IsAutoRepeat() && !IsTriggered()) - cancel(); + if (!IsNextMeleeSwingSpell() && !IsAutoRepeat() && !IsTriggered() && !(IsChannelActive() && m_spellInfo->HasAttribute(SPELL_ATTR5_CAN_CHANNEL_WHEN_MOVING))) + { + // if charmed by creature, trust the AI not to cheat and allow the cast to proceed + // @todo this is a hack, "creature" movesplines don't differentiate turning/moving right now + // however, checking what type of movement the spline is for every single spline would be really expensive + if (!m_caster->GetCharmerGUID().IsCreature()) + cancel(); + } } switch (m_spellState) @@ -4803,7 +4848,7 @@ SpellCastResult Spell::CheckCast(bool strict) // cancel autorepeat spells if cast start when moving // (not wand currently autorepeat cast delayed to moving stop anyway in spell update code) - if (m_caster->GetTypeId() == TYPEID_PLAYER && m_caster->ToPlayer()->isMoving()) + if (m_caster->GetTypeId() == TYPEID_PLAYER && m_caster->ToPlayer()->isMoving() && (!m_caster->IsCharmed() || !m_caster->GetCharmerGUID().IsCreature())) { // skip stuck spell to allow use it in falling case and apply spell limitations at movement if ((!m_caster->HasUnitMovementFlag(MOVEMENTFLAG_FALLING_FAR) || m_spellInfo->Effects[0].Effect != SPELL_EFFECT_STUCK) && @@ -5260,7 +5305,7 @@ SpellCastResult Spell::CheckCast(bool strict) switch (SummonProperties->Category) { case SUMMON_CATEGORY_PET: - if (m_caster->GetPetGUID()) + if (!m_spellInfo->HasAttribute(SPELL_ATTR1_DISMISS_PET) && m_caster->GetPetGUID()) return SPELL_FAILED_ALREADY_HAVE_SUMMON; // intentional missing break, check both GetPetGUID() and GetCharmGUID for SUMMON_CATEGORY_PET case SUMMON_CATEGORY_PUPPET: @@ -5276,7 +5321,7 @@ SpellCastResult Spell::CheckCast(bool strict) { if (m_targets.GetUnitTarget()->GetTypeId() != TYPEID_PLAYER) return SPELL_FAILED_BAD_TARGETS; - if (m_targets.GetUnitTarget()->GetPetGUID()) + if (!m_spellInfo->HasAttribute(SPELL_ATTR1_DISMISS_PET) && m_targets.GetUnitTarget()->GetPetGUID()) return SPELL_FAILED_ALREADY_HAVE_SUMMON; } break; @@ -5285,13 +5330,13 @@ SpellCastResult Spell::CheckCast(bool strict) { if (m_caster->GetPetGUID()) //let warlock do a replacement summon { - if (m_caster->GetTypeId() == TYPEID_PLAYER && m_caster->getClass() == CLASS_WARLOCK) + if (m_caster->GetTypeId() == TYPEID_PLAYER) { if (strict) //starting cast, trigger pet stun (cast by pet so it doesn't attack player) if (Pet* pet = m_caster->ToPlayer()->GetPet()) pet->CastSpell(pet, 32752, true, NULL, NULL, pet->GetGUID()); } - else + else if (!m_spellInfo->HasAttribute(SPELL_ATTR1_DISMISS_PET)) return SPELL_FAILED_ALREADY_HAVE_SUMMON; } @@ -5310,6 +5355,9 @@ SpellCastResult Spell::CheckCast(bool strict) if (!target || m_caster->ToPlayer() == target || (!target->IsInSameRaidWith(m_caster->ToPlayer()) && m_spellInfo->Id != 48955)) // refer-a-friend spell return SPELL_FAILED_BAD_TARGETS; + if (target->HasSummonPending()) + return SPELL_FAILED_SUMMON_PENDING; + // check if our map is dungeon MapEntry const* map = sMapStore.LookupEntry(m_caster->GetMapId()); if (map->IsDungeon()) @@ -5415,7 +5463,7 @@ SpellCastResult Spell::CheckCast(bool strict) if (m_spellInfo->Effects[i].ApplyAuraName == SPELL_AURA_MOD_CHARM || m_spellInfo->Effects[i].ApplyAuraName == SPELL_AURA_MOD_POSSESS) { - if (m_caster->GetPetGUID()) + if (!m_spellInfo->HasAttribute(SPELL_ATTR1_DISMISS_PET) && m_caster->GetPetGUID()) return SPELL_FAILED_ALREADY_HAVE_SUMMON; if (m_caster->GetCharmGUID()) @@ -5561,7 +5609,14 @@ SpellCastResult Spell::CheckPetCast(Unit* target) m_targets.SetUnitTarget(target); } - // cooldown + // check power requirement + // this would be zero until ::prepare normally, we set it here (it gets reset in ::prepare) + m_powerCost = m_spellInfo->CalcPowerCost(m_caster, m_spellSchoolMask); + SpellCastResult failReason = CheckPower(); + if (failReason != SPELL_CAST_OK) + return failReason; + + // check cooldown if (Creature* creatureCaster = m_caster->ToCreature()) if (!creatureCaster->GetSpellHistory()->IsReady(m_spellInfo)) return SPELL_FAILED_NOT_READY; @@ -5704,6 +5759,9 @@ SpellCastResult Spell::CheckCasterAuras() const bool Spell::CanAutoCast(Unit* target) { + if (!target) + return (CheckPetCast(target) == SPELL_CAST_OK); + ObjectGuid targetguid = target->GetGUID(); // check if target already has the same or a more powerful aura @@ -5740,16 +5798,19 @@ bool Spell::CanAutoCast(Unit* target) } SpellCastResult result = CheckPetCast(target); - if (result == SPELL_CAST_OK || result == SPELL_FAILED_UNIT_NOT_INFRONT) { + // do not check targets for ground-targeted spells (we target them on top of the intended target anyway) + if (GetSpellInfo()->ExplicitTargetMask & TARGET_FLAG_DEST_LOCATION) + return true; SelectSpellTargets(); //check if among target units, our WANTED target is as well (->only self cast spells return false) - for (std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit) + for (std::list<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit) if (ihit->targetGUID == targetguid) return true; } - return false; //target invalid + // either the cast failed or the intended target wouldn't be hit + return false; } SpellCastResult Spell::CheckRange(bool strict) diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h index e634aa62a1c..b7134283ccb 100644 --- a/src/server/game/Spells/Spell.h +++ b/src/server/game/Spells/Spell.h @@ -694,14 +694,6 @@ class TC_GAME_API Spell ByteBuffer * m_effectExecuteData[MAX_SPELL_EFFECTS]; -#ifdef MAP_BASED_RAND_GEN - int32 irand(int32 min, int32 max) { return int32 (m_caster->GetMap()->mtRand.randInt(max - min)) + min; } - uint32 urand(uint32 min, uint32 max) { return m_caster->GetMap()->mtRand.randInt(max - min) + min; } - int32 rand32() { return m_caster->GetMap()->mtRand.randInt(); } - double rand_norm() { return m_caster->GetMap()->mtRand.randExc(); } - double rand_chance() { return m_caster->GetMap()->mtRand.randExc(100.0); } -#endif - Spell(Spell const& right) = delete; Spell& operator=(Spell const& right) = delete; }; diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index 5b1def554e7..8a16812034c 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -217,7 +217,7 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]= &Spell::EffectCreateItem2, //157 SPELL_EFFECT_CREATE_ITEM_2 create item or create item template and replace by some randon spell loot item &Spell::EffectMilling, //158 SPELL_EFFECT_MILLING milling &Spell::EffectRenamePet, //159 SPELL_EFFECT_ALLOW_RENAME_PET allow rename pet once again - &Spell::EffectNULL, //160 SPELL_EFFECT_160 1 spell - 45534 + &Spell::EffectForceCast, //160 SPELL_EFFECT_FORCE_CAST_2 &Spell::EffectSpecCount, //161 SPELL_EFFECT_TALENT_SPEC_COUNT second talent spec (learn/revert) &Spell::EffectActivateSpec, //162 SPELL_EFFECT_TALENT_SPEC_SELECT activate primary/secondary spec &Spell::EffectNULL, //163 unused @@ -3019,6 +3019,12 @@ void Spell::EffectSummonPet(SpellEffIndex effIndex) //OldSummon->Relocate(px, py, pz, OldSummon->GetOrientation()); //OldSummon->SetMap(owner->GetMap()); //owner->GetMap()->Add(OldSummon->ToCreature()); + if (OldSummon->getPetType() == SUMMON_PET) + { + OldSummon->SetHealth(OldSummon->GetMaxHealth()); + OldSummon->SetPower(OldSummon->getPowerType(), + OldSummon->GetMaxPower(OldSummon->getPowerType())); + } if (owner->GetTypeId() == TYPEID_PLAYER && OldSummon->isControlled()) owner->ToPlayer()->PetSpellInitialize(); @@ -3771,28 +3777,6 @@ void Spell::EffectScriptEffect(SpellEffIndex effIndex) break; } - // Roll Dice - Decahedral Dwarven Dice - case 47770: - { - char buf[128]; - const char *gender = "his"; - if (m_caster->getGender() > 0) - gender = "her"; - sprintf(buf, "%s rubs %s [Decahedral Dwarven Dice] between %s hands and rolls. One %u and one %u.", m_caster->GetName().c_str(), gender, gender, urand(1, 10), urand(1, 10)); - m_caster->TextEmote(buf); - break; - } - // Roll 'dem Bones - Worn Troll Dice - case 47776: - { - char buf[128]; - const char *gender = "his"; - if (m_caster->getGender() > 0) - gender = "her"; - sprintf(buf, "%s causually tosses %s [Worn Troll Dice]. One %u and one %u.", m_caster->GetName().c_str(), gender, urand(1, 6), urand(1, 6)); - m_caster->TextEmote(buf); - break; - } // Death Knight Initiate Visual case 51519: { @@ -4234,20 +4218,7 @@ void Spell::EffectSummonPlayer(SpellEffIndex /*effIndex*/) if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) return; - // Evil Twin (ignore player summon, but hide this for summoner) - if (unitTarget->HasAura(23445)) - return; - - float x, y, z; - m_caster->GetPosition(x, y, z); - - unitTarget->ToPlayer()->SetSummonPoint(m_caster->GetMapId(), x, y, z); - - WorldPacket data(SMSG_SUMMON_REQUEST, 8+4+4); - data << uint64(m_caster->GetGUID()); // summoner guid - data << uint32(m_caster->GetZoneId()); // summoner zone - data << uint32(MAX_PLAYER_SUMMON_DELAY*IN_MILLISECONDS); // auto decline after msecs - unitTarget->ToPlayer()->GetSession()->SendPacket(&data); + unitTarget->ToPlayer()->SendSummonRequestFrom(m_caster); } void Spell::EffectActivateObject(SpellEffIndex /*effIndex*/) @@ -5510,7 +5481,7 @@ void Spell::EffectActivateRune(SpellEffIndex effIndex) for (uint32 l = 0; l + 1 < MAX_RUNES && count > 0; ++l) { // Check if both runes are on cd as that is the only time when this needs to come into effect - if ((player->GetRuneCooldown(l) && player->GetCurrentRune(l) == RuneType(m_spellInfo->Effects[effIndex].MiscValueB)) && (player->GetRuneCooldown(l+1) && player->GetCurrentRune(l+1) == RuneType(m_spellInfo->Effects[effIndex].MiscValueB))) + if ((player->GetRuneCooldown(l) && player->GetBaseRune(l) == RuneType(m_spellInfo->Effects[effIndex].MiscValueB)) && (player->GetRuneCooldown(l+1) && player->GetBaseRune(l+1) == RuneType(m_spellInfo->Effects[effIndex].MiscValueB))) { // Should always update the rune with the lowest cd if (l + 1 < MAX_RUNES && player->GetRuneCooldown(l) >= player->GetRuneCooldown(l+1)) diff --git a/src/server/game/Spells/SpellHistory.cpp b/src/server/game/Spells/SpellHistory.cpp index 4f74197fed2..31490bea29b 100644 --- a/src/server/game/Spells/SpellHistory.cpp +++ b/src/server/game/Spells/SpellHistory.cpp @@ -533,7 +533,7 @@ void SpellHistory::LockSpellSchool(SpellSchoolMask schoolMask, uint32 lockoutTim else { Creature* creatureOwner = _owner->ToCreature(); - for (uint8 i = 0; i < CREATURE_MAX_SPELLS; ++i) + for (uint8 i = 0; i < MAX_CREATURE_SPELLS; ++i) if (creatureOwner->m_spells[i]) knownSpells.insert(creatureOwner->m_spells[i]); } diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp index 069c794ca8b..ac157b48783 100644 --- a/src/server/game/Spells/SpellInfo.cpp +++ b/src/server/game/Spells/SpellInfo.cpp @@ -418,7 +418,8 @@ int32 SpellEffectInfo::CalcValue(Unit const* caster, int32 const* bp, Unit const level = int32(_spellInfo->MaxLevel); else if (level < int32(_spellInfo->BaseLevel)) level = int32(_spellInfo->BaseLevel); - level -= int32(_spellInfo->SpellLevel); + if (!_spellInfo->IsPassive()) + level -= int32(_spellInfo->SpellLevel); basePoints += int32(level * basePointsPerLevel); } @@ -524,10 +525,10 @@ float SpellEffectInfo::CalcValueMultiplier(Unit* caster, Spell* spell) const float SpellEffectInfo::CalcDamageMultiplier(Unit* caster, Spell* spell) const { - float multiplier = DamageMultiplier; + float multiplierPercent = DamageMultiplier * 100.0f; if (Player* modOwner = (caster ? caster->GetSpellModOwner() : NULL)) - modOwner->ApplySpellMod(_spellInfo->Id, SPELLMOD_DAMAGE_MULTIPLIER, multiplier, spell); - return multiplier; + modOwner->ApplySpellMod(_spellInfo->Id, SPELLMOD_DAMAGE_MULTIPLIER, multiplierPercent, spell); + return multiplierPercent / 100.0f; } bool SpellEffectInfo::HasRadius() const @@ -754,7 +755,7 @@ SpellEffectInfo::StaticData SpellEffectInfo::_data[TOTAL_SPELL_EFFECTS] = {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 157 SPELL_EFFECT_CREATE_ITEM_2 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_ITEM}, // 158 SPELL_EFFECT_MILLING {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 159 SPELL_EFFECT_ALLOW_RENAME_PET - {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 160 SPELL_EFFECT_160 + {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 160 SPELL_EFFECT_FORCE_CAST_2 {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 161 SPELL_EFFECT_TALENT_SPEC_COUNT {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 162 SPELL_EFFECT_TALENT_SPEC_SELECT {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 163 SPELL_EFFECT_163 diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index 50f750f2ca5..70eb7ad76bf 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -955,11 +955,11 @@ SpellProcEntry const* SpellMgr::GetSpellProcEntry(uint32 spellId) const bool SpellMgr::CanSpellTriggerProcOnEvent(SpellProcEntry const& procEntry, ProcEventInfo& eventInfo) const { // proc type doesn't match - if (!(eventInfo.GetTypeMask() & procEntry.typeMask)) + if (!(eventInfo.GetTypeMask() & procEntry.ProcFlags)) return false; // check XP or honor target requirement - if (procEntry.attributesMask & PROC_ATTR_REQ_EXP_OR_HONOR) + if (procEntry.AttributesMask & PROC_ATTR_REQ_EXP_OR_HONOR) if (Player* actor = eventInfo.GetActor()->ToPlayer()) if (eventInfo.GetActionTarget() && !actor->isHonorOrXPTarget(eventInfo.GetActionTarget())) return false; @@ -969,7 +969,7 @@ bool SpellMgr::CanSpellTriggerProcOnEvent(SpellProcEntry const& procEntry, ProcE return true; // check school mask (if set) for other trigger types - if (procEntry.schoolMask && !(eventInfo.GetSchoolMask() & procEntry.schoolMask)) + if (procEntry.SchoolMask && !(eventInfo.GetSchoolMask() & procEntry.SchoolMask)) return false; // check spell family name/flags (if set) for spells @@ -977,31 +977,31 @@ bool SpellMgr::CanSpellTriggerProcOnEvent(SpellProcEntry const& procEntry, ProcE { SpellInfo const* eventSpellInfo = eventInfo.GetSpellInfo(); - if (procEntry.spellFamilyName && eventSpellInfo && (procEntry.spellFamilyName != eventSpellInfo->SpellFamilyName)) + if (procEntry.SpellFamilyName && eventSpellInfo && (procEntry.SpellFamilyName != eventSpellInfo->SpellFamilyName)) return false; - if (procEntry.spellFamilyMask && eventSpellInfo && !(procEntry.spellFamilyMask & eventSpellInfo->SpellFamilyFlags)) + if (procEntry.SpellFamilyMask && eventSpellInfo && !(procEntry.SpellFamilyMask & eventSpellInfo->SpellFamilyFlags)) return false; } // check spell type mask (if set) if (eventInfo.GetTypeMask() & (SPELL_PROC_FLAG_MASK | PERIODIC_PROC_FLAG_MASK)) { - if (procEntry.spellTypeMask && !(eventInfo.GetSpellTypeMask() & procEntry.spellTypeMask)) + if (procEntry.SpellTypeMask && !(eventInfo.GetSpellTypeMask() & procEntry.SpellTypeMask)) return false; } // check spell phase mask if (eventInfo.GetTypeMask() & REQ_SPELL_PHASE_PROC_FLAG_MASK) { - if (!(eventInfo.GetSpellPhaseMask() & procEntry.spellPhaseMask)) + if (!(eventInfo.GetSpellPhaseMask() & procEntry.SpellPhaseMask)) return false; } // check hit mask (on taken hit or on done hit, but not on spell cast phase) if ((eventInfo.GetTypeMask() & TAKEN_HIT_PROC_FLAG_MASK) || ((eventInfo.GetTypeMask() & DONE_HIT_PROC_FLAG_MASK) && !(eventInfo.GetSpellPhaseMask() & PROC_SPELL_PHASE_CAST))) { - uint32 hitMask = procEntry.hitMask; + uint32 hitMask = procEntry.HitMask; // get default values if hit mask not set if (!hitMask) { @@ -1929,8 +1929,11 @@ void SpellMgr::LoadSpellProcs() mSpellProcMap.clear(); // need for reload case - // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 - QueryResult result = WorldDatabase.Query("SELECT spellId, schoolMask, spellFamilyName, spellFamilyMask0, spellFamilyMask1, spellFamilyMask2, typeMask, spellTypeMask, spellPhaseMask, hitMask, attributesMask, ratePerMinute, chance, cooldown, charges FROM spell_proc"); + // 0 1 2 3 4 5 + QueryResult result = WorldDatabase.Query("SELECT SpellId, SchoolMask, SpellFamilyName, SpellFamilyMask0, SpellFamilyMask1, SpellFamilyMask2, " + // 6 7 8 9 10 11 12 13 14 + "ProcFlags, SpellTypeMask, SpellPhaseMask, HitMask, AttributesMask, ProcsPerMinute, Chance, Cooldown, Charges FROM spell_proc"); + if (!result) { TC_LOG_INFO("server.loading", ">> Loaded 0 spell proc conditions and data. DB table `spell_proc` is empty."); @@ -1972,21 +1975,20 @@ void SpellMgr::LoadSpellProcs() SpellProcEntry baseProcEntry; - baseProcEntry.schoolMask = fields[1].GetInt8(); - baseProcEntry.spellFamilyName = fields[2].GetUInt16(); - baseProcEntry.spellFamilyMask[0] = fields[3].GetUInt32(); - baseProcEntry.spellFamilyMask[1] = fields[4].GetUInt32(); - baseProcEntry.spellFamilyMask[2] = fields[5].GetUInt32(); - baseProcEntry.typeMask = fields[6].GetUInt32(); - baseProcEntry.spellTypeMask = fields[7].GetUInt32(); - baseProcEntry.spellPhaseMask = fields[8].GetUInt32(); - baseProcEntry.hitMask = fields[9].GetUInt32(); - baseProcEntry.attributesMask = fields[10].GetUInt32(); - baseProcEntry.ratePerMinute = fields[11].GetFloat(); - baseProcEntry.chance = fields[12].GetFloat(); - float cooldown = fields[13].GetFloat(); - baseProcEntry.cooldown = uint32(cooldown); - baseProcEntry.charges = fields[14].GetUInt32(); + baseProcEntry.SchoolMask = fields[1].GetInt8(); + baseProcEntry.SpellFamilyName = fields[2].GetUInt16(); + baseProcEntry.SpellFamilyMask[0] = fields[3].GetUInt32(); + baseProcEntry.SpellFamilyMask[1] = fields[4].GetUInt32(); + baseProcEntry.SpellFamilyMask[2] = fields[5].GetUInt32(); + baseProcEntry.ProcFlags = fields[6].GetUInt32(); + baseProcEntry.SpellTypeMask = fields[7].GetUInt32(); + baseProcEntry.SpellPhaseMask = fields[8].GetUInt32(); + baseProcEntry.HitMask = fields[9].GetUInt32(); + baseProcEntry.AttributesMask = fields[10].GetUInt32(); + baseProcEntry.ProcsPerMinute = fields[11].GetFloat(); + baseProcEntry.Chance = fields[12].GetFloat(); + baseProcEntry.Cooldown = Milliseconds(fields[13].GetUInt32()); + baseProcEntry.Charges = fields[14].GetUInt8(); while (spellInfo) { @@ -1999,56 +2001,46 @@ void SpellMgr::LoadSpellProcs() SpellProcEntry procEntry = SpellProcEntry(baseProcEntry); // take defaults from dbcs - if (!procEntry.typeMask) - procEntry.typeMask = spellInfo->ProcFlags; - if (!procEntry.charges) - procEntry.charges = spellInfo->ProcCharges; - if (!procEntry.chance && !procEntry.ratePerMinute) - procEntry.chance = float(spellInfo->ProcChance); + if (!procEntry.ProcFlags) + procEntry.ProcFlags = spellInfo->ProcFlags; + if (!procEntry.Charges) + procEntry.Charges = spellInfo->ProcCharges; + if (!procEntry.Chance && !procEntry.ProcsPerMinute) + procEntry.Chance = float(spellInfo->ProcChance); // validate data - if (procEntry.schoolMask & ~SPELL_SCHOOL_MASK_ALL) - TC_LOG_ERROR("sql.sql", "`spell_proc` table entry for spellId %u has wrong `schoolMask` set: %u", spellInfo->Id, procEntry.schoolMask); - if (procEntry.spellFamilyName && (procEntry.spellFamilyName < 3 || procEntry.spellFamilyName > 17 || procEntry.spellFamilyName == 14 || procEntry.spellFamilyName == 16)) - TC_LOG_ERROR("sql.sql", "`spell_proc` table entry for spellId %u has wrong `spellFamilyName` set: %u", spellInfo->Id, procEntry.spellFamilyName); - if (procEntry.chance < 0) - { - TC_LOG_ERROR("sql.sql", "`spell_proc` table entry for spellId %u has negative value in the `chance` field", spellInfo->Id); - procEntry.chance = 0; - } - if (procEntry.ratePerMinute < 0) - { - TC_LOG_ERROR("sql.sql", "`spell_proc` table entry for spellId %u has negative value in the `ratePerMinute` field", spellInfo->Id); - procEntry.ratePerMinute = 0; - } - if (cooldown < 0) + if (procEntry.SchoolMask & ~SPELL_SCHOOL_MASK_ALL) + TC_LOG_ERROR("sql.sql", "`spell_proc` table entry for spellId %u has wrong `SchoolMask` set: %u", spellInfo->Id, procEntry.SchoolMask); + if (procEntry.SpellFamilyName && (procEntry.SpellFamilyName < 3 || procEntry.SpellFamilyName > 17 || procEntry.SpellFamilyName == 14 || procEntry.SpellFamilyName == 16)) + TC_LOG_ERROR("sql.sql", "`spell_proc` table entry for spellId %u has wrong `SpellFamilyName` set: %u", spellInfo->Id, procEntry.SpellFamilyName); + if (procEntry.Chance < 0) { - TC_LOG_ERROR("sql.sql", "`spell_proc` table entry for spellId %u has negative value in the `cooldown` field", spellInfo->Id); - procEntry.cooldown = 0; + TC_LOG_ERROR("sql.sql", "`spell_proc` table entry for spellId %u has negative value in the `Chance` field", spellInfo->Id); + procEntry.Chance = 0; } - if (procEntry.chance == 0 && procEntry.ratePerMinute == 0) - TC_LOG_ERROR("sql.sql", "`spell_proc` table entry for spellId %u doesn't have any `chance` and `ratePerMinute` values defined, proc will not be triggered", spellInfo->Id); - if (procEntry.charges > 99) + if (procEntry.ProcsPerMinute < 0) { - TC_LOG_ERROR("sql.sql", "The `spell_proc` table entry for spellId %u has a too big `charges` field value.", spellInfo->Id); - procEntry.charges = 99; + TC_LOG_ERROR("sql.sql", "`spell_proc` table entry for spellId %u has negative value in the `ProcsPerMinute` field", spellInfo->Id); + procEntry.ProcsPerMinute = 0; } - if (!procEntry.typeMask) - TC_LOG_ERROR("sql.sql", "The `spell_proc` table entry for spellId %u doesn't have any `typeMask` value defined, proc will not be triggered.", spellInfo->Id); - if (procEntry.spellTypeMask & ~PROC_SPELL_TYPE_MASK_ALL) - TC_LOG_ERROR("sql.sql", "`spell_proc` table entry for spellId %u has wrong `spellTypeMask` set: %u", spellInfo->Id, procEntry.spellTypeMask); - if (procEntry.spellTypeMask && !(procEntry.typeMask & (SPELL_PROC_FLAG_MASK | PERIODIC_PROC_FLAG_MASK))) - TC_LOG_ERROR("sql.sql", "The `spell_proc` table entry for spellId %u has `spellTypeMask` value defined, but it will not be used for the defined `typeMask` value.", spellInfo->Id); - if (!procEntry.spellPhaseMask && procEntry.typeMask & REQ_SPELL_PHASE_PROC_FLAG_MASK) - TC_LOG_ERROR("sql.sql", "The `spell_proc` table entry for spellId %u doesn't have any `spellPhaseMask` value defined, but it is required for the defined `typeMask` value. Proc will not be triggered.", spellInfo->Id); - if (procEntry.spellPhaseMask & ~PROC_SPELL_PHASE_MASK_ALL) - TC_LOG_ERROR("sql.sql", "The `spell_proc` table entry for spellId %u has wrong `spellPhaseMask` set: %u", spellInfo->Id, procEntry.spellPhaseMask); - if (procEntry.spellPhaseMask && !(procEntry.typeMask & REQ_SPELL_PHASE_PROC_FLAG_MASK)) - TC_LOG_ERROR("sql.sql", "The `spell_proc` table entry for spellId %u has a `spellPhaseMask` value defined, but it will not be used for the defined `typeMask` value.", spellInfo->Id); - if (procEntry.hitMask & ~PROC_HIT_MASK_ALL) - TC_LOG_ERROR("sql.sql", "The `spell_proc` table entry for spellId %u has wrong `hitMask` set: %u", spellInfo->Id, procEntry.hitMask); - if (procEntry.hitMask && !(procEntry.typeMask & TAKEN_HIT_PROC_FLAG_MASK || (procEntry.typeMask & DONE_HIT_PROC_FLAG_MASK && (!procEntry.spellPhaseMask || procEntry.spellPhaseMask & (PROC_SPELL_PHASE_HIT | PROC_SPELL_PHASE_FINISH))))) - TC_LOG_ERROR("sql.sql", "The `spell_proc` table entry for spellId %u has `hitMask` value defined, but it will not be used for defined `typeMask` and `spellPhaseMask` values.", spellInfo->Id); + if (procEntry.Chance == 0 && procEntry.ProcsPerMinute == 0) + TC_LOG_ERROR("sql.sql", "`spell_proc` table entry for spellId %u doesn't have any `Chance` and `ProcsPerMinute` values defined, proc will not be triggered", spellInfo->Id); + if (!procEntry.ProcFlags) + TC_LOG_ERROR("sql.sql", "The `spell_proc` table entry for spellId %u doesn't have any `ProcFlags` value defined, proc will not be triggered.", spellInfo->Id); + if (procEntry.SpellTypeMask & ~PROC_SPELL_TYPE_MASK_ALL) + TC_LOG_ERROR("sql.sql", "`spell_proc` table entry for spellId %u has wrong `SpellTypeMask` set: %u", spellInfo->Id, procEntry.SpellTypeMask); + if (procEntry.SpellTypeMask && !(procEntry.ProcFlags & (SPELL_PROC_FLAG_MASK | PERIODIC_PROC_FLAG_MASK))) + TC_LOG_ERROR("sql.sql", "The `spell_proc` table entry for spellId %u has `SpellTypeMask` value defined, but it will not be used for the defined `ProcFlags` value.", spellInfo->Id); + if (!procEntry.SpellPhaseMask && procEntry.ProcFlags & REQ_SPELL_PHASE_PROC_FLAG_MASK) + TC_LOG_ERROR("sql.sql", "The `spell_proc` table entry for spellId %u doesn't have any `SpellPhaseMask` value defined, but it is required for the defined `ProcFlags` value. Proc will not be triggered.", spellInfo->Id); + if (procEntry.SpellPhaseMask & ~PROC_SPELL_PHASE_MASK_ALL) + TC_LOG_ERROR("sql.sql", "The `spell_proc` table entry for spellId %u has wrong `SpellPhaseMask` set: %u", spellInfo->Id, procEntry.SpellPhaseMask); + if (procEntry.SpellPhaseMask && !(procEntry.ProcFlags & REQ_SPELL_PHASE_PROC_FLAG_MASK)) + TC_LOG_ERROR("sql.sql", "The `spell_proc` table entry for spellId %u has a `SpellPhaseMask` value defined, but it will not be used for the defined `ProcFlags` value.", spellInfo->Id); + if (procEntry.HitMask & ~PROC_HIT_MASK_ALL) + TC_LOG_ERROR("sql.sql", "The `spell_proc` table entry for spellId %u has wrong `HitMask` set: %u", spellInfo->Id, procEntry.HitMask); + if (procEntry.HitMask && !(procEntry.ProcFlags & TAKEN_HIT_PROC_FLAG_MASK || (procEntry.ProcFlags & DONE_HIT_PROC_FLAG_MASK && (!procEntry.SpellPhaseMask || procEntry.SpellPhaseMask & (PROC_SPELL_PHASE_HIT | PROC_SPELL_PHASE_FINISH))))) + TC_LOG_ERROR("sql.sql", "The `spell_proc` table entry for spellId %u has `HitMask` value defined, but it will not be used for defined `ProcFlags` and `SpellPhaseMask` values.", spellInfo->Id); mSpellProcMap[spellInfo->Id] = procEntry; @@ -3758,6 +3750,8 @@ void SpellMgr::LoadSpellInfoCorrections() case 45257: // Using Steam Tonk Controller case 45440: // Steam Tonk Controller case 60256: // Collect Sample + case 45634: // Neural Needle + case 54897: // Flaming Arrow // Crashes client on pressing ESC spellInfo->AttributesEx4 &= ~SPELL_ATTR4_CAN_CAST_WHILE_CASTING; break; diff --git a/src/server/game/Spells/SpellMgr.h b/src/server/game/Spells/SpellMgr.h index fea7513b092..75da933636c 100644 --- a/src/server/game/Spells/SpellMgr.h +++ b/src/server/game/Spells/SpellMgr.h @@ -266,7 +266,7 @@ enum ProcFlagsHit PROC_HIT_REFLECT = 0x0000800, PROC_HIT_INTERRUPT = 0x0001000, // (not used atm) PROC_HIT_FULL_BLOCK = 0x0002000, - PROC_HIT_MASK_ALL = 0x2FFF + PROC_HIT_MASK_ALL = 0x0002FFF }; enum ProcAttributes @@ -290,18 +290,18 @@ typedef std::unordered_map<uint32, SpellProcEventEntry> SpellProcEventMap; struct SpellProcEntry { - uint32 schoolMask; // if nonzero - bitmask for matching proc condition based on spell's school - uint32 spellFamilyName; // if nonzero - for matching proc condition based on candidate spell's SpellFamilyName - flag96 spellFamilyMask; // if nonzero - bitmask for matching proc condition based on candidate spell's SpellFamilyFlags - uint32 typeMask; // if nonzero - owerwrite procFlags field for given Spell.dbc entry, bitmask for matching proc condition, see enum ProcFlags - uint32 spellTypeMask; // if nonzero - bitmask for matching proc condition based on candidate spell's damage/heal effects, see enum ProcFlagsSpellType - uint32 spellPhaseMask; // if nonzero - bitmask for matching phase of a spellcast on which proc occurs, see enum ProcFlagsSpellPhase - uint32 hitMask; // if nonzero - bitmask for matching proc condition based on hit result, see enum ProcFlagsHit - uint32 attributesMask; // bitmask, see ProcAttributes - float ratePerMinute; // if nonzero - chance to proc is equal to value * aura caster's weapon speed / 60 - float chance; // if nonzero - owerwrite procChance field for given Spell.dbc entry, defines chance of proc to occur, not used if perMinuteRate set - uint32 cooldown; // if nonzero - cooldown in secs for aura proc, applied to aura - uint32 charges; // if nonzero - owerwrite procCharges field for given Spell.dbc entry, defines how many times proc can occur before aura remove, 0 - infinite + uint32 SchoolMask; // if nonzero - bitmask for matching proc condition based on spell's school + uint32 SpellFamilyName; // if nonzero - for matching proc condition based on candidate spell's SpellFamilyName + flag96 SpellFamilyMask; // if nonzero - bitmask for matching proc condition based on candidate spell's SpellFamilyFlags + uint32 ProcFlags; // if nonzero - owerwrite procFlags field for given Spell.dbc entry, bitmask for matching proc condition, see enum ProcFlags + uint32 SpellTypeMask; // if nonzero - bitmask for matching proc condition based on candidate spell's damage/heal effects, see enum ProcFlagsSpellType + uint32 SpellPhaseMask; // if nonzero - bitmask for matching phase of a spellcast on which proc occurs, see enum ProcFlagsSpellPhase + uint32 HitMask; // if nonzero - bitmask for matching proc condition based on hit result, see enum ProcFlagsHit + uint32 AttributesMask; // bitmask, see ProcAttributes + float ProcsPerMinute; // if nonzero - chance to proc is equal to value * aura caster's weapon speed / 60 + float Chance; // if nonzero - owerwrite procChance field for given Spell.dbc entry, defines chance of proc to occur, not used if ProcsPerMinute set + Milliseconds Cooldown; // if nonzero - cooldown in secs for aura proc, applied to aura + uint32 Charges; // if nonzero - owerwrite procCharges field for given Spell.dbc entry, defines how many times proc can occur before aura remove, 0 - infinite }; typedef std::unordered_map<uint32, SpellProcEntry> SpellProcMap; diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 4b64ef0bbd8..37457f36145 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -66,7 +66,7 @@ #include "WaypointMovementGenerator.h" #include "WeatherMgr.h" #include "WorldSession.h" - +#include "M2Stores.h" TC_GAME_API std::atomic<bool> World::m_stopEvent(false); TC_GAME_API uint8 World::m_ExitCode = SHUTDOWN_EXIT_CODE; @@ -659,9 +659,8 @@ void World::LoadConfigSettings(bool reload) m_float_configs[CONFIG_GROUP_XP_DISTANCE] = sConfigMgr->GetFloatDefault("MaxGroupXPDistance", 74.0f); m_float_configs[CONFIG_MAX_RECRUIT_A_FRIEND_DISTANCE] = sConfigMgr->GetFloatDefault("MaxRecruitAFriendBonusDistance", 100.0f); - /// @todo Add MonsterSight and GuarderSight (with meaning) in worldserver.conf or put them as define + /// @todo Add MonsterSight (with meaning) in worldserver.conf or put them as define m_float_configs[CONFIG_SIGHT_MONSTER] = sConfigMgr->GetFloatDefault("MonsterSight", 50.0f); - m_float_configs[CONFIG_SIGHT_GUARDER] = sConfigMgr->GetFloatDefault("GuarderSight", 50.0f); if (reload) { @@ -900,6 +899,7 @@ void World::LoadConfigSettings(bool reload) m_bool_configs[CONFIG_ALLOW_GM_GROUP] = sConfigMgr->GetBoolDefault("GM.AllowInvite", false); m_bool_configs[CONFIG_GM_LOWER_SECURITY] = sConfigMgr->GetBoolDefault("GM.LowerSecurity", false); m_float_configs[CONFIG_CHANCE_OF_GM_SURVEY] = sConfigMgr->GetFloatDefault("GM.TicketSystem.ChanceOfGMSurvey", 50.0f); + m_int_configs[CONFIG_FORCE_SHUTDOWN_THRESHOLD] = sConfigMgr->GetIntDefault("GM.ForceShutdownThreshold", 30); m_int_configs[CONFIG_GROUP_VISIBILITY] = sConfigMgr->GetIntDefault("Visibility.GroupMode", 1); @@ -1082,6 +1082,7 @@ void World::LoadConfigSettings(bool reload) m_bool_configs[CONFIG_OFFHAND_CHECK_AT_SPELL_UNLEARN] = sConfigMgr->GetBoolDefault("OffhandCheckAtSpellUnlearn", true); m_int_configs[CONFIG_CREATURE_PICKPOCKET_REFILL] = sConfigMgr->GetIntDefault("Creature.PickPocketRefillDelay", 10 * MINUTE); + m_int_configs[CONFIG_CREATURE_STOP_FOR_PLAYER] = sConfigMgr->GetIntDefault("Creature.MovingStopTimeForPlayer", 3 * MINUTE * IN_MILLISECONDS); if (int32 clientCacheId = sConfigMgr->GetIntDefault("ClientCacheVersion", 0)) { @@ -1402,6 +1403,9 @@ void World::SetInitialWorldSettings() LoadDBCStores(m_dataPath); DetectDBCLang(); + // Load cinematic cameras + LoadM2Cameras(m_dataPath); + std::vector<uint32> mapIds; for (uint32 mapId = 0; mapId < sMapStore.GetNumRows(); mapId++) if (sMapStore.LookupEntry(mapId)) diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h index abc0ea452ac..4456b7a553e 100644 --- a/src/server/game/World/World.h +++ b/src/server/game/World/World.h @@ -28,7 +28,7 @@ #include "Timer.h" #include "SharedDefines.h" #include "QueryResult.h" -#include "Callback.h" +#include "QueryCallback.h" #include "Realm/Realm.h" #include <atomic> @@ -56,7 +56,8 @@ enum ServerMessageType enum ShutdownMask { SHUTDOWN_MASK_RESTART = 1, - SHUTDOWN_MASK_IDLE = 2 + SHUTDOWN_MASK_IDLE = 2, + SHUTDOWN_MASK_FORCE = 4 }; enum ShutdownExitCode @@ -182,7 +183,6 @@ enum WorldFloatConfigs CONFIG_GROUP_XP_DISTANCE = 0, CONFIG_MAX_RECRUIT_A_FRIEND_DISTANCE, CONFIG_SIGHT_MONSTER, - CONFIG_SIGHT_GUARDER, CONFIG_LISTEN_RANGE_SAY, CONFIG_LISTEN_RANGE_TEXTEMOTE, CONFIG_LISTEN_RANGE_YELL, @@ -252,6 +252,7 @@ enum WorldIntConfigs CONFIG_GM_LEVEL_IN_GM_LIST, CONFIG_GM_LEVEL_IN_WHO_LIST, CONFIG_START_GM_LEVEL, + CONFIG_FORCE_SHUTDOWN_THRESHOLD, CONFIG_GROUP_VISIBILITY, CONFIG_MAIL_DELIVERY_DELAY, CONFIG_UPTIME_UPDATE, @@ -357,6 +358,7 @@ enum WorldIntConfigs CONFIG_BG_REWARD_LOSER_HONOR_LAST, CONFIG_BIRTHDAY_TIME, CONFIG_CREATURE_PICKPOCKET_REFILL, + CONFIG_CREATURE_STOP_FOR_PLAYER, CONFIG_AHBOT_UPDATE_INTERVAL, CONFIG_CHARTER_COST_GUILD, CONFIG_CHARTER_COST_ARENA_2v2, diff --git a/src/server/scripts/Commands/cs_character.cpp b/src/server/scripts/Commands/cs_character.cpp index 9557d182df1..01602e2f24c 100644 --- a/src/server/scripts/Commands/cs_character.cpp +++ b/src/server/scripts/Commands/cs_character.cpp @@ -436,7 +436,7 @@ public: if (isalpha(levelStr[0])) { nameStr = levelStr; - levelStr = NULL; // current level will used + levelStr = nullptr; // current level will used } Player* target; diff --git a/src/server/scripts/Commands/cs_debug.cpp b/src/server/scripts/Commands/cs_debug.cpp index 1d8094885d4..ca4dd814e01 100644 --- a/src/server/scripts/Commands/cs_debug.cpp +++ b/src/server/scripts/Commands/cs_debug.cpp @@ -34,6 +34,7 @@ EndScriptData */ #include "Transport.h" #include "Language.h" #include "MapManager.h" +#include "M2Stores.h" #include <fstream> @@ -847,7 +848,7 @@ public: if (Unit* unit = ref->GetSource()->GetOwner()) { ++count; - handler->PSendSysMessage(" %u. %s (guid %u) - threat %f", count, unit->GetName().c_str(), unit->GetGUID().GetCounter(), ref->getThreat()); + handler->PSendSysMessage(" %u. %s (current guid %u, DB guid %u) - threat %f", count, unit->GetName().c_str(), unit->GetGUID().GetCounter(), unit->GetTypeId() == TYPEID_UNIT ? unit->ToCreature()->GetSpawnId() : 0, ref->getThreat()); } ref = ref->next(); } diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp index 3e35a721162..a98f9f4bf9c 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -796,7 +796,7 @@ public: target->CleanupAfterTaxiFlight(); } - target->TeleportTo(target->m_recallMap, target->m_recallX, target->m_recallY, target->m_recallZ, target->m_recallO); + target->Recall(); return true; } diff --git a/src/server/scripts/Commands/cs_modify.cpp b/src/server/scripts/Commands/cs_modify.cpp index f1ddb448b35..e25018cf1bd 100644 --- a/src/server/scripts/Commands/cs_modify.cpp +++ b/src/server/scripts/Commands/cs_modify.cpp @@ -80,23 +80,32 @@ public: return commandTable; } - //Edit Player HP - static bool HandleModifyHPCommand(ChatHandler* handler, const char* args) + template<typename... Args> + static void NotifyModification(ChatHandler* handler, Unit* target, TrinityStrings resourceMessage, TrinityStrings resourceReportMessage, Args&&... args) + { + if (Player* player = target->ToPlayer()) + { + handler->PSendSysMessage(resourceMessage, handler->GetNameLink(player).c_str(), args...); + if (handler->needReportToTarget(player)) + ChatHandler(player->GetSession()).PSendSysMessage(resourceReportMessage, handler->GetNameLink().c_str(), std::forward<Args>(args)...); + } + } + + static bool CheckModifyResources(ChatHandler* handler, const char* args, Player* target, int32& res, int32& resmax, int8 const multiplier = 1) { if (!*args) return false; - int32 hp = atoi((char*)args); - int32 hpm = atoi((char*)args); + res = atoi((char*)args) * multiplier; + resmax = atoi((char*)args) * multiplier; - if (hp < 1 || hpm < 1 || hpm < hp) + if (res < 1 || resmax < 1 || resmax < res) { handler->SendSysMessage(LANG_BAD_VALUE); handler->SetSentErrorMessage(true); return false; } - Player* target = handler->getSelectedPlayerOrSelf(); if (!target) { handler->SendSysMessage(LANG_NO_CHAR_SELECTED); @@ -107,164 +116,87 @@ public: if (handler->HasLowerSecurity(target, ObjectGuid::Empty)) return false; - handler->PSendSysMessage(LANG_YOU_CHANGE_HP, handler->GetNameLink(target).c_str(), hp, hpm); - if (handler->needReportToTarget(target)) - ChatHandler(target->GetSession()).PSendSysMessage(LANG_YOURS_HP_CHANGED, handler->GetNameLink().c_str(), hp, hpm); - - target->SetMaxHealth(hpm); - target->SetHealth(hp); - return true; } - //Edit Player Mana - static bool HandleModifyManaCommand(ChatHandler* handler, const char* args) + //Edit Player HP + static bool HandleModifyHPCommand(ChatHandler* handler, const char* args) { - if (!*args) - return false; - - int32 mana = atoi((char*)args); - int32 manam = atoi((char*)args); - - if (mana <= 0 || manam <= 0 || manam < mana) + int32 hp, hpmax; + Player* target = handler->getSelectedPlayerOrSelf(); + if (CheckModifyResources(handler, args, target, hp, hpmax)) { - handler->SendSysMessage(LANG_BAD_VALUE); - handler->SetSentErrorMessage(true); - return false; + NotifyModification(handler, target, LANG_YOU_CHANGE_HP, LANG_YOURS_HP_CHANGED, hp, hpmax); + target->SetMaxHealth(hpmax); + target->SetHealth(hp); + return true; } + return false; + } + //Edit Player Mana + static bool HandleModifyManaCommand(ChatHandler* handler, const char* args) + { + int32 mana, manamax; Player* target = handler->getSelectedPlayerOrSelf(); - if (!target) + + if (CheckModifyResources(handler, args, target, mana, manamax)) { - handler->SendSysMessage(LANG_NO_CHAR_SELECTED); - handler->SetSentErrorMessage(true); - return false; + NotifyModification(handler, target, LANG_YOU_CHANGE_MANA, LANG_YOURS_MANA_CHANGED, mana, manamax); + target->SetMaxPower(POWER_MANA, manamax); + target->SetPower(POWER_MANA, mana); + return true; } - - // check online security - if (handler->HasLowerSecurity(target, ObjectGuid::Empty)) - return false; - - handler->PSendSysMessage(LANG_YOU_CHANGE_MANA, handler->GetNameLink(target).c_str(), mana, manam); - if (handler->needReportToTarget(target)) - ChatHandler(target->GetSession()).PSendSysMessage(LANG_YOURS_MANA_CHANGED, handler->GetNameLink().c_str(), mana, manam); - - target->SetMaxPower(POWER_MANA, manam); - target->SetPower(POWER_MANA, mana); - - return true; + return false; } //Edit Player Energy static bool HandleModifyEnergyCommand(ChatHandler* handler, const char* args) { - if (!*args) - return false; - - int32 energy = atoi((char*)args)*10; - int32 energym = atoi((char*)args)*10; - - if (energy <= 0 || energym <= 0 || energym < energy) - { - handler->SendSysMessage(LANG_BAD_VALUE); - handler->SetSentErrorMessage(true); - return false; - } - + int32 energy, energymax; Player* target = handler->getSelectedPlayerOrSelf(); - if (!target) + int8 const energyMultiplier = 10; + if (CheckModifyResources(handler, args, target, energy, energymax, energyMultiplier)) { - handler->SendSysMessage(LANG_NO_CHAR_SELECTED); - handler->SetSentErrorMessage(true); - return false; + NotifyModification(handler, target, LANG_YOU_CHANGE_ENERGY, LANG_YOURS_ENERGY_CHANGED, energy / energyMultiplier, energymax / energyMultiplier); + target->SetMaxPower(POWER_ENERGY, energymax); + target->SetPower(POWER_ENERGY, energy); + TC_LOG_DEBUG("misc", handler->GetTrinityString(LANG_CURRENT_ENERGY), target->GetMaxPower(POWER_ENERGY)); + return true; } - - // check online security - if (handler->HasLowerSecurity(target, ObjectGuid::Empty)) - return false; - - handler->PSendSysMessage(LANG_YOU_CHANGE_ENERGY, handler->GetNameLink(target).c_str(), energy/10, energym/10); - if (handler->needReportToTarget(target)) - ChatHandler(target->GetSession()).PSendSysMessage(LANG_YOURS_ENERGY_CHANGED, handler->GetNameLink().c_str(), energy/10, energym/10); - - target->SetMaxPower(POWER_ENERGY, energym); - target->SetPower(POWER_ENERGY, energy); - - TC_LOG_DEBUG("misc", handler->GetTrinityString(LANG_CURRENT_ENERGY), target->GetMaxPower(POWER_ENERGY)); - - return true; + return false; } //Edit Player Rage static bool HandleModifyRageCommand(ChatHandler* handler, const char* args) { - if (!*args) - return false; - - int32 rage = atoi((char*)args)*10; - int32 ragem = atoi((char*)args)*10; - - if (rage <= 0 || ragem <= 0 || ragem < rage) - { - handler->SendSysMessage(LANG_BAD_VALUE); - handler->SetSentErrorMessage(true); - return false; - } - + int32 rage, ragemax; Player* target = handler->getSelectedPlayerOrSelf(); - if (!target) + int8 const rageMultiplier = 10; + if (CheckModifyResources(handler, args, target, rage, ragemax, rageMultiplier)) { - handler->SendSysMessage(LANG_NO_CHAR_SELECTED); - handler->SetSentErrorMessage(true); - return false; + NotifyModification(handler, target, LANG_YOU_CHANGE_RAGE, LANG_YOURS_RAGE_CHANGED, rage / rageMultiplier, ragemax / rageMultiplier); + target->SetMaxPower(POWER_RAGE, ragemax); + target->SetPower(POWER_RAGE, rage); + return true; } - - // check online security - if (handler->HasLowerSecurity(target, ObjectGuid::Empty)) - return false; - - handler->PSendSysMessage(LANG_YOU_CHANGE_RAGE, handler->GetNameLink(target).c_str(), rage/10, ragem/10); - if (handler->needReportToTarget(target)) - ChatHandler(target->GetSession()).PSendSysMessage(LANG_YOURS_RAGE_CHANGED, handler->GetNameLink().c_str(), rage/10, ragem/10); - - target->SetMaxPower(POWER_RAGE, ragem); - target->SetPower(POWER_RAGE, rage); - - return true; + return false; } // Edit Player Runic Power static bool HandleModifyRunicPowerCommand(ChatHandler* handler, const char* args) { - if (!*args) - return false; - - int32 rune = atoi((char*)args)*10; - int32 runem = atoi((char*)args)*10; - - if (rune <= 0 || runem <= 0 || runem < rune) - { - handler->SendSysMessage(LANG_BAD_VALUE); - handler->SetSentErrorMessage(true); - return false; - } - + int32 rune, runemax; Player* target = handler->getSelectedPlayerOrSelf(); - if (!target) + int8 const runeMultiplier = 10; + if (CheckModifyResources(handler, args, target, rune, runemax, runeMultiplier)) { - handler->SendSysMessage(LANG_NO_CHAR_SELECTED); - handler->SetSentErrorMessage(true); - return false; + NotifyModification(handler, target, LANG_YOU_CHANGE_RUNIC_POWER, LANG_YOURS_RUNIC_POWER_CHANGED, rune / runeMultiplier, runemax / runeMultiplier); + target->SetMaxPower(POWER_RUNIC_POWER, runemax); + target->SetPower(POWER_RUNIC_POWER, rune); + return true; } - - handler->PSendSysMessage(LANG_YOU_CHANGE_RUNIC_POWER, handler->GetNameLink(target).c_str(), rune/10, runem/10); - if (handler->needReportToTarget(target)) - ChatHandler(target->GetSession()).PSendSysMessage(LANG_YOURS_RUNIC_POWER_CHANGED, handler->GetNameLink().c_str(), rune/10, runem/10); - - target->SetMaxPower(POWER_RUNIC_POWER, runem); - target->SetPower(POWER_RUNIC_POWER, rune); - - return true; + return false; } //Edit Player Faction @@ -437,22 +369,20 @@ public: return false; } - //Edit Player Aspeed - static bool HandleModifyASpeedCommand(ChatHandler* handler, const char* args) + static bool CheckModifySpeed(ChatHandler* handler, const char* args, Unit* target, float& speed, float minimumBound, float maximumBound, bool checkInFlight = true) { if (!*args) return false; - float ASpeed = (float)atof((char*)args); + speed = (float)atof((char*)args); - if (ASpeed > 50.0f || ASpeed < 0.1f) + if (speed > maximumBound || speed < minimumBound) { handler->SendSysMessage(LANG_BAD_VALUE); handler->SetSentErrorMessage(true); return false; } - Player* target = handler->getSelectedPlayerOrSelf(); if (!target) { handler->SendSysMessage(LANG_NO_CHAR_SELECTED); @@ -460,238 +390,107 @@ public: return false; } - // check online security - if (handler->HasLowerSecurity(target, ObjectGuid::Empty)) - return false; - - std::string targetNameLink = handler->GetNameLink(target); - - if (target->IsInFlight()) + if (Player* player = target->ToPlayer()) { - handler->PSendSysMessage(LANG_CHAR_IN_FLIGHT, targetNameLink.c_str()); - handler->SetSentErrorMessage(true); - return false; - } - - handler->PSendSysMessage(LANG_YOU_CHANGE_ASPEED, targetNameLink.c_str(), ASpeed); - if (handler->needReportToTarget(target)) - ChatHandler(target->GetSession()).PSendSysMessage(LANG_YOURS_ASPEED_CHANGED, handler->GetNameLink().c_str(), ASpeed); + // check online security + if (handler->HasLowerSecurity(player, ObjectGuid::Empty)) + return false; - target->SetSpeedRate(MOVE_WALK, ASpeed); - target->SetSpeedRate(MOVE_RUN, ASpeed); - target->SetSpeedRate(MOVE_SWIM, ASpeed); - //target->SetSpeedRate(MOVE_TURN, ASpeed); - target->SetSpeedRate(MOVE_FLIGHT, ASpeed); + if (player->IsInFlight() && checkInFlight) + { + handler->PSendSysMessage(LANG_CHAR_IN_FLIGHT, handler->GetNameLink(player).c_str()); + handler->SetSentErrorMessage(true); + return false; + } + } return true; } - //Edit Player Speed - static bool HandleModifySpeedCommand(ChatHandler* handler, const char* args) + //Edit Player Aspeed + static bool HandleModifyASpeedCommand(ChatHandler* handler, const char* args) { - if (!*args) - return false; - - float Speed = (float)atof((char*)args); - - if (Speed > 50.0f || Speed < 0.1f) - { - handler->SendSysMessage(LANG_BAD_VALUE); - handler->SetSentErrorMessage(true); - return false; - } - + float allSpeed; Player* target = handler->getSelectedPlayerOrSelf(); - if (!target) + if (CheckModifySpeed(handler, args, target, allSpeed, 0.1f, 50.0f)) { - handler->SendSysMessage(LANG_NO_CHAR_SELECTED); - handler->SetSentErrorMessage(true); - return false; + NotifyModification(handler, target, LANG_YOU_CHANGE_ASPEED, LANG_YOURS_ASPEED_CHANGED, allSpeed); + target->SetSpeedRate(MOVE_WALK, allSpeed); + target->SetSpeedRate(MOVE_RUN, allSpeed); + target->SetSpeedRate(MOVE_SWIM, allSpeed); + target->SetSpeedRate(MOVE_FLIGHT, allSpeed); + return true; } + return false; + } - // check online security - if (handler->HasLowerSecurity(target, ObjectGuid::Empty)) - return false; - - std::string targetNameLink = handler->GetNameLink(target); - - if (target->IsInFlight()) + //Edit Player Speed + static bool HandleModifySpeedCommand(ChatHandler* handler, const char* args) + { + float Speed; + Player* target = handler->getSelectedPlayerOrSelf(); + if (CheckModifySpeed(handler, args, target, Speed, 0.1f, 50.0f)) { - handler->PSendSysMessage(LANG_CHAR_IN_FLIGHT, targetNameLink.c_str()); - handler->SetSentErrorMessage(true); - return false; + NotifyModification(handler, target, LANG_YOU_CHANGE_SPEED, LANG_YOURS_SPEED_CHANGED, Speed); + target->SetSpeedRate(MOVE_RUN, Speed); + return true; } - - handler->PSendSysMessage(LANG_YOU_CHANGE_SPEED, targetNameLink.c_str(), Speed); - if (handler->needReportToTarget(target)) - ChatHandler(target->GetSession()).PSendSysMessage(LANG_YOURS_SPEED_CHANGED, handler->GetNameLink().c_str(), Speed); - - target->SetSpeedRate(MOVE_RUN, Speed); - - return true; + return false; } //Edit Player Swim Speed static bool HandleModifySwimCommand(ChatHandler* handler, const char* args) { - if (!*args) - return false; - - float Swim = (float)atof((char*)args); - - if (Swim > 50.0f || Swim < 0.1f) - { - handler->SendSysMessage(LANG_BAD_VALUE); - handler->SetSentErrorMessage(true); - return false; - } - + float swimSpeed; Player* target = handler->getSelectedPlayerOrSelf(); - if (!target) + if (CheckModifySpeed(handler, args, target, swimSpeed, 0.1f, 50.0f)) { - handler->SendSysMessage(LANG_NO_CHAR_SELECTED); - handler->SetSentErrorMessage(true); - return false; - } - - // check online security - if (handler->HasLowerSecurity(target, ObjectGuid::Empty)) - return false; - - std::string targetNameLink = handler->GetNameLink(target); - - if (target->IsInFlight()) - { - handler->PSendSysMessage(LANG_CHAR_IN_FLIGHT, targetNameLink.c_str()); - handler->SetSentErrorMessage(true); - return false; + NotifyModification(handler, target, LANG_YOU_CHANGE_SWIM_SPEED, LANG_YOURS_SWIM_SPEED_CHANGED, swimSpeed); + target->SetSpeedRate(MOVE_SWIM, swimSpeed); + return true; } - - handler->PSendSysMessage(LANG_YOU_CHANGE_SWIM_SPEED, targetNameLink.c_str(), Swim); - if (handler->needReportToTarget(target)) - ChatHandler(target->GetSession()).PSendSysMessage(LANG_YOURS_SWIM_SPEED_CHANGED, handler->GetNameLink().c_str(), Swim); - - target->SetSpeedRate(MOVE_SWIM, Swim); - - return true; + return false; } - //Edit Player Walk Speed + //Edit Player Backwards Walk Speed static bool HandleModifyBWalkCommand(ChatHandler* handler, const char* args) { - if (!*args) - return false; - - float BSpeed = (float)atof((char*)args); - - if (BSpeed > 50.0f || BSpeed < 0.1f) - { - handler->SendSysMessage(LANG_BAD_VALUE); - handler->SetSentErrorMessage(true); - return false; - } - + float backSpeed; Player* target = handler->getSelectedPlayerOrSelf(); - if (!target) + if (CheckModifySpeed(handler, args, target, backSpeed, 0.1f, 50.0f)) { - handler->SendSysMessage(LANG_NO_CHAR_SELECTED); - handler->SetSentErrorMessage(true); - return false; - } - - // check online security - if (handler->HasLowerSecurity(target, ObjectGuid::Empty)) - return false; - - std::string targetNameLink = handler->GetNameLink(target); - - if (target->IsInFlight()) - { - handler->PSendSysMessage(LANG_CHAR_IN_FLIGHT, targetNameLink.c_str()); - handler->SetSentErrorMessage(true); - return false; + NotifyModification(handler, target, LANG_YOU_CHANGE_BACK_SPEED, LANG_YOURS_BACK_SPEED_CHANGED, backSpeed); + target->SetSpeedRate(MOVE_RUN_BACK, backSpeed); + return true; } - - handler->PSendSysMessage(LANG_YOU_CHANGE_BACK_SPEED, targetNameLink.c_str(), BSpeed); - if (handler->needReportToTarget(target)) - ChatHandler(target->GetSession()).PSendSysMessage(LANG_YOURS_BACK_SPEED_CHANGED, handler->GetNameLink().c_str(), BSpeed); - - target->SetSpeedRate(MOVE_RUN_BACK, BSpeed); - - return true; + return false; } //Edit Player Fly static bool HandleModifyFlyCommand(ChatHandler* handler, const char* args) { - if (!*args) - return false; - - float FSpeed = (float)atof((char*)args); - - if (FSpeed > 50.0f || FSpeed < 0.1f) - { - handler->SendSysMessage(LANG_BAD_VALUE); - handler->SetSentErrorMessage(true); - return false; - } - + float flySpeed; Player* target = handler->getSelectedPlayerOrSelf(); - if (!target) + if (CheckModifySpeed(handler, args, target, flySpeed, 0.1f, 50.0f, false)) { - handler->SendSysMessage(LANG_NO_CHAR_SELECTED); - handler->SetSentErrorMessage(true); - return false; + NotifyModification(handler, target, LANG_YOU_CHANGE_FLY_SPEED, LANG_YOURS_FLY_SPEED_CHANGED, flySpeed); + target->SetSpeedRate(MOVE_FLIGHT, flySpeed); + return true; } - - // check online security - if (handler->HasLowerSecurity(target, ObjectGuid::Empty)) - return false; - - handler->PSendSysMessage(LANG_YOU_CHANGE_FLY_SPEED, handler->GetNameLink(target).c_str(), FSpeed); - if (handler->needReportToTarget(target)) - ChatHandler(target->GetSession()).PSendSysMessage(LANG_YOURS_FLY_SPEED_CHANGED, handler->GetNameLink().c_str(), FSpeed); - - target->SetSpeedRate(MOVE_FLIGHT, FSpeed); - - return true; + return false; } //Edit Player or Creature Scale static bool HandleModifyScaleCommand(ChatHandler* handler, const char* args) { - if (!*args) - return false; - - float Scale = (float)atof((char*)args); - if (Scale > 10.0f || Scale < 0.1f) - { - handler->SendSysMessage(LANG_BAD_VALUE); - handler->SetSentErrorMessage(true); - return false; - } - + float Scale; Unit* target = handler->getSelectedUnit(); - if (!target) + if (CheckModifySpeed(handler, args, target, Scale, 0.1f, 10.0f, false)) { - handler->SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE); - handler->SetSentErrorMessage(true); - return false; - } - - if (Player* player = target->ToPlayer()) - { - // check online security - if (handler->HasLowerSecurity(player, ObjectGuid::Empty)) - return false; - - handler->PSendSysMessage(LANG_YOU_CHANGE_SIZE, handler->GetNameLink(player).c_str(), Scale); - if (handler->needReportToTarget(player)) - ChatHandler(player->GetSession()).PSendSysMessage(LANG_YOURS_SIZE_CHANGED, handler->GetNameLink().c_str(), Scale); + NotifyModification(handler, target, LANG_YOU_CHANGE_SIZE, LANG_YOURS_SIZE_CHANGED, Scale); + target->SetObjectScale(Scale); + return true; } - - target->SetObjectScale(Scale); - - return true; + return false; } //Enable Player mount @@ -932,9 +731,7 @@ public: if (handler->HasLowerSecurity(target, ObjectGuid::Empty)) return false; - handler->PSendSysMessage(LANG_YOU_GIVE_MOUNT, handler->GetNameLink(target).c_str()); - if (handler->needReportToTarget(target)) - ChatHandler(target->GetSession()).PSendSysMessage(LANG_MOUNT_GIVED, handler->GetNameLink().c_str()); + NotifyModification(handler, target, LANG_YOU_GIVE_MOUNT, LANG_MOUNT_GIVED); target->SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP); target->Mount(mId); @@ -988,10 +785,7 @@ public: TC_LOG_DEBUG("misc", handler->GetTrinityString(LANG_CURRENT_MONEY), targetMoney, moneyToAdd, newmoney); if (newmoney <= 0) { - handler->PSendSysMessage(LANG_YOU_TAKE_ALL_MONEY, handler->GetNameLink(target).c_str()); - if (handler->needReportToTarget(target)) - ChatHandler(target->GetSession()).PSendSysMessage(LANG_YOURS_ALL_MONEY_GONE, handler->GetNameLink().c_str()); - + NotifyModification(handler, target, LANG_YOU_TAKE_ALL_MONEY, LANG_YOURS_ALL_MONEY_GONE); target->SetMoney(0); } else diff --git a/src/server/scripts/Commands/cs_npc.cpp b/src/server/scripts/Commands/cs_npc.cpp index fbd199b99db..38aa96a6a66 100644 --- a/src/server/scripts/Commands/cs_npc.cpp +++ b/src/server/scripts/Commands/cs_npc.cpp @@ -113,7 +113,7 @@ EnumName<UnitFlags> const unitFlags[MAX_UNIT_FLAGS] = { CREATE_NAMED_ENUM(UNIT_FLAG_SERVER_CONTROLLED), CREATE_NAMED_ENUM(UNIT_FLAG_NON_ATTACKABLE), - CREATE_NAMED_ENUM(UNIT_FLAG_DISABLE_MOVE), + CREATE_NAMED_ENUM(UNIT_FLAG_REMOVE_CLIENT_CONTROL), CREATE_NAMED_ENUM(UNIT_FLAG_PVP_ATTACKABLE), CREATE_NAMED_ENUM(UNIT_FLAG_RENAME), CREATE_NAMED_ENUM(UNIT_FLAG_PREPARATION), @@ -125,7 +125,7 @@ EnumName<UnitFlags> const unitFlags[MAX_UNIT_FLAGS] = CREATE_NAMED_ENUM(UNIT_FLAG_PET_IN_COMBAT), CREATE_NAMED_ENUM(UNIT_FLAG_PVP), CREATE_NAMED_ENUM(UNIT_FLAG_SILENCED), - CREATE_NAMED_ENUM(UNIT_FLAG_UNK_14), + CREATE_NAMED_ENUM(UNIT_FLAG_CANNOT_SWIM), CREATE_NAMED_ENUM(UNIT_FLAG_UNK_15), CREATE_NAMED_ENUM(UNIT_FLAG_UNK_16), CREATE_NAMED_ENUM(UNIT_FLAG_PACIFIED), @@ -220,14 +220,15 @@ public: { "whisper", rbac::RBAC_PERM_COMMAND_NPC_WHISPER, false, &HandleNpcWhisperCommand, "" }, { "yell", rbac::RBAC_PERM_COMMAND_NPC_YELL, false, &HandleNpcYellCommand, "" }, { "tame", rbac::RBAC_PERM_COMMAND_NPC_TAME, false, &HandleNpcTameCommand, "" }, - { "add", rbac::RBAC_PERM_COMMAND_NPC_ADD, false, NULL, "", npcAddCommandTable }, - { "delete", rbac::RBAC_PERM_COMMAND_NPC_DELETE, false, NULL, "", npcDeleteCommandTable }, - { "follow", rbac::RBAC_PERM_COMMAND_NPC_FOLLOW, false, NULL, "", npcFollowCommandTable }, - { "set", rbac::RBAC_PERM_COMMAND_NPC_SET, false, NULL, "", npcSetCommandTable }, + { "add", rbac::RBAC_PERM_COMMAND_NPC_ADD, false, nullptr, "", npcAddCommandTable }, + { "delete", rbac::RBAC_PERM_COMMAND_NPC_DELETE, false, nullptr, "", npcDeleteCommandTable }, + { "follow", rbac::RBAC_PERM_COMMAND_NPC_FOLLOW, false, nullptr, "", npcFollowCommandTable }, + { "set", rbac::RBAC_PERM_COMMAND_NPC_SET, false, nullptr, "", npcSetCommandTable }, + { "evade", rbac::RBAC_PERM_COMMAND_NPC_EVADE, false, &HandleNpcEvadeCommand, "" }, }; static std::vector<ChatCommand> commandTable = { - { "npc", rbac::RBAC_PERM_COMMAND_NPC, false, NULL, "", npcCommandTable }, + { "npc", rbac::RBAC_PERM_COMMAND_NPC, false, nullptr, "", npcCommandTable }, }; return commandTable; } @@ -318,17 +319,17 @@ public: uint32 itemId = item_int; - char* fmaxcount = strtok(NULL, " "); //add maxcount, default: 0 + char* fmaxcount = strtok(nullptr, " "); //add maxcount, default: 0 uint32 maxcount = 0; if (fmaxcount) maxcount = atoul(fmaxcount); - char* fincrtime = strtok(NULL, " "); //add incrtime, default: 0 + char* fincrtime = strtok(nullptr, " "); //add incrtime, default: 0 uint32 incrtime = 0; if (fincrtime) incrtime = atoul(fincrtime); - char* fextendedcost = strtok(NULL, " "); //add ExtendedCost, default: 0 + char* fextendedcost = strtok(nullptr, " "); //add ExtendedCost, default: 0 uint32 extendedcost = fextendedcost ? atoul(fextendedcost) : 0; Creature* vendor = handler->getSelectedCreature(); if (!vendor) @@ -361,7 +362,7 @@ public: return false; char* guidStr = strtok((char*)args, " "); - char* waitStr = strtok((char*)NULL, " "); + char* waitStr = strtok((char*)nullptr, " "); ObjectGuid::LowType lowGuid = atoi((char*)guidStr); @@ -446,36 +447,24 @@ public: } Creature* creature = handler->getSelectedCreature(); - if (!creature) + if (!creature || creature->IsPet()) { handler->SendSysMessage(LANG_SELECT_CREATURE); handler->SetSentErrorMessage(true); return false; } - if (creature->IsPet()) - { - if (((Pet*)creature)->getPetType() == HUNTER_PET) - { - creature->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, sObjectMgr->GetXPForLevel(lvl)/4); - creature->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0); - } - ((Pet*)creature)->GivePetLevel(lvl); - } - else - { - creature->SetMaxHealth(100 + 30*lvl); - creature->SetHealth(100 + 30*lvl); - creature->SetLevel(lvl); - creature->SaveToDB(); - } + creature->SetMaxHealth(100 + 30*lvl); + creature->SetHealth(100 + 30*lvl); + creature->SetLevel(lvl); + creature->SaveToDB(); return true; } static bool HandleNpcDeleteCommand(ChatHandler* handler, char const* args) { - Creature* unit = NULL; + Creature* unit = nullptr; if (*args) { @@ -628,7 +617,7 @@ public: return false; char* arg1 = strtok((char*)args, " "); - char* arg2 = strtok((char*)NULL, ""); + char* arg2 = strtok((char*)nullptr, ""); if (!arg1 || !arg2) return false; @@ -926,8 +915,8 @@ public: // later switched on/off according to special events (like escort // quests, etc) char* guid_str = strtok((char*)args, " "); - char* type_str = strtok((char*)NULL, " "); - char* dontdel_str = strtok((char*)NULL, " "); + char* type_str = strtok((char*)nullptr, " "); + char* dontdel_str = strtok((char*)nullptr, " "); bool doNotDelete = false; @@ -935,7 +924,7 @@ public: return false; ObjectGuid::LowType lowguid = 0; - Creature* creature = NULL; + Creature* creature = nullptr; if (dontdel_str) { @@ -961,7 +950,7 @@ public: { //TC_LOG_ERROR("misc", "DEBUG: type_str, NODEL "); doNotDelete = true; - type_str = NULL; + type_str = nullptr; } } } @@ -1001,7 +990,7 @@ public: } // now lowguid is low guid really existed creature - // and creature point (maybe) to this creature or NULL + // and creature point (maybe) to this creature or nullptr MovementGeneratorType move_type; @@ -1260,7 +1249,7 @@ public: } char* receiver_str = strtok((char*)args, " "); - char* text = strtok(NULL, ""); + char* text = strtok(nullptr, ""); if (!receiver_str || !text) { @@ -1319,7 +1308,16 @@ public: if (!*args) return false; - char* charID = handler->extractKeyFromLink((char*)args, "Hcreature_entry"); + bool loot = false; + char const* spawntype_str = strtok((char*)args, " "); + char const* entry_str = strtok(nullptr, ""); + if (stricmp(spawntype_str, "LOOT") == 0) + loot = true; + else if (stricmp(spawntype_str, "NOLOOT") == 0) + loot = false; + else + entry_str = args; + char* charID = handler->extractKeyFromLink((char*)entry_str, "Hcreature_entry"); if (!charID) return false; @@ -1332,7 +1330,7 @@ public: if (!sObjectMgr->GetCreatureTemplate(id)) return false; - chr->SummonCreature(id, *chr, TEMPSUMMON_CORPSE_DESPAWN, 120); + chr->SummonCreature(id, *chr, loot ? TEMPSUMMON_CORPSE_TIMED_DESPAWN : TEMPSUMMON_CORPSE_DESPAWN, 30 * IN_MILLISECONDS); return true; } @@ -1404,6 +1402,51 @@ public: return true; } + static bool HandleNpcEvadeCommand(ChatHandler* handler, char const* args) + { + Creature* creatureTarget = handler->getSelectedCreature(); + if (!creatureTarget || creatureTarget->IsPet()) + { + handler->PSendSysMessage(LANG_SELECT_CREATURE); + handler->SetSentErrorMessage(true); + return false; + } + + if (!creatureTarget->IsAIEnabled) + { + handler->PSendSysMessage(LANG_CREATURE_NOT_AI_ENABLED); + handler->SetSentErrorMessage(true); + return false; + } + + char* type_str = args ? strtok((char*)args, " ") : nullptr; + char* force_str = args ? strtok(nullptr, " ") : nullptr; + + CreatureAI::EvadeReason why = CreatureAI::EVADE_REASON_OTHER; + bool force = false; + if (type_str) + { + if (stricmp(type_str, "NO_HOSTILES") == 0 || stricmp(type_str, "EVADE_REASON_NO_HOSTILES") == 0) + why = CreatureAI::EVADE_REASON_NO_HOSTILES; + else if (stricmp(type_str, "BOUNDARY") == 0 || stricmp(type_str, "EVADE_REASON_BOUNDARY") == 0) + why = CreatureAI::EVADE_REASON_BOUNDARY; + else if (stricmp(type_str, "SEQUENCE_BREAK") == 0 || stricmp(type_str, "EVADE_REASON_SEQUENCE_BREAK") == 0) + why = CreatureAI::EVADE_REASON_SEQUENCE_BREAK; + else if (stricmp(type_str, "FORCE") == 0) + force = true; + + if (!force && force_str) + if (stricmp(force_str, "FORCE") == 0) + force = true; + } + + if (force) + creatureTarget->ClearUnitState(UNIT_STATE_EVADE); + creatureTarget->AI()->EnterEvadeMode(why); + + return true; + } + static bool HandleNpcAddFormationCommand(ChatHandler* handler, char const* args) { if (!*args) @@ -1515,7 +1558,7 @@ public: if (!pSlotID) return false; - char* pItemID = strtok(NULL, " "); + char* pItemID = strtok(nullptr, " "); if (!pItemID) return false; diff --git a/src/server/scripts/Commands/cs_pet.cpp b/src/server/scripts/Commands/cs_pet.cpp index 4f0a179142d..a86de766117 100644 --- a/src/server/scripts/Commands/cs_pet.cpp +++ b/src/server/scripts/Commands/cs_pet.cpp @@ -22,6 +22,19 @@ #include "ObjectMgr.h" #include "ScriptMgr.h" +static inline Pet* GetSelectedPlayerPetOrOwn(ChatHandler* handler) +{ + if (Unit* target = handler->getSelectedUnit()) + { + if (target->GetTypeId() == TYPEID_PLAYER) + return target->ToPlayer()->GetPet(); + if (target->IsPet()) + return target->ToPet(); + return nullptr; + } + Player* player = handler->GetSession()->GetPlayer(); + return player ? player->GetPet() : nullptr; +} class pet_commandscript : public CommandScript { public: @@ -34,6 +47,7 @@ public: { "create", rbac::RBAC_PERM_COMMAND_PET_CREATE, false, &HandlePetCreateCommand, "" }, { "learn", rbac::RBAC_PERM_COMMAND_PET_LEARN, false, &HandlePetLearnCommand, "" }, { "unlearn", rbac::RBAC_PERM_COMMAND_PET_UNLEARN, false, &HandlePetUnlearnCommand, "" }, + { "level", rbac::RBAC_PERM_COMMAND_PET_LEVEL, false, &HandlePetLevelCommand, "" }, }; static std::vector<ChatCommand> commandTable = @@ -54,11 +68,11 @@ public: return false; } - CreatureTemplate const* creatrueTemplate = creatureTarget->GetCreatureTemplate(); - // Creatures with family 0 crashes the server - if (!creatrueTemplate->family) + CreatureTemplate const* creatureTemplate = creatureTarget->GetCreatureTemplate(); + // Creatures with family CREATURE_FAMILY_NONE crashes the server + if (creatureTemplate->family == CREATURE_FAMILY_NONE) { - handler->PSendSysMessage("This creature cannot be tamed. (family id: 0)."); + handler->PSendSysMessage("This creature cannot be tamed. Family id: 0 (CREATURE_FAMILY_NONE)."); handler->SetSentErrorMessage(true); return false; } @@ -119,12 +133,11 @@ public: if (!*args) return false; - Player* player = handler->GetSession()->GetPlayer(); - Pet* pet = player->GetPet(); + Pet* pet = GetSelectedPlayerPetOrOwn(handler); if (!pet) { - handler->PSendSysMessage("You have no pet"); + handler->SendSysMessage(LANG_SELECT_PLAYER_OR_PET); handler->SetSentErrorMessage(true); return false; } @@ -162,11 +175,10 @@ public: if (!*args) return false; - Player* player = handler->GetSession()->GetPlayer(); - Pet* pet = player->GetPet(); + Pet* pet = GetSelectedPlayerPetOrOwn(handler); if (!pet) { - handler->PSendSysMessage("You have no pet"); + handler->SendSysMessage(LANG_SELECT_PLAYER_OR_PET); handler->SetSentErrorMessage(true); return false; } @@ -180,6 +192,37 @@ public: return true; } + + static bool HandlePetLevelCommand(ChatHandler* handler, char const* args) + { + Pet* pet = GetSelectedPlayerPetOrOwn(handler); + Player* owner = pet ? pet->GetOwner() : nullptr; + if (!pet || !owner) + { + handler->SendSysMessage(LANG_SELECT_PLAYER_OR_PET); + handler->SetSentErrorMessage(true); + return false; + } + + int32 level = args ? atoi(args) : 0; + if (level == 0) + level = owner->getLevel() - pet->getLevel(); + if (level == 0 || level < -STRONG_MAX_LEVEL || level > STRONG_MAX_LEVEL) + { + handler->SendSysMessage(LANG_BAD_VALUE); + handler->SetSentErrorMessage(true); + return false; + } + + int32 newLevel = pet->getLevel() + level; + if (newLevel < 1) + newLevel = 1; + else if (newLevel > owner->getLevel()) + newLevel = owner->getLevel(); + + pet->GivePetLevel(newLevel); + return true; + } }; void AddSC_pet_commandscript() diff --git a/src/server/scripts/Commands/cs_reload.cpp b/src/server/scripts/Commands/cs_reload.cpp index eb28a8adae4..4470fa7de42 100644 --- a/src/server/scripts/Commands/cs_reload.cpp +++ b/src/server/scripts/Commands/cs_reload.cpp @@ -91,7 +91,7 @@ public: { "disenchant_loot_template", rbac::RBAC_PERM_COMMAND_RELOAD_DISENCHANT_LOOT_TEMPLATE, true, &HandleReloadLootTemplatesDisenchantCommand, "" }, { "event_scripts", rbac::RBAC_PERM_COMMAND_RELOAD_EVENT_SCRIPTS, true, &HandleReloadEventScriptsCommand, "" }, { "fishing_loot_template", rbac::RBAC_PERM_COMMAND_RELOAD_FISHING_LOOT_TEMPLATE, true, &HandleReloadLootTemplatesFishingCommand, "" }, - { "game_graveyard_zone", rbac::RBAC_PERM_COMMAND_RELOAD_GAME_GRAVEYARD_ZONE, true, &HandleReloadGameGraveyardZoneCommand, "" }, + { "graveyard_zone", rbac::RBAC_PERM_COMMAND_RELOAD_GRAVEYARD_ZONE, true, &HandleReloadGameGraveyardZoneCommand, "" }, { "game_tele", rbac::RBAC_PERM_COMMAND_RELOAD_GAME_TELE, true, &HandleReloadGameTeleCommand, "" }, { "gameobject_questender", rbac::RBAC_PERM_COMMAND_RELOAD_GAMEOBJECT_QUESTENDER, true, &HandleReloadGOQuestEnderCommand, "" }, { "gameobject_loot_template", rbac::RBAC_PERM_COMMAND_RELOAD_GAMEOBJECT_QUEST_LOOT_TEMPLATE, true, &HandleReloadLootTemplatesGameobjectCommand, "" }, diff --git a/src/server/scripts/Commands/cs_server.cpp b/src/server/scripts/Commands/cs_server.cpp index 83bc2e47674..e0e52d4e1f5 100644 --- a/src/server/scripts/Commands/cs_server.cpp +++ b/src/server/scripts/Commands/cs_server.cpp @@ -29,6 +29,7 @@ EndScriptData */ #include "Player.h" #include "ScriptMgr.h" #include "GitRevision.h" +#include "Util.h" class server_commandscript : public CommandScript { @@ -52,12 +53,14 @@ public: static std::vector<ChatCommand> serverRestartCommandTable = { { "cancel", rbac::RBAC_PERM_COMMAND_SERVER_RESTART_CANCEL, true, &HandleServerShutDownCancelCommand, "" }, + { "force", rbac::RBAC_PERM_COMMAND_SERVER_RESTART_FORCE, true, &HandleServerForceRestartCommand, "" }, { "" , rbac::RBAC_PERM_COMMAND_SERVER_RESTART, true, &HandleServerRestartCommand, "" }, }; static std::vector<ChatCommand> serverShutdownCommandTable = { { "cancel", rbac::RBAC_PERM_COMMAND_SERVER_SHUTDOWN_CANCEL, true, &HandleServerShutDownCancelCommand, "" }, + { "force", rbac::RBAC_PERM_COMMAND_SERVER_SHUTDOWN_FORCE, true, &HandleServerForceShutDownCommand, "" }, { "" , rbac::RBAC_PERM_COMMAND_SERVER_SHUTDOWN, true, &HandleServerShutDownCommand, "" }, }; @@ -73,19 +76,19 @@ public: { { "corpses", rbac::RBAC_PERM_COMMAND_SERVER_CORPSES, true, &HandleServerCorpsesCommand, "" }, { "exit", rbac::RBAC_PERM_COMMAND_SERVER_EXIT, true, &HandleServerExitCommand, "" }, - { "idlerestart", rbac::RBAC_PERM_COMMAND_SERVER_IDLERESTART, true, NULL, "", serverIdleRestartCommandTable }, - { "idleshutdown", rbac::RBAC_PERM_COMMAND_SERVER_IDLESHUTDOWN, true, NULL, "", serverIdleShutdownCommandTable }, + { "idlerestart", rbac::RBAC_PERM_COMMAND_SERVER_IDLERESTART, true, nullptr, "", serverIdleRestartCommandTable }, + { "idleshutdown", rbac::RBAC_PERM_COMMAND_SERVER_IDLESHUTDOWN, true, nullptr, "", serverIdleShutdownCommandTable }, { "info", rbac::RBAC_PERM_COMMAND_SERVER_INFO, true, &HandleServerInfoCommand, "" }, { "motd", rbac::RBAC_PERM_COMMAND_SERVER_MOTD, true, &HandleServerMotdCommand, "" }, { "plimit", rbac::RBAC_PERM_COMMAND_SERVER_PLIMIT, true, &HandleServerPLimitCommand, "" }, - { "restart", rbac::RBAC_PERM_COMMAND_SERVER_RESTART, true, NULL, "", serverRestartCommandTable }, - { "shutdown", rbac::RBAC_PERM_COMMAND_SERVER_SHUTDOWN, true, NULL, "", serverShutdownCommandTable }, - { "set", rbac::RBAC_PERM_COMMAND_SERVER_SET, true, NULL, "", serverSetCommandTable }, + { "restart", rbac::RBAC_PERM_COMMAND_SERVER_RESTART, true, nullptr, "", serverRestartCommandTable }, + { "shutdown", rbac::RBAC_PERM_COMMAND_SERVER_SHUTDOWN, true, nullptr, "", serverShutdownCommandTable }, + { "set", rbac::RBAC_PERM_COMMAND_SERVER_SET, true, nullptr, "", serverSetCommandTable }, }; static std::vector<ChatCommand> commandTable = { - { "server", rbac::RBAC_PERM_COMMAND_SERVER, true, NULL, "", serverCommandTable }, + { "server", rbac::RBAC_PERM_COMMAND_SERVER, true, nullptr, "", serverCommandTable }, }; return commandTable; } @@ -192,19 +195,34 @@ public: return true; } - static bool HandleServerShutDownCommand(ChatHandler* /*handler*/, char const* args) + static inline bool IsOnlyUser(WorldSession* mySession) { - return ShutdownServer(args, 0, SHUTDOWN_EXIT_CODE); + // check if there is any session connected from a different address + std::string myAddr = mySession ? mySession->GetRemoteAddress() : ""; + SessionMap const& sessions = sWorld->GetAllSessions(); + for (SessionMap::value_type const& session : sessions) + if (session.second && myAddr != session.second->GetRemoteAddress()) + return false; + return true; + } + static bool HandleServerShutDownCommand(ChatHandler* handler, char const* args) + { + return ShutdownServer(args, IsOnlyUser(handler->GetSession()) ? SHUTDOWN_MASK_FORCE : 0, SHUTDOWN_EXIT_CODE); } - static bool HandleServerRestartCommand(ChatHandler* /*handler*/, char const* args) + static bool HandleServerRestartCommand(ChatHandler* handler, char const* args) { - return ShutdownServer(args, SHUTDOWN_MASK_RESTART, RESTART_EXIT_CODE); + return ShutdownServer(args, IsOnlyUser(handler->GetSession()) ? (SHUTDOWN_MASK_FORCE | SHUTDOWN_MASK_RESTART) : SHUTDOWN_MASK_RESTART, RESTART_EXIT_CODE); } - static bool HandleServerIdleRestartCommand(ChatHandler* /*handler*/, char const* args) + static bool HandleServerForceShutDownCommand(ChatHandler* /*handler*/, char const* args) { - return ShutdownServer(args, SHUTDOWN_MASK_RESTART | SHUTDOWN_MASK_IDLE, RESTART_EXIT_CODE); + return ShutdownServer(args, SHUTDOWN_MASK_FORCE, SHUTDOWN_EXIT_CODE); + } + + static bool HandleServerForceRestartCommand(ChatHandler* /*handler*/, char const* args) + { + return ShutdownServer(args, SHUTDOWN_MASK_FORCE | SHUTDOWN_MASK_RESTART, RESTART_EXIT_CODE); } static bool HandleServerIdleShutDownCommand(ChatHandler* /*handler*/, char const* args) @@ -212,6 +230,11 @@ public: return ShutdownServer(args, SHUTDOWN_MASK_IDLE, SHUTDOWN_EXIT_CODE); } + static bool HandleServerIdleRestartCommand(ChatHandler* /*handler*/, char const* args) + { + return ShutdownServer(args, SHUTDOWN_MASK_RESTART | SHUTDOWN_MASK_IDLE, RESTART_EXIT_CODE); + } + // Exit the realm static bool HandleServerExitCommand(ChatHandler* handler, char const* /*args*/) { @@ -256,8 +279,8 @@ public: return false; char* type = strtok((char*)args, " "); - char* name = strtok(NULL, " "); - char* level = strtok(NULL, " "); + char* name = strtok(nullptr, " "); + char* level = strtok(nullptr, " "); if (!type || !name || !level || *name == '\0' || *level == '\0' || (*type != 'a' && *type != 'l')) return false; @@ -313,10 +336,26 @@ private: return false; // #delay [#exit_code] [reason] + int32 delay = 0; char* delayStr = strtok((char*)args, " "); - if (!delayStr || !isNumeric(delayStr)) + if (!delayStr) return false; + if (isNumeric(delayStr)) + { + delay = atoi(delayStr); + // Prevent interpret wrong arg value as 0 secs shutdown time + if ((delay == 0 && (delayStr[0] != '0' || delayStr[1] != '\0')) || delay < 0) + return false; + } + else + { + delay = TimeStringToSecs(std::string(delayStr)); + + if (delay == 0) + return false; + } + char* exitCodeStr = nullptr; char reason[256] = { 0 }; @@ -337,17 +376,14 @@ private: } } - int32 delay = atoi(delayStr); - - // Prevent interpret wrong arg value as 0 secs shutdown time - if ((delay == 0 && (delayStr[0] != '0' || delayStr[1] != '\0')) || delay < 0) - return false; - int32 exitCode = defaultExitCode; if (exitCodeStr) if (!ParseExitCode(exitCodeStr, exitCode)) return false; + if (delay < (int32)sWorld->getIntConfig(CONFIG_FORCE_SHUTDOWN_THRESHOLD) && !(shutdownMask & SHUTDOWN_MASK_FORCE)) + return false; + sWorld->ShutdownServ(delay, shutdownMask, static_cast<uint8>(exitCode), std::string(reason)); return true; diff --git a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_headless_horseman.cpp b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_headless_horseman.cpp index f7a1c18c234..734b70933aa 100644 --- a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_headless_horseman.cpp +++ b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_headless_horseman.cpp @@ -894,12 +894,12 @@ public: if (instance->GetBossState(DATA_HORSEMAN_EVENT) == IN_PROGRESS) return false; - player->AreaExploredOrEventHappens(11405); - if (Creature* horseman = go->SummonCreature(HH_MOUNTED, FlightPoint[20].x, FlightPoint[20].y, FlightPoint[20].z, 0, TEMPSUMMON_MANUAL_DESPAWN, 0)) - { - ENSURE_AI(boss_headless_horseman::boss_headless_horsemanAI, horseman->AI())->PlayerGUID = player->GetGUID(); - ENSURE_AI(boss_headless_horseman::boss_headless_horsemanAI, horseman->AI())->FlyMode(); - } + player->AreaExploredOrEventHappens(11405); + if (Creature* horseman = go->SummonCreature(HH_MOUNTED, FlightPoint[20].x, FlightPoint[20].y, FlightPoint[20].z, 0, TEMPSUMMON_MANUAL_DESPAWN, 0)) + { + ENSURE_AI(boss_headless_horseman::boss_headless_horsemanAI, horseman->AI())->PlayerGUID = player->GetGUID(); + ENSURE_AI(boss_headless_horseman::boss_headless_horsemanAI, horseman->AI())->FlyMode(); + } return true; } }; diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kiljaeden.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kiljaeden.cpp index d86b3707606..7563a880f0a 100644 --- a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kiljaeden.cpp +++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kiljaeden.cpp @@ -143,11 +143,7 @@ enum Spells SPELL_RING_OF_BLUE_FLAMES = 45825 //Cast this spell when the go is activated }; -/*** Error messages ***/ -#define ERROR_KJ_NOT_SUMMONED "TSCR ERROR: Unable to summon Kil'Jaeden for some reason" - /*** Others ***/ -#define FLOOR_Z 28.050388f #define SHIELD_ORB_Z 45.000f enum Phase diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_muru.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_muru.cpp index 04d23cd7d4e..6c84677708e 100644 --- a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_muru.cpp +++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_muru.cpp @@ -15,88 +15,119 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -/* ScriptData -SDName: Boss_Muru -SD%Complete: 80 -SDComment: all sounds, black hole effect triggers to often (46228) -*/ - #include "ScriptMgr.h" #include "ScriptedCreature.h" #include "sunwell_plateau.h" -#include "Player.h" -#include "SpellInfo.h" +#include "SpellScript.h" +#include "SpellAuraEffects.h" -// Muru & Entropius's spells enum Spells { - SPELL_ENRAGE = 26662, - // Muru's spells - SPELL_NEGATIVE_ENERGY = 46009, //(this trigger 46008) - SPELL_DARKNESS = 45999, - SPELL_OPEN_ALL_PORTALS = 46177, - SPELL_OPEN_PORTAL = 45977, - SPELL_OPEN_PORTAL_2 = 45976, - SPELL_SUMMON_BERSERKER = 46037, - SPELL_SUMNON_FURY_MAGE = 46038, - SPELL_SUMMON_VOID_SENTINEL = 45988, - SPELL_SUMMON_ENTROPIUS = 46217, + SPELL_OPEN_PORTAL_PERIODIC = 45994, + SPELL_DARKNESS_PERIODIC = 45998, + SPELL_NEGATIVE_ENERGY_PERIODIC = 46009, + SPELL_SUMMON_VOID_SPAWN = 46071, + SPELL_SUMMON_BLOOD_ELVES_SCRIPT = 46050, + SPELL_SUMMON_BLOOD_ELVES_PERIODIC = 46041, + SPELL_OPEN_ALL_PORTALS = 46177, + SPELL_SUMMON_ENTROPIUS = 46217, + SPELL_ENRAGE = 26662, + SPELL_SUMMON_DARK_FIEND_0 = 46000, + SPELL_SUMMON_DARK_FIEND_1 = 46001, + SPELL_SUMMON_DARK_FIEND_2 = 46002, + SPELL_SUMMON_DARK_FIEND_3 = 46003, + SPELL_SUMMON_DARK_FIEND_4 = 46004, + SPELL_SUMMON_DARK_FIEND_5 = 46005, + SPELL_SUMMON_DARK_FIEND_6 = 46006, + SPELL_SUMMON_DARK_FIEND_7 = 46007, + SPELL_SUMMON_BERSERKER = 46037, + SPELL_SUMMON_BERSERKER_2 = 46040, + SPELL_SUMMON_FURY_MAGE = 46038, + SPELL_SUMMON_FURY_MAGE_2 = 46039, // Entropius's spells - SPELL_DARKNESS_E = 46269, - SPELL_BLACKHOLE = 46282, - SPELL_NEGATIVE_ENERGY_E = 46284, - SPELL_ENTROPIUS_SPAWN = 46223, - - // Shadowsword Berserker's spells - SPELL_FLURRY = 46160, - SPELL_DUAL_WIELD = 29651, + SPELL_ENTROPIUS_COSMETIC_SPAWN = 46223, + SPELL_DARKNESS_E = 46269, + SPELL_NEGATIVE_ENERGY_PERIODIC_E = 46284, + SPELL_BLACKHOLE = 46282, + SPELL_SUMMON_DARKFIEND_E = 46263, + + // Myruu's Portal Target + SPELL_SUMMON_VOID_SENTINEL_SUMMONER = 45978, + SPELL_SUMMON_VOID_SENTINEL_SUMMONER_VISUAL = 45989, + SPELL_SUMMON_VOID_SENTINEL = 45988, + SPELL_TRANSFORM_VISUAL_MISSILE = 46205, + TRANSFORM_VISUAL_MISSILE_1 = 46208, + TRANSFORM_VISUAL_MISSILE_2 = 46178, + SPELL_OPEN_PORTAL = 45977, + SPELL_OPEN_PORTAL_2 = 45976, - // Shadowsword Fury Mage's spells - SPELL_FEL_FIREBALL = 46101, - SPELL_SPELL_FURY = 46102, + //Dark Fiend Spells + SPELL_DARKFIEND_DAMAGE = 45944, + SPELL_DARKFIEND_VISUAL = 45936, + SPELL_DARKFIEND_SKIN = 45934, // Void Sentinel's spells - SPELL_SHADOW_PULSE = 46087, - SPELL_VOID_BLAST = 46161, + SPELL_SHADOW_PULSE_PERIODIC = 46086, + SPELL_VOID_BLAST = 46161, - // Void Spawn's spells - SPELL_SHADOW_BOLT_VOLLEY = 46082, + //Black Hole Spells + SPELL_BLACKHOLE_SUMMON_VISUAL = 46242, + SPELL_BLACKHOLE_SUMMON_VISUAL_2 = 46247, + SPELL_BLACKHOLE_PASSIVE = 46228, + SPELL_BLACK_HOLE_VISUAL_2 = 46235 +}; - //Dark Fiend Spells - SPELL_DARKFIEND_AOE = 45944, - SPELL_DARKFIEND_VISUAL = 45936, - SPELL_DARKFIEND_SKIN = 45934, +enum Phases +{ + PHASE_ONE = 1, + PHASE_TWO = 2 +}; - //Black Hole Spells - SPELL_BLACKHOLE_SPAWN = 46242, - SPELL_BLACKHOLE_GROW = 46228 +enum Misc +{ + MAX_VOID_SPAWNS = 6, + MAX_SUMMON_BLOOD_ELVES = 4, + MAX_SUMMON_DARK_FIEND = 8 }; -enum Events +uint32 const SummonDarkFiendSpells[MAX_SUMMON_DARK_FIEND] = { - // M'uru - EVENT_DARKNESS = 1, - EVENT_SUMMON_HUMANOIDS, - EVENT_SUMMON_SENTINEL, - EVENT_PHASE_TRANSITION, // Delayed phase transition. - EVENT_ENRAGE, - - // Entropius - EVENT_SUMMON_BLACK_HOLE + SPELL_SUMMON_DARK_FIEND_0, + SPELL_SUMMON_DARK_FIEND_1, + SPELL_SUMMON_DARK_FIEND_2, + SPELL_SUMMON_DARK_FIEND_3, + SPELL_SUMMON_DARK_FIEND_4, + SPELL_SUMMON_DARK_FIEND_5, + SPELL_SUMMON_DARK_FIEND_6, + SPELL_SUMMON_DARK_FIEND_7 }; -enum Phases +uint32 const SummonBloodElvesSpells[MAX_SUMMON_BLOOD_ELVES] = { - PHASE_ONE = 1, - PHASE_TWO, + SPELL_SUMMON_BERSERKER, + SPELL_SUMMON_BERSERKER_2, + SPELL_SUMMON_FURY_MAGE, + SPELL_SUMMON_FURY_MAGE_2 }; -enum CreatureGroups +class VoidSpawnSummon : public BasicEvent { - CREATURE_GROUP_HUMANOIDS, - CREATURE_GROUP_DARKFIENDS + public: + explicit VoidSpawnSummon(Creature* owner) + : _owner(owner) + { + } + + bool Execute(uint64 /*time*/, uint32 /*diff*/) + { + _owner->CastSpell((Unit*)nullptr, SPELL_SUMMON_VOID_SENTINEL, true); + return true; + } + + private: + Creature* _owner; }; class boss_entropius : public CreatureScript @@ -110,53 +141,78 @@ public: void Reset() override { - DoCastAOE(SPELL_NEGATIVE_ENERGY_E); + _Reset(); + DoCast(me, SPELL_ENTROPIUS_COSMETIC_SPAWN, true); } - void EnterCombat(Unit* /*who*/) override + void ScheduleTasks() override { - _EnterCombat(); - DoCastAOE(SPELL_NEGATIVE_ENERGY_E, true); - DoCast(me, SPELL_ENTROPIUS_SPAWN); - events.ScheduleEvent(EVENT_SUMMON_BLACK_HOLE, 15000); + scheduler.Schedule(Milliseconds(2000), [this](TaskContext /*context*/) + { + DoResetPortals(); + DoCastAOE(SPELL_NEGATIVE_ENERGY_PERIODIC_E, true); + }); + + scheduler.Schedule(Seconds(15), [this](TaskContext context) + { + DoCastAOE(SPELL_DARKNESS_E, true); + DoCastAOE(SPELL_BLACKHOLE, true); + + context.Repeat(); + }); } - void JustSummoned(Creature* summoned) override + void JustSummoned(Creature* summon) override { - switch (summoned->GetEntry()) + switch (summon->GetEntry()) { case NPC_DARK_FIENDS: - summoned->CastSpell(summoned, SPELL_DARKFIEND_VISUAL); + summon->CastSpell(summon, SPELL_DARKFIEND_VISUAL); break; case NPC_DARKNESS: - summoned->AddUnitState(UNIT_STATE_STUNNED); - float x, y, z, o; - summoned->GetHomePosition(x, y, z, o); - me->SummonCreature(NPC_DARK_FIENDS, x, y, z, o, TEMPSUMMON_CORPSE_DESPAWN, 0); + summon->SetReactState(REACT_PASSIVE); + summon->CastSpell(summon, SPELL_BLACKHOLE); + summon->CastSpell(summon, SPELL_SUMMON_DARKFIEND_E, true); break; } - summoned->AI()->AttackStart(SelectTarget(SELECT_TARGET_RANDOM, 0, 50, true)); - summons.Summon(summoned); + summons.Summon(summon); } - void ExecuteEvent(uint32 eventId) override + void EnterEvadeMode(EvadeReason /*why*/) override { - if (eventId == EVENT_SUMMON_BLACK_HOLE) - { - if (Unit* random = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(random, SPELL_DARKNESS_E); - if (Unit* random = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - random->CastSpell(random, SPELL_BLACKHOLE); - events.ScheduleEvent(EVENT_SUMMON_BLACK_HOLE, 15000); - } + if (Creature* muru = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_MURU))) + muru->AI()->EnterEvadeMode(); + + DoResetPortals(); + summons.DespawnAll(); + me->DespawnOrUnsummon(); } - void EnterEvadeMode(EvadeReason /*why*/) override + void JustDied(Unit* /*killer*/) override { + _JustDied(); + if (Creature* muru = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_MURU))) - muru->AI()->Reset(); // Reset encounter. - me->DisappearAndDie(); - summons.DespawnAll(); + muru->DisappearAndDie(); + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + scheduler.Update(diff, [this] + { + DoMeleeAttackIfReady(); + }); + } + + void DoResetPortals() + { + std::list<Creature*> portals; + me->GetCreatureListWithEntryInGrid(portals, NPC_MURU_PORTAL_TARGET, 100.0f); + for (Creature* portal : portals) + portal->RemoveAllAuras(); } }; @@ -181,101 +237,96 @@ public: void Initialize() { - DarkFiend = false; - HasEnraged = false; - EntropiusGUID.Clear(); + _hasEnraged = false; + _phase = PHASE_ONE; + _entropiusGUID.Clear(); } void Reset() override { - Initialize(); _Reset(); + Initialize(); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); me->SetVisible(true); } + void EnterEvadeMode(EvadeReason /*why*/) override + { + BossAI::EnterEvadeMode(); + if (Creature* entropius = ObjectAccessor::GetCreature(*me, _entropiusGUID)) + entropius->AI()->EnterEvadeMode(); + } + + void ScheduleTasks() override + { + scheduler.Schedule(Minutes(10), [this](TaskContext /*context*/) + { + if (Creature* entropius = ObjectAccessor::GetCreature(*me, _entropiusGUID)) + entropius->CastSpell(entropius, SPELL_ENRAGE); + DoCast(me, SPELL_ENRAGE); + _hasEnraged = true; + }); + + scheduler.Schedule(Seconds(10), [this](TaskContext /*context*/) + { + DoCast(me, SPELL_SUMMON_BLOOD_ELVES_SCRIPT, true); + DoCast(me, SPELL_SUMMON_BLOOD_ELVES_PERIODIC, true); + }); + } + void EnterCombat(Unit* /*who*/) override { _EnterCombat(); - events.SetPhase(PHASE_ONE); - events.ScheduleEvent(EVENT_ENRAGE, 600000); - events.ScheduleEvent(EVENT_DARKNESS, 45000, 0, PHASE_ONE); - events.ScheduleEvent(EVENT_SUMMON_HUMANOIDS, 10000, 0, PHASE_ONE); - events.ScheduleEvent(EVENT_SUMMON_SENTINEL, 31500, 0, PHASE_ONE); - DoCastAOE(SPELL_NEGATIVE_ENERGY); + DoCast(me, SPELL_OPEN_PORTAL_PERIODIC, true); + DoCast(me, SPELL_DARKNESS_PERIODIC, true); + DoCast(me, SPELL_NEGATIVE_ENERGY_PERIODIC, true); } void DamageTaken(Unit* /*done_by*/, uint32 &damage) override { - if (damage >= me->GetHealth() && events.IsInPhase(PHASE_ONE)) + if (damage >= me->GetHealth()) { - damage = 0; + damage = me->GetHealth() - 1; + if (_phase != PHASE_ONE) + return; + + _phase = PHASE_TWO; me->RemoveAllAuras(); - DoCast(me, SPELL_OPEN_ALL_PORTALS); + DoCast(me, SPELL_OPEN_ALL_PORTALS, true); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - events.SetPhase(PHASE_TWO); - events.ScheduleEvent(EVENT_PHASE_TRANSITION, 2000); + + scheduler.Schedule(Seconds(6), [this](TaskContext /*context*/) + { + DoCast(me, SPELL_SUMMON_ENTROPIUS, true); + }); } } - void JustSummoned(Creature* summoned) override + void JustSummoned(Creature* summon) override { - switch (summoned->GetEntry()) + if (summon->GetEntry() == NPC_ENTROPIUS) { - case NPC_ENTROPIUS: - me->SetVisible(false); - EntropiusGUID = summoned->GetGUID(); - if (HasEnraged) // If we hit phase transition while enraged, enrage Entropius as well. - summoned->CastSpell(summoned, SPELL_ENRAGE); - break; - case NPC_DARK_FIENDS: - summoned->CastSpell(summoned, SPELL_DARKFIEND_VISUAL); - break; + me->SetVisible(false); + _entropiusGUID = summon->GetGUID(); + if (_hasEnraged) + summon->CastSpell(summon, SPELL_ENRAGE, true); + return; } - summoned->AI()->AttackStart(SelectTarget(SELECT_TARGET_RANDOM, 0, 50, true)); - summons.Summon(summoned); + BossAI::JustSummoned(summon); } - void ExecuteEvent(uint32 eventId) override + void UpdateAI(uint32 diff) override { - switch (eventId) - { - case EVENT_DARKNESS: - if (!DarkFiend) - { - DarkFiend = true; - DoCastAOE(SPELL_DARKNESS); - } - else - me->SummonCreatureGroup(CREATURE_GROUP_DARKFIENDS); - events.ScheduleEvent(EVENT_DARKNESS, DarkFiend ? 3000 : 42000, 0, PHASE_ONE); - break; - case EVENT_SUMMON_HUMANOIDS: - me->SummonCreatureGroup(CREATURE_GROUP_HUMANOIDS); - events.ScheduleEvent(EVENT_SUMMON_HUMANOIDS, 60000, 0, PHASE_ONE); - break; - case EVENT_SUMMON_SENTINEL: - DoCastAOE(SPELL_OPEN_PORTAL_2); - events.ScheduleEvent(EVENT_SUMMON_SENTINEL, 30000, 0, PHASE_ONE); - break; - case EVENT_PHASE_TRANSITION: - DoCast(me, SPELL_SUMMON_ENTROPIUS); - break; - case EVENT_ENRAGE: - if (Creature* entropius = ObjectAccessor::GetCreature(*me, EntropiusGUID)) - entropius->CastSpell(entropius, SPELL_ENRAGE); - DoCast(me, SPELL_ENRAGE); - HasEnraged = true; - break; - default: - break; - } + if (!UpdateVictim()) + return; + + scheduler.Update(diff); } private: - bool DarkFiend; - bool HasEnraged; - ObjectGuid EntropiusGUID; + ObjectGuid _entropiusGUID; + bool _hasEnraged; + uint8 _phase; }; CreatureAI* GetAI(Creature* creature) const override @@ -289,89 +340,50 @@ class npc_muru_portal : public CreatureScript public: npc_muru_portal() : CreatureScript("npc_muru_portal") { } - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI<npc_muru_portalAI>(creature); - } - struct npc_muru_portalAI : public ScriptedAI { - npc_muru_portalAI(Creature* creature) : ScriptedAI(creature), Summons(creature) - { - Initialize(); - SetCombatMovement(false); - instance = creature->GetInstanceScript(); - } - - void Initialize() - { - SummonTimer = 5000; - - InAction = false; - SummonSentinel = false; - } - - InstanceScript* instance; - - SummonList Summons; - - bool SummonSentinel; - bool InAction; - - uint32 SummonTimer; - - void Reset() override - { - Initialize(); + npc_muru_portalAI(Creature* creature) : ScriptedAI(creature) { } - me->AddUnitState(UNIT_STATE_STUNNED); - - Summons.DespawnAll(); - } - - void JustSummoned(Creature* summoned) override + void JustSummoned(Creature* summon) override { - if (Player* target = ObjectAccessor::GetPlayer(*me, instance->GetGuidData(DATA_PLAYER_GUID))) - summoned->AI()->AttackStart(target); + DoCast(summon, SPELL_SUMMON_VOID_SENTINEL_SUMMONER_VISUAL, true); - Summons.Summon(summoned); + summon->m_Events.AddEvent(new VoidSpawnSummon(summon), summon->m_Events.CalculateTime(1500)); } - void SpellHit(Unit* /*caster*/, const SpellInfo* Spell) override + void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override { - float x, y, z, o; - me->GetHomePosition(x, y, z, o); - me->NearTeleportTo(x, y, z, o); - InAction = true; - switch (Spell->Id) + switch (spell->Id) { case SPELL_OPEN_ALL_PORTALS: - DoCastAOE(SPELL_OPEN_PORTAL); + DoCastAOE(SPELL_OPEN_PORTAL, true); + DoCastAOE(SPELL_TRANSFORM_VISUAL_MISSILE, true); break; case SPELL_OPEN_PORTAL_2: - DoCastAOE(SPELL_OPEN_PORTAL); - SummonSentinel = true; + DoCastAOE(SPELL_OPEN_PORTAL, true); + _scheduler.Schedule(Seconds(6), [this](TaskContext /*context*/) + { + DoCastAOE(SPELL_SUMMON_VOID_SENTINEL_SUMMONER, true); + }); + break; + default: break; } } void UpdateAI(uint32 diff) override { - if (!SummonSentinel) - { - if (InAction && instance->GetBossState(DATA_MURU) == NOT_STARTED) - Reset(); - return; - } - - if (SummonTimer <= diff) - { - DoCastAOE(SPELL_SUMMON_VOID_SENTINEL, false); - SummonTimer = 5000; - SummonSentinel = false; - } else SummonTimer -= diff; + _scheduler.Update(diff); } + + private: + TaskScheduler _scheduler; }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetSunwellPlateauAI<npc_muru_portalAI>(creature); + } }; class npc_dark_fiend : public CreatureScript @@ -379,11 +391,6 @@ class npc_dark_fiend : public CreatureScript public: npc_dark_fiend() : CreatureScript("npc_dark_fiend") { } - CreatureAI* GetAI(Creature* creature) const override - { - return new npc_dark_fiendAI(creature); - } - struct npc_dark_fiendAI : public ScriptedAI { npc_dark_fiendAI(Creature* creature) : ScriptedAI(creature) @@ -393,54 +400,56 @@ public: void Initialize() { - WaitTimer = 2000; - InAction = false; - } + me->SetDisplayId(me->GetCreatureTemplate()->Modelid2); + me->SetReactState(REACT_PASSIVE); + DoCast(me, SPELL_DARKFIEND_SKIN, true); - uint32 WaitTimer; - bool InAction; + _scheduler.Schedule(Seconds(2), [this](TaskContext /*context*/) + { + me->SetReactState(REACT_AGGRESSIVE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - void Reset() override - { - Initialize(); + if (Creature* _summoner = ObjectAccessor::GetCreature(*me, _summonerGUID)) + if (Unit* target = _summoner->AI()->SelectTarget(SELECT_TARGET_RANDOM, 0)) + AttackStart(target); + }); - me->AddUnitState(UNIT_STATE_STUNNED); + _scheduler.Schedule(Seconds(3), [this](TaskContext context) + { + if (me->IsWithinDist(me->GetVictim(), 5.0f) && me->HasAura(SPELL_DARKFIEND_SKIN)) + { + DoCastAOE(SPELL_DARKFIEND_DAMAGE, false); + me->DisappearAndDie(); + } + + context.Repeat(Milliseconds(500)); + }); } - void SpellHit(Unit* /*caster*/, const SpellInfo* Spell) override + void IsSummonedBy(Unit* summoner) override { - for (uint8 i = 0; i < 3; ++i) - if (Spell->Effects[i].Effect == 38) - me->DisappearAndDie(); + _summonerGUID = summoner->GetGUID(); } - void UpdateAI(uint32 diff) override + bool CanAIAttack(Unit const* /*target*/) const override { - if (!UpdateVictim()) - return; + return me->HasAura(SPELL_DARKFIEND_SKIN); + } - if (WaitTimer <= diff) - { - if (!InAction) - { - me->ClearUnitState(UNIT_STATE_STUNNED); - DoCastAOE(SPELL_DARKFIEND_SKIN, false); - AttackStart(SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)); - InAction = true; - WaitTimer = 500; - } - else - { - if (me->IsWithinDist(me->GetVictim(), 5)) - { - DoCastAOE(SPELL_DARKFIEND_AOE, false); - me->DisappearAndDie(); - } - WaitTimer = 500; - } - } else WaitTimer -= diff; + void UpdateAI(uint32 diff) override + { + _scheduler.Update(diff); } + + private: + TaskScheduler _scheduler; + ObjectGuid _summonerGUID; }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetSunwellPlateauAI<npc_dark_fiendAI>(creature); + } }; class npc_void_sentinel : public CreatureScript @@ -448,63 +457,54 @@ class npc_void_sentinel : public CreatureScript public: npc_void_sentinel() : CreatureScript("npc_void_sentinel") { } - CreatureAI* GetAI(Creature* creature) const override - { - return new npc_void_sentinelAI(creature); - } - struct npc_void_sentinelAI : public ScriptedAI { npc_void_sentinelAI(Creature* creature) : ScriptedAI(creature) { - Initialize(); + _instance = me->GetInstanceScript(); } - void Initialize() + void IsSummonedBy(Unit* /*summoner*/) override { - PulseTimer = 3000; - VoidBlastTimer = 45000; //is this a correct timer? + if (Creature* muru = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_MURU))) + muru->AI()->JustSummoned(me); } - uint32 PulseTimer; - uint32 VoidBlastTimer; - - void Reset() override + void EnterCombat(Unit* /*who*/) override { - Initialize(); + DoCast(me, SPELL_SHADOW_PULSE_PERIODIC, true); - float x, y, z, o; - me->GetHomePosition(x, y, z, o); - me->NearTeleportTo(x, y, 71, o); + _scheduler.Schedule(Seconds(45), [this](TaskContext context) + { + DoCastVictim(SPELL_VOID_BLAST, false); + + context.Repeat(); + }); } - void JustDied(Unit* killer) override + void JustDied(Unit* /*killer*/) override { - for (uint8 i = 0; i < 8; ++i) - if (Creature* temp = me->SummonCreature(NPC_VOID_SPAWN, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), float(rand32() % 6), TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 180000)) - temp->AI()->AttackStart(killer); + for (uint8 i = 0; i < MAX_VOID_SPAWNS; ++i) + DoCastAOE(SPELL_SUMMON_VOID_SPAWN, true); } void UpdateAI(uint32 diff) override { - if (!UpdateVictim()) - return; - - if (PulseTimer <= diff) - { - DoCastAOE(SPELL_SHADOW_PULSE, true); - PulseTimer = 3000; - } else PulseTimer -= diff; - - if (VoidBlastTimer <= diff) + _scheduler.Update(diff, [this] { - DoCastVictim(SPELL_VOID_BLAST, false); - VoidBlastTimer = 45000; - } else VoidBlastTimer -= diff; - - DoMeleeAttackIfReady(); + DoMeleeAttackIfReady(); + }); } + + private: + TaskScheduler _scheduler; + InstanceScript* _instance; }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetSunwellPlateauAI<npc_void_sentinelAI>(creature); + } }; class npc_blackhole : public CreatureScript @@ -512,84 +512,220 @@ class npc_blackhole : public CreatureScript public: npc_blackhole() : CreatureScript("npc_blackhole") { } - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI<npc_blackholeAI>(creature); - } - struct npc_blackholeAI : public ScriptedAI { npc_blackholeAI(Creature* creature) : ScriptedAI(creature) { - Initialize(); - instance = creature->GetInstanceScript(); + _instance = creature->GetInstanceScript(); } - void Initialize() - { - DespawnTimer = 15000; - SpellTimer = 5000; - Phase = 0; - NeedForAHack = 0; - } - - InstanceScript* instance; - - uint32 DespawnTimer; - uint32 SpellTimer; - uint8 Phase; - uint8 NeedForAHack; - void Reset() override { - Initialize(); + me->SetReactState(REACT_PASSIVE); + DoCast(SPELL_BLACKHOLE_SUMMON_VISUAL); - me->AddUnitState(UNIT_STATE_STUNNED); - DoCastAOE(SPELL_BLACKHOLE_SPAWN, true); - } + _scheduler.Schedule(Seconds(15), [this](TaskContext /*context*/) + { + me->DisappearAndDie(); + }); - void UpdateAI(uint32 diff) override - { - if (SpellTimer <= diff) + _scheduler.Schedule(Seconds(1), [this](TaskContext context) { - Unit* Victim = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_PLAYER_GUID)); - switch (NeedForAHack) + switch (context.GetRepeatCounter()) { case 0: - me->ClearUnitState(UNIT_STATE_STUNNED); - DoCastAOE(SPELL_BLACKHOLE_GROW, false); - if (Victim) - AttackStart(Victim); - SpellTimer = 700; - NeedForAHack = 2; + me->SetReactState(REACT_AGGRESSIVE); + DoCast(SPELL_BLACKHOLE_SUMMON_VISUAL_2); + if (Unit* victim = ObjectAccessor::GetUnit(*me, _instance->GetGuidData(DATA_PLAYER_GUID))) + AttackStart(victim); + context.Repeat(Milliseconds(1200)); break; case 1: - me->AddAura(SPELL_BLACKHOLE_GROW, me); - NeedForAHack = 2; - SpellTimer = 600; + DoCast(SPELL_BLACKHOLE_SUMMON_VISUAL); + context.Repeat(Seconds(2)); break; case 2: - SpellTimer = 400; - NeedForAHack = 3; - me->RemoveAura(SPELL_BLACKHOLE_GROW); + DoCast(SPELL_BLACKHOLE_PASSIVE); + DoCast(SPELL_BLACK_HOLE_VISUAL_2); + break; + default: break; - case 3: - SpellTimer = urand(400, 900); - NeedForAHack = 1; - if (Unit* Temp = me->GetVictim()) - { - if (Temp->GetPositionZ() > 73 && Victim) - AttackStart(Victim); - } else - return; } - } else SpellTimer -= diff; + }); + } - if (DespawnTimer <= diff) - me->DisappearAndDie(); - else DespawnTimer -= diff; + void UpdateAI(uint32 diff) override + { + _scheduler.Update(diff); } + + private: + TaskScheduler _scheduler; + InstanceScript* _instance; }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetSunwellPlateauAI<npc_blackholeAI>(creature); + } +}; + +class spell_summon_blood_elves_script : SpellScriptLoader +{ + public: + spell_summon_blood_elves_script() : SpellScriptLoader("spell_summon_blood_elves_script") { } + + class spell_summon_blood_elves_script_SpellScript : public SpellScript + { + PrepareSpellScript(spell_summon_blood_elves_script_SpellScript); + + bool Validate(SpellInfo const* /*spell*/) override + { + for (uint8 i = 0; i < MAX_SUMMON_BLOOD_ELVES; ++i) + if (!sSpellMgr->GetSpellInfo(SummonBloodElvesSpells[i])) + return false; + return true; + } + + void HandleScript(SpellEffIndex /*effIndex*/) + { + for (uint8 i = 0; i < MAX_SUMMON_BLOOD_ELVES; ++i) + GetCaster()->CastSpell((Unit*)nullptr, SummonBloodElvesSpells[urand(0,3)], true); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_summon_blood_elves_script_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_summon_blood_elves_script_SpellScript(); + } +}; + +class spell_muru_darkness : SpellScriptLoader +{ + public: + spell_muru_darkness() : SpellScriptLoader("spell_muru_darkness") { } + + class spell_muru_darkness_SpellScript : public SpellScript + { + PrepareSpellScript(spell_muru_darkness_SpellScript); + + bool Validate(SpellInfo const* /*spell*/) override + { + for (uint8 i = 0; i < MAX_SUMMON_DARK_FIEND; ++i) + if (!sSpellMgr->GetSpellInfo(SummonDarkFiendSpells[i])) + return false; + return true; + } + + void HandleAfterCast() + { + for (uint8 i = 0; i < MAX_SUMMON_DARK_FIEND; ++i) + GetCaster()->CastSpell((Unit*)nullptr, SummonDarkFiendSpells[i], true); + } + + void Register() override + { + AfterCast += SpellCastFn(spell_muru_darkness_SpellScript::HandleAfterCast); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_muru_darkness_SpellScript(); + } +}; + +class spell_dark_fiend_skin : public SpellScriptLoader +{ + public: + spell_dark_fiend_skin() : SpellScriptLoader("spell_dark_fiend_skin") { } + + class spell_dark_fiend_skin_AuraScript : public AuraScript + { + PrepareAuraScript(spell_dark_fiend_skin_AuraScript); + + void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (GetTargetApplication()->GetRemoveMode() != AURA_REMOVE_BY_ENEMY_SPELL) + return; + + if (Creature* target = GetTarget()->ToCreature()) + { + target->SetReactState(REACT_PASSIVE); + target->AttackStop(); + target->StopMoving(); + target->CastSpell(target, SPELL_DARKFIEND_VISUAL, true); + target->DespawnOrUnsummon(3000); + } + } + + void Register() override + { + AfterEffectRemove += AuraEffectRemoveFn(spell_dark_fiend_skin_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_dark_fiend_skin_AuraScript(); + } +}; + +class spell_transform_visual_missile_periodic : public SpellScriptLoader +{ + public: + spell_transform_visual_missile_periodic() : SpellScriptLoader("spell_transform_visual_missile_periodic") { } + + class spell_transform_visual_missile_periodic_AuraScript : public AuraScript + { + PrepareAuraScript(spell_transform_visual_missile_periodic_AuraScript); + + void OnPeriodic(AuraEffect const* /*aurEff*/) + { + GetTarget()->CastSpell((Unit*)nullptr, RAND(TRANSFORM_VISUAL_MISSILE_1, TRANSFORM_VISUAL_MISSILE_2), true); + } + + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_transform_visual_missile_periodic_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_transform_visual_missile_periodic_AuraScript(); + } +}; + +class spell_summon_blood_elves_periodic : public SpellScriptLoader +{ + public: + spell_summon_blood_elves_periodic() : SpellScriptLoader("spell_summon_blood_elves_periodic") { } + + class spell_summon_blood_elves_periodic_AuraScript : public AuraScript + { + PrepareAuraScript(spell_summon_blood_elves_periodic_AuraScript); + + void OnPeriodic(AuraEffect const* /*aurEff*/) + { + GetTarget()->CastSpell((Unit*)nullptr, SPELL_SUMMON_BLOOD_ELVES_SCRIPT, true); + } + + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_summon_blood_elves_periodic_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_summon_blood_elves_periodic_AuraScript(); + } }; void AddSC_boss_muru() @@ -600,4 +736,9 @@ void AddSC_boss_muru() new npc_dark_fiend(); new npc_void_sentinel(); new npc_blackhole(); + new spell_summon_blood_elves_script(); + new spell_muru_darkness(); + new spell_dark_fiend_skin(); + new spell_transform_visual_missile_periodic(); + new spell_summon_blood_elves_periodic(); } diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/sunwell_plateau.h b/src/server/scripts/EasternKingdoms/SunwellPlateau/sunwell_plateau.h index c6b4ae753a5..7ea0fc4bc7d 100644 --- a/src/server/scripts/EasternKingdoms/SunwellPlateau/sunwell_plateau.h +++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/sunwell_plateau.h @@ -97,7 +97,8 @@ enum CreatureIds NPC_FURY_MAGE = 25799, NPC_VOID_SENTINEL = 25772, NPC_VOID_SPAWN = 25824, - NPC_BLACK_HOLE = 25855 + NPC_BLACK_HOLE = 25855, + NPC_MURU_PORTAL_TARGET = 25770 }; enum GameObjectIds diff --git a/src/server/scripts/EasternKingdoms/Uldaman/boss_archaedas.cpp b/src/server/scripts/EasternKingdoms/Uldaman/boss_archaedas.cpp index a5fed30a6c6..68391c65655 100644 --- a/src/server/scripts/EasternKingdoms/Uldaman/boss_archaedas.cpp +++ b/src/server/scripts/EasternKingdoms/Uldaman/boss_archaedas.cpp @@ -98,7 +98,7 @@ class boss_archaedas : public CreatureScript instance->SetData(0, 5); // respawn any dead minions me->setFaction(35); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL); me->AddAura(SPELL_FREEZE_ANIM, me); } @@ -111,7 +111,7 @@ class boss_archaedas : public CreatureScript DoCast(minion, SPELL_AWAKEN_VAULT_WALKER, flag); minion->CastSpell(minion, SPELL_ARCHAEDAS_AWAKEN, true); minion->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - minion->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + minion->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL); minion->setFaction(14); minion->RemoveAura(SPELL_MINION_FREEZE_ANIM); } @@ -121,7 +121,7 @@ class boss_archaedas : public CreatureScript { me->setFaction(14); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL); } void SpellHit(Unit* /*caster*/, const SpellInfo* spell) override @@ -261,7 +261,7 @@ class npc_archaedas_minions : public CreatureScript me->setFaction(35); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL); me->RemoveAllAuras(); me->AddAura(SPELL_MINION_FREEZE_ANIM, me); } @@ -271,7 +271,7 @@ class npc_archaedas_minions : public CreatureScript me->setFaction (14); me->RemoveAllAuras(); me->RemoveFlag (UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->RemoveFlag (UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + me->RemoveFlag (UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL); bAmIAwake = true; } @@ -350,7 +350,7 @@ class npc_stonekeepers : public CreatureScript { me->setFaction(35); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL); me->RemoveAllAuras(); me->AddAura(SPELL_MINION_FREEZE_ANIM, me); } @@ -359,7 +359,7 @@ class npc_stonekeepers : public CreatureScript { me->setFaction(14); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL); } void UpdateAI(uint32 /*diff*/) override diff --git a/src/server/scripts/EasternKingdoms/Uldaman/instance_uldaman.cpp b/src/server/scripts/EasternKingdoms/Uldaman/instance_uldaman.cpp index 8c78fb7ff1b..28a3a4eb4e0 100644 --- a/src/server/scripts/EasternKingdoms/Uldaman/instance_uldaman.cpp +++ b/src/server/scripts/EasternKingdoms/Uldaman/instance_uldaman.cpp @@ -147,7 +147,7 @@ class instance_uldaman : public InstanceMapScript creature->setFaction(35); creature->RemoveAllAuras(); creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL); creature->AddAura(SPELL_MINION_FREEZE_ANIM, creature); } @@ -178,7 +178,7 @@ class instance_uldaman : public InstanceMapScript Creature* target = instance->GetCreature(*i); if (!target || !target->IsAlive()) continue; - target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL); target->setFaction(14); target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); target->RemoveAura(SPELL_MINION_FREEZE_ANIM); @@ -202,7 +202,7 @@ class instance_uldaman : public InstanceMapScript Creature* target = instance->GetCreature(*i); if (!target || !target->IsAlive() || target->getFaction() == 14) continue; - target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL); target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); target->setFaction(14); target->RemoveAura(SPELL_MINION_FREEZE_ANIM); @@ -268,7 +268,7 @@ class instance_uldaman : public InstanceMapScript return; ironaya->setFaction(415); - ironaya->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + ironaya->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL); ironaya->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); ironaya->GetMotionMaster()->Clear(); diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp index 8c179af2adf..3697b0876c8 100644 --- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp +++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp @@ -148,6 +148,11 @@ class boss_mandokir : public CreatureScript instance->SaveToDB(); } + void JustReachedHome() override + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC); + } + void EnterCombat(Unit* /*who*/) override { _EnterCombat(); @@ -194,9 +199,9 @@ class boss_mandokir : public CreatureScript me->SetWalk(false); if (id == POINT_MANDOKIR_END) { - me->SetHomePosition(PosMandokir[0]); + me->SetHomePosition(PosMandokir[1]); + me->GetMotionMaster()->MoveTargetedHome(); instance->SetBossState(DATA_MANDOKIR, NOT_STARTED); - me->DespawnOrUnsummon(6000); // No idea how to respawn on wipe. } } } diff --git a/src/server/scripts/Kalimdor/BlackfathomDeeps/instance_blackfathom_deeps.cpp b/src/server/scripts/Kalimdor/BlackfathomDeeps/instance_blackfathom_deeps.cpp index b0d6e782052..03c957fa221 100644 --- a/src/server/scripts/Kalimdor/BlackfathomDeeps/instance_blackfathom_deeps.cpp +++ b/src/server/scripts/Kalimdor/BlackfathomDeeps/instance_blackfathom_deeps.cpp @@ -174,7 +174,7 @@ public: if (state == DONE) if (GameObject* go = instance->GetGameObject(shrineOfGelihastGUID)) go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); - break; + break; case DATA_AKU_MAI: if (state == DONE) if (GameObject* go = instance->GetGameObject(altarOfTheDeepsGUID)) diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/old_hillsbrad.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/old_hillsbrad.cpp index 0526dcfa630..8e53ab06ca5 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/old_hillsbrad.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/old_hillsbrad.cpp @@ -535,12 +535,12 @@ public: if (!UpdateVictim()) return; - /// @todo add his abilities'n-crap here - if (!LowHp && HealthBelowPct(20)) - { - Talk(SAY_TH_RANDOM_LOW_HP); - LowHp = true; - } + /// @todo add his abilities'n-crap here + if (!LowHp && HealthBelowPct(20)) + { + Talk(SAY_TH_RANDOM_LOW_HP); + LowHp = true; + } } }; diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_aeonus.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_aeonus.cpp index 8715f3ca0f6..4d0f80d502d 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_aeonus.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_aeonus.cpp @@ -106,33 +106,33 @@ public: if (!UpdateVictim()) return; - events.Update(diff); + events.Update(diff); - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; - while (uint32 eventId = events.ExecuteEvent()) + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) { - switch (eventId) - { - case EVENT_SANDBREATH: - DoCastVictim(SPELL_SAND_BREATH); - events.ScheduleEvent(EVENT_SANDBREATH, urand(15000, 25000)); - break; - case EVENT_TIMESTOP: - DoCastVictim(SPELL_TIME_STOP); - events.ScheduleEvent(EVENT_TIMESTOP, urand(20000, 35000)); - break; - case EVENT_FRENZY: - Talk(EMOTE_FRENZY); - DoCast(me, SPELL_ENRAGE); - events.ScheduleEvent(EVENT_FRENZY, urand(20000, 35000)); - break; - default: - break; - } + case EVENT_SANDBREATH: + DoCastVictim(SPELL_SAND_BREATH); + events.ScheduleEvent(EVENT_SANDBREATH, urand(15000, 25000)); + break; + case EVENT_TIMESTOP: + DoCastVictim(SPELL_TIME_STOP); + events.ScheduleEvent(EVENT_TIMESTOP, urand(20000, 35000)); + break; + case EVENT_FRENZY: + Talk(EMOTE_FRENZY); + DoCast(me, SPELL_ENRAGE); + events.ScheduleEvent(EVENT_FRENZY, urand(20000, 35000)); + break; + default: + break; } - DoMeleeAttackIfReady(); + } + DoMeleeAttackIfReady(); } }; diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_temporus.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_temporus.cpp index 2befdabe550..844ce239bdf 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_temporus.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_temporus.cpp @@ -107,36 +107,36 @@ public: if (!UpdateVictim()) return; - events.Update(diff); + events.Update(diff); - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; - while (uint32 eventId = events.ExecuteEvent()) + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) { - switch (eventId) - { - case EVENT_HASTE: - DoCast(me, SPELL_HASTE); - events.ScheduleEvent(EVENT_HASTE, urand(20000, 25000)); - break; - case EVENT_MORTAL_WOUND: - DoCast(me, SPELL_MORTAL_WOUND); - events.ScheduleEvent(EVENT_MORTAL_WOUND, urand(10000, 20000)); - break; - case EVENT_WING_BUFFET: - DoCast(me, SPELL_WING_BUFFET); - events.ScheduleEvent(EVENT_WING_BUFFET, urand(20000, 30000)); - break; - case EVENT_SPELL_REFLECTION: // Only in Heroic - DoCast(me, SPELL_REFLECT); - events.ScheduleEvent(EVENT_SPELL_REFLECTION, urand(25000, 35000)); - break; - default: - break; - } + case EVENT_HASTE: + DoCast(me, SPELL_HASTE); + events.ScheduleEvent(EVENT_HASTE, urand(20000, 25000)); + break; + case EVENT_MORTAL_WOUND: + DoCast(me, SPELL_MORTAL_WOUND); + events.ScheduleEvent(EVENT_MORTAL_WOUND, urand(10000, 20000)); + break; + case EVENT_WING_BUFFET: + DoCast(me, SPELL_WING_BUFFET); + events.ScheduleEvent(EVENT_WING_BUFFET, urand(20000, 30000)); + break; + case EVENT_SPELL_REFLECTION: // Only in Heroic + DoCast(me, SPELL_REFLECT); + events.ScheduleEvent(EVENT_SPELL_REFLECTION, urand(25000, 35000)); + break; + default: + break; } - DoMeleeAttackIfReady(); + } + DoMeleeAttackIfReady(); } }; diff --git a/src/server/scripts/Kalimdor/zone_the_barrens.cpp b/src/server/scripts/Kalimdor/zone_the_barrens.cpp index b113615ca50..7a963d066b6 100644 --- a/src/server/scripts/Kalimdor/zone_the_barrens.cpp +++ b/src/server/scripts/Kalimdor/zone_the_barrens.cpp @@ -43,38 +43,37 @@ EndContentData */ ## npc_beaten_corpse ######*/ -#define GOSSIP_CORPSE "Examine corpse in detail..." - enum BeatenCorpse { - QUEST_LOST_IN_BATTLE = 4921 + GOSSIP_OPTION_ID_BEATEN_CORPSE = 0, + GOSSIP_MENU_OPTION_INSPECT_BODY = 2871 }; class npc_beaten_corpse : public CreatureScript { -public: - npc_beaten_corpse() : CreatureScript("npc_beaten_corpse") { } + public: + npc_beaten_corpse() : CreatureScript("npc_beaten_corpse") { } - bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) override - { - player->PlayerTalkClass->ClearMenus(); - if (action == GOSSIP_ACTION_INFO_DEF +1) + struct npc_beaten_corpseAI : public ScriptedAI { - player->SEND_GOSSIP_MENU(3558, creature->GetGUID()); - player->TalkedToCreature(creature->GetEntry(), creature->GetGUID()); - } - return true; - } - - bool OnGossipHello(Player* player, Creature* creature) override - { - if (player->GetQuestStatus(QUEST_LOST_IN_BATTLE) == QUEST_STATUS_INCOMPLETE || player->GetQuestStatus(QUEST_LOST_IN_BATTLE) == QUEST_STATUS_COMPLETE) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_CORPSE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + npc_beaten_corpseAI(Creature* creature) : ScriptedAI(creature) + { + } - player->SEND_GOSSIP_MENU(3557, creature->GetGUID()); - return true; - } + void sGossipSelect(Player* player, uint32 menuId, uint32 gossipListId) override + { + if (menuId == GOSSIP_MENU_OPTION_INSPECT_BODY && gossipListId == GOSSIP_OPTION_ID_BEATEN_CORPSE) + { + player->CLOSE_GOSSIP_MENU(); + player->TalkedToCreature(me->GetEntry(), me->GetGUID()); + } + } + }; + CreatureAI* GetAI(Creature* creature) const override + { + return new npc_beaten_corpseAI(creature); + } }; /*###### diff --git a/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_anubarak.cpp b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_anubarak.cpp index 16cfb30e2dc..2df0fceab9c 100644 --- a/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_anubarak.cpp +++ b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_anubarak.cpp @@ -156,7 +156,7 @@ public: ImpaleTarget = impaleTarget->GetGUID(); impaleTarget->SetReactState(REACT_PASSIVE); impaleTarget->SetDisplayId(DISPLAY_INVISIBLE); - impaleTarget->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE|UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); + impaleTarget->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL|UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); return impaleTarget; } diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp index abca9a42d45..7f4a2158d25 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp @@ -646,7 +646,7 @@ struct boss_jormungarAI : public BossAI // if the worm was mobile before submerging, make him stationary now if (WasMobile) { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL); SetCombatMovement(false); me->SetDisplayId(ModelStationary); me->CastSpell(me, SPELL_GROUND_VISUAL_1, true); @@ -658,7 +658,7 @@ struct boss_jormungarAI : public BossAI } else { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL); SetCombatMovement(true); me->GetMotionMaster()->MoveChase(me->GetVictim()); me->SetDisplayId(ModelMobile); @@ -1023,7 +1023,7 @@ class boss_icehowl : public CreatureScript me->SetTarget(_trampleTargetGUID); _trampleCast = false; SetCombatMovement(false); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_REMOVE_CLIENT_CONTROL); me->GetMotionMaster()->Clear(); me->GetMotionMaster()->MoveIdle(); events.ScheduleEvent(EVENT_TRAMPLE, 4*IN_MILLISECONDS); @@ -1107,7 +1107,7 @@ class boss_icehowl : public CreatureScript Talk(EMOTE_TRAMPLE_FAIL); } _movementStarted = false; - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_REMOVE_CLIENT_CONTROL); SetCombatMovement(true); me->GetMotionMaster()->MovementExpired(); me->GetMotionMaster()->Clear(); diff --git a/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_devourer_of_souls.cpp b/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_devourer_of_souls.cpp index 055d0a07f41..94d1d93225c 100644 --- a/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_devourer_of_souls.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_devourer_of_souls.cpp @@ -144,7 +144,7 @@ class boss_devourer_of_souls : public CreatureScript void Reset() override { _Reset(); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL); me->SetDisplayId(DISPLAY_ANGER); me->SetReactState(REACT_AGGRESSIVE); @@ -297,7 +297,7 @@ class boss_devourer_of_souls : public CreatureScript me->SetTarget(ObjectGuid::Empty); me->GetMotionMaster()->Clear(); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL); wailingSoulTick = 15; events.DelayEvents(18000); // no other events during wailing souls @@ -317,7 +317,7 @@ class boss_devourer_of_souls : public CreatureScript { me->SetReactState(REACT_AGGRESSIVE); me->SetDisplayId(DISPLAY_ANGER); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL); me->GetMotionMaster()->MoveChase(me->GetVictim()); events.ScheduleEvent(EVENT_WAILING_SOULS, urand(60000, 70000)); } diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp index d77842fff0a..73a7de36580 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp @@ -2461,6 +2461,33 @@ class spell_igb_teleport_players_on_victory : public SpellScriptLoader } }; +// 71201 - Battle Experience - proc should never happen, handled in script +class spell_igb_battle_experience_check : public SpellScriptLoader +{ +public: + spell_igb_battle_experience_check() : SpellScriptLoader("spell_igb_battle_experience_check") { } + + class spell_igb_battle_experience_check_AuraScript : public AuraScript + { + PrepareAuraScript(spell_igb_battle_experience_check_AuraScript); + + bool CheckProc(ProcEventInfo& /*eventInfo*/) + { + return false; + } + + void Register() override + { + DoCheckProc += AuraCheckProcFn(spell_igb_battle_experience_check_AuraScript::CheckProc); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_igb_battle_experience_check_AuraScript(); + } +}; + class achievement_im_on_a_boat : public AchievementCriteriaScript { public: @@ -2500,5 +2527,6 @@ void AddSC_boss_icecrown_gunship_battle() new spell_igb_gunship_fall_teleport(); new spell_igb_check_for_players(); new spell_igb_teleport_players_on_victory(); + new spell_igb_battle_experience_check(); new achievement_im_on_a_boat(); } diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp index caa37465165..1a37d5238d2 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp @@ -604,6 +604,7 @@ class npc_ice_tomb : public CreatureScript _trappedPlayerGUID.Clear(); player->RemoveAurasDueToSpell(SPELL_ICE_TOMB_DAMAGE); player->RemoveAurasDueToSpell(SPELL_ASPHYXIATION); + player->RemoveAurasDueToSpell(SPELL_ICE_TOMB_UNTARGETABLE); } } @@ -1284,9 +1285,9 @@ class spell_sindragosa_ice_tomb : public SpellScriptLoader public: spell_sindragosa_ice_tomb() : SpellScriptLoader("spell_sindragosa_ice_tomb_trap") { } - class spell_sindragosa_ice_tomb_SpellScript : public SpellScript + class spell_sindragosa_ice_tomb_AuraScript : public AuraScript { - PrepareSpellScript(spell_sindragosa_ice_tomb_SpellScript); + PrepareAuraScript(spell_sindragosa_ice_tomb_AuraScript); bool Validate(SpellInfo const* /*spell*/) override { @@ -1297,46 +1298,42 @@ class spell_sindragosa_ice_tomb : public SpellScriptLoader return true; } - void SummonTomb() + void PeriodicTick(AuraEffect const* aurEff) { - Position pos = GetHitUnit()->GetPosition(); - if (TempSummon* summon = GetCaster()->SummonCreature(NPC_ICE_TOMB, pos)) + PreventDefaultAction(); + + if (aurEff->GetTickNumber() == 1) { - summon->AI()->SetGUID(GetHitUnit()->GetGUID(), DATA_TRAPPED_PLAYER); - if (GameObject* go = summon->SummonGameObject(GO_ICE_BLOCK, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 0)) + if (Unit* caster = GetCaster()) { - go->SetSpellId(SPELL_ICE_TOMB_DAMAGE); - summon->AddGameObject(go); + Position pos = GetTarget()->GetPosition(); + + if (TempSummon* summon = caster->SummonCreature(NPC_ICE_TOMB, pos)) + { + summon->AI()->SetGUID(GetTarget()->GetGUID(), DATA_TRAPPED_PLAYER); + GetTarget()->CastSpell(GetTarget(), SPELL_ICE_TOMB_UNTARGETABLE); + if (GameObject* go = summon->SummonGameObject(GO_ICE_BLOCK, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 0)) + { + go->SetSpellId(SPELL_ICE_TOMB_DAMAGE); + summon->AddGameObject(go); + } + } } } } - void Register() override - { - AfterHit += SpellHitFn(spell_sindragosa_ice_tomb_SpellScript::SummonTomb); - } - }; - - class spell_sindragosa_ice_tomb_AuraScript : public AuraScript - { - PrepareAuraScript(spell_sindragosa_ice_tomb_AuraScript); - - void PeriodicTick(AuraEffect const* /*aurEff*/) + void HandleRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) { - PreventDefaultAction(); + GetTarget()->RemoveAurasDueToSpell(SPELL_ICE_TOMB_UNTARGETABLE); } void Register() override { OnEffectPeriodic += AuraEffectPeriodicFn(spell_sindragosa_ice_tomb_AuraScript::PeriodicTick, EFFECT_2, SPELL_AURA_PERIODIC_TRIGGER_SPELL); + AfterEffectRemove += AuraEffectRemoveFn(spell_sindragosa_ice_tomb_AuraScript::HandleRemove, EFFECT_2, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL); } }; - SpellScript* GetSpellScript() const override - { - return new spell_sindragosa_ice_tomb_SpellScript(); - } - AuraScript* GetAuraScript() const override { return new spell_sindragosa_ice_tomb_AuraScript(); diff --git a/src/server/scripts/Northrend/IsleOfConquest/boss_ioc_horde_alliance.cpp b/src/server/scripts/Northrend/IsleOfConquest/boss_ioc_horde_alliance.cpp new file mode 100644 index 00000000000..71d90da21a1 --- /dev/null +++ b/src/server/scripts/Northrend/IsleOfConquest/boss_ioc_horde_alliance.cpp @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "BattlegroundIC.h" + +enum BossSpells +{ + SPELL_BRUTAL_STRIKE = 58460, + SPELL_DAGGER_THROW = 67280, + SPELL_CRUSHING_LEAP = 68506, + SPELL_RAGE = 66776 +}; + +enum BossEvents +{ + EVENT_BRUTAL_STRIKE = 1, + EVENT_DAGGER_THROW = 2, + EVENT_CRUSHING_LEAP = 3, + EVENT_CHECK_RANGE = 4 +}; + +class boss_ioc_horde_alliance : public CreatureScript +{ +public: + boss_ioc_horde_alliance() : CreatureScript("boss_ioc_horde_alliance") { } + + struct boss_ioc_horde_allianceAI : public ScriptedAI + { + boss_ioc_horde_allianceAI(Creature* creature) : ScriptedAI(creature) { } + + void Reset() override + { + _events.Reset(); + + uint32 _npcGuard; + if (me->GetEntry() == NPC_HIGH_COMMANDER_HALFORD_WYRMBANE) + _npcGuard = NPC_SEVEN_TH_LEGION_INFANTRY; + else + _npcGuard = NPC_KOR_KRON_GUARD; + + std::list<Creature*> guardsList; + me->GetCreatureListWithEntryInGrid(guardsList, _npcGuard, 100.0f); + for (std::list<Creature*>::const_iterator itr = guardsList.begin(); itr != guardsList.end(); ++itr) + (*itr)->Respawn(); + }; + + void EnterCombat(Unit* /*who*/) override + { + _events.ScheduleEvent(EVENT_BRUTAL_STRIKE, 5 * IN_MILLISECONDS); + _events.ScheduleEvent(EVENT_DAGGER_THROW, 7 * IN_MILLISECONDS); + _events.ScheduleEvent(EVENT_CHECK_RANGE, 1 * IN_MILLISECONDS); + _events.ScheduleEvent(EVENT_CRUSHING_LEAP, 15 * IN_MILLISECONDS); + } + + void SpellHit(Unit* caster, SpellInfo const* /*spell*/) override + { + if (caster->IsVehicle()) + me->Kill(caster); + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + _events.Update(diff); + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_BRUTAL_STRIKE: + DoCastVictim(SPELL_BRUTAL_STRIKE); + _events.ScheduleEvent(EVENT_BRUTAL_STRIKE, 5 * IN_MILLISECONDS); + break; + case EVENT_DAGGER_THROW: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1)) + DoCast(target, SPELL_DAGGER_THROW); + _events.ScheduleEvent(EVENT_DAGGER_THROW, 7 * IN_MILLISECONDS); + break; + case EVENT_CRUSHING_LEAP: + DoCastVictim(SPELL_CRUSHING_LEAP); + _events.ScheduleEvent(EVENT_CRUSHING_LEAP, 25 * IN_MILLISECONDS); + break; + case EVENT_CHECK_RANGE: + if (me->GetDistance(me->GetHomePosition()) > 25.0f) + DoCast(me, SPELL_RAGE); + else + me->RemoveAurasDueToSpell(SPELL_RAGE); + _events.ScheduleEvent(EVENT_CHECK_RANGE, 1 * IN_MILLISECONDS); + break; + default: + break; + } + } + + DoMeleeAttackIfReady(); + } + + private: + EventMap _events; + }; + + CreatureAI* GetAI(Creature* creature) const + { + return new boss_ioc_horde_allianceAI(creature); + } +}; + +void AddSC_boss_ioc_horde_alliance() +{ + new boss_ioc_horde_alliance(); +} diff --git a/src/server/scripts/Northrend/isle_of_conquest.cpp b/src/server/scripts/Northrend/IsleOfConquest/isle_of_conquest.cpp index 11cc645f0cb..f7e83ff1f42 100644 --- a/src/server/scripts/Northrend/isle_of_conquest.cpp +++ b/src/server/scripts/Northrend/IsleOfConquest/isle_of_conquest.cpp @@ -259,6 +259,58 @@ class spell_ioc_launch : public SpellScriptLoader } }; +enum SeaforiumBombSpells +{ + SPELL_SEAFORIUM_BLAST = 66676, + SPELL_HUGE_SEAFORIUM_BLAST = 66672, + SPELL_A_BOMB_INABLE_CREDIT = 68366, + SPELL_A_BOMB_INATION_CREDIT = 68367 +}; + +class spell_ioc_seaforium_blast_credit : public SpellScriptLoader +{ + public: + spell_ioc_seaforium_blast_credit() : SpellScriptLoader("spell_ioc_seaforium_blast_credit") { } + + class spell_ioc_seaforium_blast_credit_SpellScript : public SpellScript + { + PrepareSpellScript(spell_ioc_seaforium_blast_credit_SpellScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_A_BOMB_INABLE_CREDIT) || !sSpellMgr->GetSpellInfo(SPELL_A_BOMB_INATION_CREDIT)) + return false; + return true; + } + + void HandleAchievementCredit(SpellEffIndex /*effIndex*/) + { + uint32 _creditSpell = 0; + Unit* caster = GetOriginalCaster(); + if (!caster) + return; + + if (GetSpellInfo()->Id == SPELL_SEAFORIUM_BLAST) + _creditSpell = SPELL_A_BOMB_INABLE_CREDIT; + else if (GetSpellInfo()->Id == SPELL_HUGE_SEAFORIUM_BLAST) + _creditSpell = SPELL_A_BOMB_INATION_CREDIT; + + if (GetHitGObj() && GetHitGObj()->IsDestructibleBuilding()) + caster->CastSpell(caster, _creditSpell, true); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_ioc_seaforium_blast_credit_SpellScript::HandleAchievementCredit, EFFECT_1, SPELL_EFFECT_GAMEOBJECT_DAMAGE); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_ioc_seaforium_blast_credit_SpellScript(); + } +}; + void AddSC_isle_of_conquest() { new npc_four_car_garage(); @@ -266,4 +318,5 @@ void AddSC_isle_of_conquest() new spell_ioc_gunship_portal(); new spell_ioc_parachute_ic(); new spell_ioc_launch(); + new spell_ioc_seaforium_blast_credit(); } diff --git a/src/server/scripts/Northrend/Naxxramas/boss_gluth.cpp b/src/server/scripts/Northrend/Naxxramas/boss_gluth.cpp index 1e2eb06a2d5..ef6ccf5bf4b 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_gluth.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_gluth.cpp @@ -332,7 +332,7 @@ public: OnEffectHit += SpellEffectFn(spell_gluth_decimate_SpellScript::HandleEvent, EFFECT_2, SPELL_EFFECT_SEND_EVENT); } - bool Load() + bool Load() override { return GetCaster() && GetCaster()->GetEntry() == NPC_GLUTH; } @@ -366,7 +366,7 @@ public: AfterHit += SpellHitFn(spell_gluth_zombiechow_search_SpellScript::HealForEachTargetHit); } - bool Load() + bool Load() override { return GetCaster() && GetCaster()->GetEntry() == NPC_GLUTH; } @@ -393,6 +393,7 @@ public: GluthGUID = creature->GetInstanceScript()->GetGuidData(DATA_GLUTH); DoCast(me, SPELL_INFECTED_WOUND); + timer = 0; state = STATE_ZOMBIE_NORMAL; } diff --git a/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp b/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp index 47807ec28cb..42efdfbfe67 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp @@ -309,7 +309,7 @@ public: _Reset(); me->setFaction(35); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_NOT_SELECTABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_REMOVE_CLIENT_CONTROL | UNIT_FLAG_NOT_SELECTABLE); ResetPlayerScale(); spawns.DespawnAll(); @@ -356,7 +356,7 @@ public: } DoCast(me, SPELL_KELTHUZAD_CHANNEL, false); Talk(SAY_SUMMON_MINIONS); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_NOT_SELECTABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_REMOVE_CLIENT_CONTROL | UNIT_FLAG_NOT_SELECTABLE); me->SetFloatValue(UNIT_FIELD_COMBATREACH, 4); me->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, 4); events.SetPhase(PHASE_ONE); @@ -426,7 +426,7 @@ public: Talk(SAY_AGGRO); Talk(EMOTE_PHASE_TWO); spawns.DespawnAll(); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_NOT_SELECTABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_REMOVE_CLIENT_CONTROL | UNIT_FLAG_NOT_SELECTABLE); me->CastStop(); DoStartMovement(me->GetVictim()); diff --git a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp index f000d7a3ef7..3d5a6ee8dfb 100644 --- a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp +++ b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp @@ -1224,13 +1224,15 @@ public: void DoAction(int32 /*action*/) override { if (Vehicle* vehicleTemp = me->GetVehicleKit()) + { if (vehicleTemp->GetPassenger(0) && vehicleTemp->GetPassenger(0)->GetTypeId() == TYPEID_PLAYER) { vehicleTemp->RemoveAllPassengers(); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); } + } - me->DespawnOrUnsummon(3*IN_MILLISECONDS); + me->DespawnOrUnsummon(3*IN_MILLISECONDS); } void MovementInform(uint32 type, uint32 id) override diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp index 8f7687d0fca..55295a534e1 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp @@ -113,7 +113,7 @@ public: Initialize(); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_DISABLE_MOVE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_REMOVE_CLIENT_CONTROL); if (!me->IsVisible()) me->SetVisible(true); @@ -152,7 +152,7 @@ public: me->AttackStop(); me->SetVisible(false); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_DISABLE_MOVE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_REMOVE_CLIENT_CONTROL); me->GetMotionMaster()->Clear(); me->GetMotionMaster()->MoveIdle(); @@ -236,7 +236,7 @@ public: else if (lSparkList.empty()) { me->SetVisible(true); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_DISABLE_MOVE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_REMOVE_CLIENT_CONTROL); DoCast(me, SPELL_SPARK_DESPAWN, false); diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp index 05beacca638..fa59c021cad 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp @@ -171,8 +171,7 @@ enum FreyaNpcs enum FreyaActions { - ACTION_ELDER_DEATH = 1, - ACTION_ELDER_FREYA_KILLED = 2 + ACTION_ELDER_FREYA_KILLED = 1 }; enum FreyaEvents @@ -619,7 +618,7 @@ class boss_freya : public CreatureScript Elder->AttackStop(); Elder->CombatStop(true); Elder->DeleteThreatList(); - Elder->GetAI()->DoAction(ACTION_ELDER_FREYA_KILLED); + Elder->AI()->DoAction(ACTION_ELDER_FREYA_KILLED); } } } @@ -705,19 +704,10 @@ class boss_elder_brightleaf : public CreatureScript Talk(SAY_ELDER_SLAY); } - void JustDied(Unit* killer) override + void JustDied(Unit* /*killer*/) override { _JustDied(); Talk(SAY_ELDER_DEATH); - - if (killer->GetTypeId() == TYPEID_PLAYER) - { - if (Creature* Ironbranch = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_IRONBRANCH))) - Ironbranch->AI()->DoAction(ACTION_ELDER_DEATH); - - if (Creature* Stonebark = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_STONEBARK))) - Stonebark->AI()->DoAction(ACTION_ELDER_DEATH); - } } void EnterCombat(Unit* /*who*/) override @@ -812,19 +802,10 @@ class boss_elder_stonebark : public CreatureScript Talk(SAY_ELDER_SLAY); } - void JustDied(Unit* killer) override + void JustDied(Unit* /*killer*/) override { _JustDied(); Talk(SAY_ELDER_DEATH); - - if (killer->GetTypeId() == TYPEID_PLAYER) - { - if (Creature* Ironbranch = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_IRONBRANCH))) - Ironbranch->AI()->DoAction(ACTION_ELDER_DEATH); - - if (Creature* Brightleaf = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_BRIGHTLEAF))) - Brightleaf->AI()->DoAction(ACTION_ELDER_DEATH); - } } void EnterCombat(Unit* /*who*/) override @@ -925,19 +906,10 @@ class boss_elder_ironbranch : public CreatureScript Talk(SAY_ELDER_SLAY); } - void JustDied(Unit* killer) override + void JustDied(Unit* /*killer*/) override { _JustDied(); Talk(SAY_ELDER_DEATH); - - if (killer->GetTypeId() == TYPEID_PLAYER) - { - if (Creature* Brightleaf = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_BRIGHTLEAF))) - Brightleaf->AI()->DoAction(ACTION_ELDER_DEATH); - - if (Creature* Stonebark = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_STONEBARK))) - Stonebark->AI()->DoAction(ACTION_ELDER_DEATH); - } } void EnterCombat(Unit* /*who*/) override diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_general_vezax.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_general_vezax.cpp index 09d95b34521..cbd24141bdf 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_general_vezax.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_general_vezax.cpp @@ -415,7 +415,7 @@ class npc_saronite_vapors : public CreatureScript if (damage >= me->GetHealth()) { damage = 0; - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_DISABLE_MOVE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_REMOVE_CLIENT_CONTROL); me->SetStandState(UNIT_STAND_STATE_DEAD); me->SetHealth(me->GetMaxHealth()); me->RemoveAllAuras(); diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_hodir.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_hodir.cpp index c35a5936822..86068a1ecba 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_hodir.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_hodir.cpp @@ -184,7 +184,7 @@ class npc_flash_freeze : public CreatureScript Initialize(); instance = me->GetInstanceScript(); me->SetDisplayId(me->GetCreatureTemplate()->Modelid2); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_STUNNED | UNIT_FLAG_PACIFIED); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL | UNIT_FLAG_STUNNED | UNIT_FLAG_PACIFIED); } void Initialize() @@ -259,7 +259,7 @@ class npc_ice_block : public CreatureScript { instance = me->GetInstanceScript(); me->SetDisplayId(me->GetCreatureTemplate()->Modelid2); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_STUNNED | UNIT_FLAG_PACIFIED); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL | UNIT_FLAG_STUNNED | UNIT_FLAG_PACIFIED); } InstanceScript* instance; @@ -269,7 +269,7 @@ class npc_ice_block : public CreatureScript void IsSummonedBy(Unit* summoner) override { targetGUID = summoner->GetGUID(); - summoner->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_STUNNED | UNIT_FLAG_PACIFIED); + summoner->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL | UNIT_FLAG_STUNNED | UNIT_FLAG_PACIFIED); me->SetInCombatWith(summoner); me->AddThreat(summoner, 250.0f); summoner->AddThreat(me, 250.0f); @@ -285,7 +285,7 @@ class npc_ice_block : public CreatureScript { if (Creature* Helper = ObjectAccessor::GetCreature(*me, targetGUID)) { - Helper->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_STUNNED | UNIT_FLAG_PACIFIED); + Helper->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL | UNIT_FLAG_STUNNED | UNIT_FLAG_PACIFIED); if (Creature* Hodir = ObjectAccessor::GetCreature(*me, instance->GetGuidData(BOSS_HODIR))) { @@ -388,7 +388,7 @@ class boss_hodir : public CreatureScript me->RemoveAllAttackers(); me->AttackStop(); me->SetReactState(REACT_PASSIVE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_REMOVE_CLIENT_CONTROL); me->InterruptNonMeleeSpells(true); me->StopMoving(); me->GetMotionMaster()->Clear(); @@ -539,7 +539,7 @@ class npc_icicle : public CreatureScript { Initialize(); me->SetDisplayId(me->GetCreatureTemplate()->Modelid1); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_PACIFIED | UNIT_FLAG_NOT_SELECTABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL | UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_PACIFIED | UNIT_FLAG_NOT_SELECTABLE); me->SetReactState(REACT_PASSIVE); } @@ -593,7 +593,7 @@ class npc_snowpacked_icicle : public CreatureScript { Initialize(); me->SetDisplayId(me->GetCreatureTemplate()->Modelid2); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_PACIFIED); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL | UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_PACIFIED); me->SetReactState(REACT_PASSIVE); } diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_ignis.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_ignis.cpp index cd214a0114f..7106e9e4ebe 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_ignis.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_ignis.cpp @@ -178,7 +178,7 @@ class boss_ignis : public CreatureScript { summon->setFaction(16); summon->SetReactState(REACT_AGGRESSIVE); - summon->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_PACIFIED | UNIT_FLAG_STUNNED | UNIT_FLAG_DISABLE_MOVE); + summon->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_PACIFIED | UNIT_FLAG_STUNNED | UNIT_FLAG_REMOVE_CLIENT_CONTROL); } summon->AI()->AttackStart(me->GetVictim()); @@ -375,7 +375,7 @@ class npc_scorch_ground : public CreatureScript npc_scorch_groundAI(Creature* creature) : ScriptedAI(creature) { Initialize(); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE |UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_PACIFIED); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL |UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_PACIFIED); creature->SetDisplayId(16925); //model 2 in db cannot overwrite wdb fields } diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_kologarn.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_kologarn.cpp index 470ad388fff..45d4fa58a03 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_kologarn.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_kologarn.cpp @@ -104,7 +104,7 @@ class boss_kologarn : public CreatureScript left(false), right(false) { me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL); DoCast(SPELL_KOLOGARN_REDUCE_PARRY); SetCombatMovement(false); diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_palehoof.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_palehoof.cpp index ee71c696d7c..3dec0c60991 100644 --- a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_palehoof.cpp +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_palehoof.cpp @@ -102,7 +102,7 @@ public: Sequence[i] = Phase(i); /// This ensures a random order and only executes each phase once. - std::random_shuffle(Sequence, Sequence + PHASE_GORTOK_PALEHOOF); + Trinity::Containers::RandomShuffle(Sequence); uiArcingSmashTimer = 15000; uiImpaleTimer = 12000; @@ -118,7 +118,7 @@ public: uint32 uiWhiteringRoarTimer; Phase currentPhase; uint8 AddCount; - Phase Sequence[4]; + std::array<Phase, 4> Sequence; void Reset() override { diff --git a/src/server/scripts/Northrend/VaultOfArchavon/boss_toravon.cpp b/src/server/scripts/Northrend/VaultOfArchavon/boss_toravon.cpp index 06ebcbdc2fb..e7305e53808 100644 --- a/src/server/scripts/Northrend/VaultOfArchavon/boss_toravon.cpp +++ b/src/server/scripts/Northrend/VaultOfArchavon/boss_toravon.cpp @@ -247,7 +247,7 @@ class npc_frozen_orb_stalker : public CreatureScript npc_frozen_orb_stalkerAI(Creature* creature) : ScriptedAI(creature) { creature->SetVisible(false); - creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE); + creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_REMOVE_CLIENT_CONTROL); creature->SetReactState(REACT_PASSIVE); instance = creature->GetInstanceScript(); diff --git a/src/server/scripts/Northrend/northrend_script_loader.cpp b/src/server/scripts/Northrend/northrend_script_loader.cpp index 7d104b85f6d..d84bb1c4072 100644 --- a/src/server/scripts/Northrend/northrend_script_loader.cpp +++ b/src/server/scripts/Northrend/northrend_script_loader.cpp @@ -178,6 +178,8 @@ void AddSC_boss_baltharus_the_warborn(); void AddSC_boss_saviana_ragefire(); void AddSC_boss_general_zarithrian(); void AddSC_boss_halion(); +void AddSC_isle_of_conquest(); // Isle of Conquest +void AddSC_boss_ioc_horde_alliance(); void AddSC_dalaran(); void AddSC_borean_tundra(); @@ -190,7 +192,6 @@ void AddSC_storm_peaks(); void AddSC_wintergrasp(); void AddSC_zuldrak(); void AddSC_crystalsong_forest(); -void AddSC_isle_of_conquest(); // The name of this function should match: // void Add${NameOfDirectory}Scripts() @@ -358,6 +359,8 @@ void AddNorthrendScripts() AddSC_boss_saviana_ragefire(); AddSC_boss_general_zarithrian(); AddSC_boss_halion(); + AddSC_isle_of_conquest(); // Isle of Conquest + AddSC_boss_ioc_horde_alliance(); AddSC_dalaran(); AddSC_borean_tundra(); @@ -370,5 +373,4 @@ void AddNorthrendScripts() AddSC_wintergrasp(); AddSC_zuldrak(); AddSC_crystalsong_forest(); - AddSC_isle_of_conquest(); } diff --git a/src/server/scripts/Northrend/zone_grizzly_hills.cpp b/src/server/scripts/Northrend/zone_grizzly_hills.cpp index 59802165a94..adade245c2b 100644 --- a/src/server/scripts/Northrend/zone_grizzly_hills.cpp +++ b/src/server/scripts/Northrend/zone_grizzly_hills.cpp @@ -22,6 +22,7 @@ #include "Player.h" #include "SpellScript.h" #include "CreatureTextMgr.h" +#include "CombatAI.h" /*###### ## Quest 12027: Mr. Floppy's Perilous Adventure @@ -854,6 +855,260 @@ class spell_infected_worgen_bite : public SpellScriptLoader } }; +/*###### +## Quest: Riding the Red Rocket +######*/ + +enum RedRocket +{ + SPELL_VEHICLE_WARHEAD_FUSE = 49107, + SPELL_ALLIANCE_KILL_CREDIT_TORPEDO = 49510, + SPELL_HORDE_KILL_CREDIT_TORPEDO = 49340, + NPC_HORDE_LUMBERBOAT = 27702, + NPC_ALLIANCE_LUMBERBOAT = 27688, + SPELL_DETONATE = 49250 +}; + +class npc_rocket_propelled_warhead : public CreatureScript +{ +public: + npc_rocket_propelled_warhead() : CreatureScript("npc_rocket_propelled_warhead") { } + + struct npc_rocket_propelled_warheadAI : public VehicleAI + { + npc_rocket_propelled_warheadAI(Creature* creature) : VehicleAI(creature) + { + _finished = false; + _faction = ALLIANCE; + } + + void PassengerBoarded(Unit* who, int8 /*seatId*/, bool apply) override + { + if (apply && who->ToPlayer()) + { + DoCast(me, SPELL_VEHICLE_WARHEAD_FUSE); + _faction = who->ToPlayer()->GetTeam(); + } + } + + void JustReachedHome() override + { + _finished = false; + me->SetVisible(true); + me->GetMotionMaster()->Clear(true); + } + + void DoAction(int32 /*action*/) override + { + FinishQuest(false, _faction); + } + + void SpellHit(Unit* caster, SpellInfo const* /*spellInfo*/) override + { + if (caster->GetEntry() == NPC_HORDE_LUMBERBOAT || caster->GetEntry() == NPC_ALLIANCE_LUMBERBOAT) + FinishQuest(true, _faction); + } + + void FinishQuest(bool success, uint32 faction) + { + if (_finished) + return; + + _finished = true; + + if (success) + DoCast(me, faction == ALLIANCE ? SPELL_ALLIANCE_KILL_CREDIT_TORPEDO : SPELL_HORDE_KILL_CREDIT_TORPEDO); + + DoCast(me, SPELL_DETONATE); + me->RemoveAllAuras(); + me->SetVisible(false); + me->GetMotionMaster()->MoveTargetedHome(); + } + + private: + uint32 _faction; + bool _finished; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return new npc_rocket_propelled_warheadAI(creature); + } +}; + +enum WarheadSpells +{ + SPELL_WARHEAD_Z_CHECK = 61678, + SPELL_WARHEAD_SEEKING_LUMBERSHIP = 49331, + SPELL_WARHEAD_FUSE = 49181 +}; +// 49107 - Vehicle: Warhead Fuse +class spell_vehicle_warhead_fuse : public SpellScriptLoader +{ +public: + spell_vehicle_warhead_fuse() : SpellScriptLoader("spell_vehicle_warhead_fuse") { } + + class spell_vehicle_warhead_fuse_SpellScript : public SpellScript + { + PrepareSpellScript(spell_vehicle_warhead_fuse_SpellScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_WARHEAD_Z_CHECK) || !sSpellMgr->GetSpellInfo(SPELL_WARHEAD_SEEKING_LUMBERSHIP) || !sSpellMgr->GetSpellInfo(SPELL_WARHEAD_FUSE)) + return false; + return true; + } + + void HandleDummy(SpellEffIndex /*effIndex*/) + { + Unit* caster = GetCaster(); + + caster->CastSpell(caster, SPELL_WARHEAD_Z_CHECK, true); + caster->CastSpell(caster, SPELL_WARHEAD_SEEKING_LUMBERSHIP, true); + caster->CastSpell(caster, SPELL_WARHEAD_FUSE, true); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_vehicle_warhead_fuse_SpellScript::HandleDummy, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_vehicle_warhead_fuse_SpellScript(); + } +}; + +enum WarheadDenonate +{ + SPELL_PARACHUTE = 66154, + SPELL_TORPEDO_EXPLOSION = 49290, + NPC_ALLIANCE_LUMBERBOAT_EXPLOSIONS = 27689 +}; +// 49250 - Detonate +class spell_warhead_detonate : public SpellScriptLoader +{ +public: + spell_warhead_detonate() : SpellScriptLoader("spell_warhead_detonate") { } + + class spell_warhead_detonate_SpellScript : public SpellScript + { + PrepareSpellScript(spell_warhead_detonate_SpellScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_PARACHUTE) || !sSpellMgr->GetSpellInfo(SPELL_TORPEDO_EXPLOSION)) + return false; + return true; + } + + void HandleDummy(SpellEffIndex /*effIndex*/) + { + Unit* caster = GetCaster(); + Player* player = GetHitPlayer(); + if (!player) + return; + + player->ExitVehicle(); + float horizontalSpeed = 3.0f; + float verticalSpeed = 40.0f; + player->KnockbackFrom(caster->GetPositionX(), caster->GetPositionY(), horizontalSpeed, verticalSpeed); + caster->CastSpell(player, SPELL_PARACHUTE, true); + + std::list<Creature*> explosionBunnys; + caster->GetCreatureListWithEntryInGrid(explosionBunnys, NPC_ALLIANCE_LUMBERBOAT_EXPLOSIONS, 90.0f); + for (std::list<Creature*>::const_iterator itr = explosionBunnys.begin(); itr != explosionBunnys.end(); ++itr) + (*itr)->CastSpell((*itr), SPELL_TORPEDO_EXPLOSION, true); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_warhead_detonate_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_warhead_detonate_SpellScript(); + } +}; + +// 61678 - Z Check +class spell_z_check : public SpellScriptLoader +{ +public: + spell_z_check() : SpellScriptLoader("spell_z_check") { } + + class spell_z_check_AuraScript : public AuraScript + { + PrepareAuraScript(spell_z_check_AuraScript); + + public: + spell_z_check_AuraScript() + { + _posZ = 0.0f; + } + + void HandleEffectApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + _posZ = GetTarget()->GetPositionZ(); + } + + void HandleEffectPeriodic(AuraEffect const* /*aurEff*/) + { + PreventDefaultAction(); + + if (_posZ != GetTarget()->GetPositionZ()) + if (Creature* target = GetTarget()->ToCreature()) + target->AI()->DoAction(0); + } + + private: + float _posZ; + + void Register() override + { + OnEffectApply += AuraEffectApplyFn(spell_z_check_AuraScript::HandleEffectApply, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL); + OnEffectPeriodic += AuraEffectPeriodicFn(spell_z_check_AuraScript::HandleEffectPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_z_check_AuraScript(); + } +}; + +// 49181 - Warhead Fuse +class spell_warhead_fuse : public SpellScriptLoader +{ +public: + spell_warhead_fuse() : SpellScriptLoader("spell_warhead_fuse") { } + + class spell_warhead_fuse_AuraScript : public AuraScript + { + PrepareAuraScript(spell_warhead_fuse_AuraScript); + + void HandleOnEffectRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (Unit* rocketUnit = GetTarget()->GetVehicleBase()) + if (Creature* rocketCrea = rocketUnit->ToCreature()) + rocketCrea->AI()->DoAction(0); + } + + void Register() override + { + OnEffectRemove += AuraEffectRemoveFn(spell_warhead_fuse_AuraScript::HandleOnEffectRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_warhead_fuse_AuraScript(); + } +}; + void AddSC_grizzly_hills() { new npc_emily(); @@ -866,4 +1121,9 @@ void AddSC_grizzly_hills() new npc_lake_frog(); new spell_shredder_delivery(); new spell_infected_worgen_bite(); + new npc_rocket_propelled_warhead(); + new spell_z_check(); + new spell_warhead_detonate(); + new spell_vehicle_warhead_fuse(); + new spell_warhead_fuse(); } diff --git a/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp b/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp index 3c651e10a1e..14aeda04a7e 100644 --- a/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp +++ b/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp @@ -1301,15 +1301,17 @@ public: EventMaiev Event = EVENT_MAIEV_NULL; for (uint8 i = 1; i <= MaxTimer; ++i) + { if (Timer[i]) { if (Timer[i] <= diff) Event = (EventMaiev)i; else Timer[i] -= diff; } + } - switch (Event) - { + switch (Event) + { case EVENT_MAIEV_STEALTH: { me->SetFullHealth(); @@ -1345,21 +1347,21 @@ public: break; default: break; - } + } - if (HealthBelowPct(50)) - { - me->SetVisible(false); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - if (Creature* illidan = ObjectAccessor::GetCreature(*me, IllidanGUID)) - ENSURE_AI(boss_illidan_stormrage::boss_illidan_stormrageAI, illidan->AI())->DeleteFromThreatList(me->GetGUID()); - me->AttackStop(); - Timer[EVENT_MAIEV_STEALTH] = 60000; // reappear after 1 minute - MaxTimer = 1; - } + if (HealthBelowPct(50)) + { + me->SetVisible(false); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + if (Creature* illidan = ObjectAccessor::GetCreature(*me, IllidanGUID)) + ENSURE_AI(boss_illidan_stormrage::boss_illidan_stormrageAI, illidan->AI())->DeleteFromThreatList(me->GetGUID()); + me->AttackStop(); + Timer[EVENT_MAIEV_STEALTH] = 60000; // reappear after 1 minute + MaxTimer = 1; + } - if (Phase == PHASE_NORMAL_MAIEV) - DoMeleeAttackIfReady(); + if (Phase == PHASE_NORMAL_MAIEV) + DoMeleeAttackIfReady(); } private: diff --git a/src/server/scripts/Outland/CoilfangReservoir/TheSlavePens/boss_ahune.cpp b/src/server/scripts/Outland/CoilfangReservoir/TheSlavePens/boss_ahune.cpp index 9b53b62cdee..5a7a7786c6a 100644 --- a/src/server/scripts/Outland/CoilfangReservoir/TheSlavePens/boss_ahune.cpp +++ b/src/server/scripts/Outland/CoilfangReservoir/TheSlavePens/boss_ahune.cpp @@ -174,7 +174,7 @@ public: void Initialize() { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_REMOVE_CLIENT_CONTROL); } void EnterCombat(Unit* /*who*/) override @@ -308,7 +308,7 @@ public: void Initialize() { me->SetReactState(REACT_PASSIVE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_REMOVE_CLIENT_CONTROL); DoCast(me, SPELL_FROZEN_CORE_GETS_HIT); DoCast(me, SPELL_ICE_SPEAR_AURA); } @@ -341,7 +341,7 @@ public: { _events.Reset(); DoCast(me, SPELL_ICE_SPEAR_AURA); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_DISABLE_MOVE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_REMOVE_CLIENT_CONTROL); } } @@ -542,6 +542,7 @@ public: npc_earthen_ring_flamecallerAI(Creature* creature) : ScriptedAI(creature) { _instance = me->GetInstanceScript(); + _mySpot = 0; } void Reset() override @@ -888,7 +889,7 @@ public: GetCaster()->CastSpell(GetHitUnit(), SPELL_SUMMON_ICE_SPEAR_BUNNY, true); } - void Register() + void Register() override { OnEffectHitTarget += SpellEffectFn(spell_ice_spear_target_picker_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); } diff --git a/src/server/scripts/Outland/CoilfangReservoir/TheSlavePens/instance_the_slave_pens.cpp b/src/server/scripts/Outland/CoilfangReservoir/TheSlavePens/instance_the_slave_pens.cpp index 0d85a8f0d86..0fac7b5a39d 100644 --- a/src/server/scripts/Outland/CoilfangReservoir/TheSlavePens/instance_the_slave_pens.cpp +++ b/src/server/scripts/Outland/CoilfangReservoir/TheSlavePens/instance_the_slave_pens.cpp @@ -81,7 +81,7 @@ public: } } - void SetGuidData(uint32 data, ObjectGuid guid) + void SetGuidData(uint32 data, ObjectGuid guid) override { switch (data) { diff --git a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_nethekurse.cpp b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_nethekurse.cpp index 499550945c6..2592ed3b262 100644 --- a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_nethekurse.cpp +++ b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_nethekurse.cpp @@ -180,24 +180,23 @@ class boss_grand_warlock_nethekurse : public CreatureScript } void MoveInLineOfSight(Unit* who) override - { if (!IntroOnce && me->IsWithinDistInMap(who, 30.0f)) - { + { if (who->GetTypeId() != TYPEID_PLAYER) return; - Talk(SAY_INTRO); - IntroOnce = true; - IsIntroEvent = true; + Talk(SAY_INTRO); + IntroOnce = true; + IsIntroEvent = true; - instance->SetBossState(DATA_NETHEKURSE, IN_PROGRESS); - } + instance->SetBossState(DATA_NETHEKURSE, IN_PROGRESS); + } - if (IsIntroEvent || !IsMainEvent) - return; + if (IsIntroEvent || !IsMainEvent) + return; - ScriptedAI::MoveInLineOfSight(who); + ScriptedAI::MoveInLineOfSight(who); } void EnterCombat(Unit* /*who*/) override diff --git a/src/server/scripts/Outland/TempestKeep/Eye/boss_astromancer.cpp b/src/server/scripts/Outland/TempestKeep/Eye/boss_astromancer.cpp index 9fd1c5c7388..30b3fd67687 100644 --- a/src/server/scripts/Outland/TempestKeep/Eye/boss_astromancer.cpp +++ b/src/server/scripts/Outland/TempestKeep/Eye/boss_astromancer.cpp @@ -325,86 +325,85 @@ class boss_high_astromancer_solarian : public CreatureScript else Phase1_Timer-=diff; } - else - if (Phase == 2) + else if (Phase == 2) + { + //10 seconds after Solarian disappears, 12 mobs spawn out of the three portals. + me->AttackStop(); + me->StopMoving(); + if (Phase2_Timer <= diff) { - //10 seconds after Solarian disappears, 12 mobs spawn out of the three portals. - me->AttackStop(); - me->StopMoving(); - if (Phase2_Timer <= diff) - { - Phase = 3; - for (int i=0; i <= 2; ++i) - for (int j=1; j <= 4; j++) - SummonMinion(NPC_SOLARIUM_AGENT, Portals[i][0], Portals[i][1], Portals[i][2]); + Phase = 3; + for (int i=0; i <= 2; ++i) + for (int j=1; j <= 4; j++) + SummonMinion(NPC_SOLARIUM_AGENT, Portals[i][0], Portals[i][1], Portals[i][2]); - Talk(SAY_SUMMON1); - Phase2_Timer = 10000; - } - else - Phase2_Timer -= diff; + Talk(SAY_SUMMON1); + Phase2_Timer = 10000; } else - if (Phase == 3) - { - me->AttackStop(); - me->StopMoving(); - //Check Phase3_Timer - if (Phase3_Timer <= diff) - { - Phase = 1; - //15 seconds later Solarian reappears out of one of the 3 portals. Simultaneously, 2 healers appear in the two other portals. - int i = rand32() % 3; - me->GetMotionMaster()->Clear(); - me->SetPosition(Portals[i][0], Portals[i][1], Portals[i][2], CENTER_O); - - for (int j=0; j <= 2; j++) - if (j != i) - SummonMinion(NPC_SOLARIUM_PRIEST, Portals[j][0], Portals[j][1], Portals[j][2]); - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetVisible(true); - - Talk(SAY_SUMMON2); - AppearDelay = true; - Phase3_Timer = 15000; - } - else - Phase3_Timer -= diff; - } - else - if (Phase == 4) - { - //Fear_Timer - if (Fear_Timer <= diff) - { - DoCast(me, SPELL_FEAR); - Fear_Timer = 20000; - } - else - Fear_Timer -= diff; - //VoidBolt_Timer - if (VoidBolt_Timer <= diff) - { - DoCastVictim(SPELL_VOID_BOLT); - VoidBolt_Timer = 10000; - } - else - VoidBolt_Timer -= diff; - } - //When Solarian reaches 20% she will transform into a huge void walker. - if (Phase != 4 && me->HealthBelowPct(20)) - { - Phase = 4; - //To make sure she wont be invisible or not selecatble - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetVisible(true); - Talk(SAY_VOIDA); - Talk(SAY_VOIDB); - me->SetArmor(WV_ARMOR); - me->SetDisplayId(MODEL_VOIDWALKER); - me->SetObjectScale(defaultsize*2.5f); - } + Phase2_Timer -= diff; + } + else if (Phase == 3) + { + me->AttackStop(); + me->StopMoving(); + //Check Phase3_Timer + if (Phase3_Timer <= diff) + { + Phase = 1; + //15 seconds later Solarian reappears out of one of the 3 portals. Simultaneously, 2 healers appear in the two other portals. + int i = rand32() % 3; + me->GetMotionMaster()->Clear(); + me->SetPosition(Portals[i][0], Portals[i][1], Portals[i][2], CENTER_O); + + for (int j=0; j <= 2; j++) + if (j != i) + SummonMinion(NPC_SOLARIUM_PRIEST, Portals[j][0], Portals[j][1], Portals[j][2]); + + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetVisible(true); + + Talk(SAY_SUMMON2); + AppearDelay = true; + Phase3_Timer = 15000; + } + else + Phase3_Timer -= diff; + } + else if (Phase == 4) + { + //Fear_Timer + if (Fear_Timer <= diff) + { + DoCast(me, SPELL_FEAR); + Fear_Timer = 20000; + } + else + Fear_Timer -= diff; + //VoidBolt_Timer + if (VoidBolt_Timer <= diff) + { + DoCastVictim(SPELL_VOID_BOLT); + VoidBolt_Timer = 10000; + } + else + VoidBolt_Timer -= diff; + } + + //When Solarian reaches 20% she will transform into a huge void walker. + if (Phase != 4 && me->HealthBelowPct(20)) + { + Phase = 4; + //To make sure she wont be invisible or not selecatble + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetVisible(true); + Talk(SAY_VOIDA); + Talk(SAY_VOIDB); + me->SetArmor(WV_ARMOR); + me->SetDisplayId(MODEL_VOIDWALKER); + me->SetObjectScale(defaultsize*2.5f); + } + DoMeleeAttackIfReady(); } }; diff --git a/src/server/scripts/Spells/spell_dk.cpp b/src/server/scripts/Spells/spell_dk.cpp index 724019a1b19..980c0db19cc 100644 --- a/src/server/scripts/Spells/spell_dk.cpp +++ b/src/server/scripts/Spells/spell_dk.cpp @@ -30,6 +30,13 @@ enum DeathKnightSpells { + SPELL_DK_ACCLIMATION_HOLY = 50490, + SPELL_DK_ACCLIMATION_FIRE = 50362, + SPELL_DK_ACCLIMATION_FROST = 50485, + SPELL_DK_ACCLIMATION_ARCANE = 50486, + SPELL_DK_ACCLIMATION_SHADOW = 50489, + SPELL_DK_ACCLIMATION_NATURE = 50488, + SPELL_DK_ADVANTAGE_T10_4P_MELEE = 70657, SPELL_DK_ANTI_MAGIC_SHELL_TALENT = 51052, SPELL_DK_BLACK_ICE_R1 = 49140, SPELL_DK_BLOOD_BOIL_TRIGGERED = 65658, @@ -51,6 +58,7 @@ enum DeathKnightSpells SPELL_DK_IMPROVED_BLOOD_PRESENCE_R1 = 50365, SPELL_DK_IMPROVED_FROST_PRESENCE_R1 = 50384, SPELL_DK_IMPROVED_UNHOLY_PRESENCE_R1 = 50391, + SPELL_DK_IMPROVED_BLOOD_PRESENCE_HEAL = 50475, SPELL_DK_IMPROVED_BLOOD_PRESENCE_TRIGGERED = 63611, SPELL_DK_IMPROVED_UNHOLY_PRESENCE_TRIGGERED = 63622, SPELL_DK_ITEM_SIGIL_VENGEFUL_HEART = 64962, @@ -78,6 +86,141 @@ enum Misc NPC_DK_GHOUL = 26125 }; +// -49200 - Acclimation +class spell_dk_acclimation : public SpellScriptLoader +{ +public: + spell_dk_acclimation() : SpellScriptLoader("spell_dk_acclimation") { } + + class spell_dk_acclimation_AuraScript : public AuraScript + { + PrepareAuraScript(spell_dk_acclimation_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_DK_ACCLIMATION_HOLY) || + !sSpellMgr->GetSpellInfo(SPELL_DK_ACCLIMATION_FIRE) || + !sSpellMgr->GetSpellInfo(SPELL_DK_ACCLIMATION_FROST) || + !sSpellMgr->GetSpellInfo(SPELL_DK_ACCLIMATION_NATURE) || + !sSpellMgr->GetSpellInfo(SPELL_DK_ACCLIMATION_SHADOW) || + !sSpellMgr->GetSpellInfo(SPELL_DK_ACCLIMATION_ARCANE)) + return false; + return true; + } + + bool CheckProc(ProcEventInfo& eventInfo) + { + if (eventInfo.GetDamageInfo()) + { + switch (GetFirstSchoolInMask(eventInfo.GetDamageInfo()->GetSchoolMask())) + { + case SPELL_SCHOOL_HOLY: + case SPELL_SCHOOL_FIRE: + case SPELL_SCHOOL_NATURE: + case SPELL_SCHOOL_FROST: + case SPELL_SCHOOL_SHADOW: + case SPELL_SCHOOL_ARCANE: + return true; + default: + break; + } + } + + return false; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + uint32 triggerspell = 0; + + switch (GetFirstSchoolInMask(eventInfo.GetDamageInfo()->GetSchoolMask())) + { + case SPELL_SCHOOL_HOLY: + triggerspell = SPELL_DK_ACCLIMATION_HOLY; + break; + case SPELL_SCHOOL_FIRE: + triggerspell = SPELL_DK_ACCLIMATION_FIRE; + break; + case SPELL_SCHOOL_NATURE: + triggerspell = SPELL_DK_ACCLIMATION_NATURE; + break; + case SPELL_SCHOOL_FROST: + triggerspell = SPELL_DK_ACCLIMATION_FROST; + break; + case SPELL_SCHOOL_SHADOW: + triggerspell = SPELL_DK_ACCLIMATION_SHADOW; + break; + case SPELL_SCHOOL_ARCANE: + triggerspell = SPELL_DK_ACCLIMATION_ARCANE; + break; + default: + return; + } + + if (Unit* target = eventInfo.GetActionTarget()) + target->CastSpell(target, triggerspell, true, nullptr, aurEff); + } + + void Register() override + { + DoCheckProc += AuraCheckProcFn(spell_dk_acclimation_AuraScript::CheckProc); + OnEffectProc += AuraEffectProcFn(spell_dk_acclimation_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_dk_acclimation_AuraScript(); + } +}; + +// 70656 - Advantage (T10 4P Melee Bonus) +class spell_dk_advantage_t10_4p : public SpellScriptLoader +{ +public: + spell_dk_advantage_t10_4p() : SpellScriptLoader("spell_dk_advantage_t10_4p") { } + + class spell_dk_advantage_t10_4p_AuraScript : public AuraScript + { + PrepareAuraScript(spell_dk_advantage_t10_4p_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_DK_ADVANTAGE_T10_4P_MELEE)) + return false; + return true; + } + + bool CheckProc(ProcEventInfo& eventInfo) + { + if (Unit* caster = eventInfo.GetActor()) + { + if (caster->GetTypeId() != TYPEID_PLAYER || caster->getClass() != CLASS_DEATH_KNIGHT) + return false; + + for (uint8 i = 0; i < MAX_RUNES; ++i) + if (caster->ToPlayer()->GetRuneCooldown(i) == 0) + return false; + + return true; + } + + return false; + } + + void Register() override + { + DoCheckProc += AuraCheckProcFn(spell_dk_advantage_t10_4p_AuraScript::CheckProc); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_dk_advantage_t10_4p_AuraScript(); + } +}; + // 50462 - Anti-Magic Shell (on raid member) class spell_dk_anti_magic_shell_raid : public SpellScriptLoader { @@ -919,6 +1062,52 @@ class spell_dk_improved_blood_presence : public SpellScriptLoader } }; +// 63611 - Improved Blood Presence Triggered +class spell_dk_improved_blood_presence_triggered : public SpellScriptLoader +{ +public: + spell_dk_improved_blood_presence_triggered() : SpellScriptLoader("spell_dk_improved_blood_presence_triggered") { } + + class spell_dk_improved_blood_presence_triggered_AuraScript : public AuraScript + { + PrepareAuraScript(spell_dk_improved_blood_presence_triggered_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_DK_IMPROVED_BLOOD_PRESENCE_HEAL)) + return false; + return true; + } + + bool CheckProc(ProcEventInfo& eventInfo) + { + if (eventInfo.GetActor()->GetTypeId() == TYPEID_PLAYER) + return true; + + return false; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + if (DamageInfo* dmgInfo = eventInfo.GetDamageInfo()) + eventInfo.GetActor()->CastCustomSpell(SPELL_DK_IMPROVED_BLOOD_PRESENCE_HEAL, SPELLVALUE_BASE_POINT0, CalculatePct(int32(dmgInfo->GetDamage()), aurEff->GetAmount()), + eventInfo.GetActor(), true, nullptr, aurEff); + } + + void Register() override + { + DoCheckProc += AuraCheckProcFn(spell_dk_improved_blood_presence_triggered_AuraScript::CheckProc); + OnEffectProc += AuraEffectProcFn(spell_dk_improved_blood_presence_triggered_AuraScript::HandleProc, EFFECT_1, SPELL_AURA_PROC_TRIGGER_SPELL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_dk_improved_blood_presence_triggered_AuraScript(); + } +}; + // -50384 - Improved Frost Presence class spell_dk_improved_frost_presence : public SpellScriptLoader { @@ -2006,6 +2195,8 @@ public: void AddSC_deathknight_spell_scripts() { + new spell_dk_acclimation(); + new spell_dk_advantage_t10_4p(); new spell_dk_anti_magic_shell_raid(); new spell_dk_anti_magic_shell_self(); new spell_dk_anti_magic_zone(); @@ -2022,6 +2213,7 @@ void AddSC_deathknight_spell_scripts() new spell_dk_ghoul_explode(); new spell_dk_icebound_fortitude(); new spell_dk_improved_blood_presence(); + new spell_dk_improved_blood_presence_triggered(); new spell_dk_improved_frost_presence(); new spell_dk_improved_unholy_presence(); new spell_dk_pestilence(); diff --git a/src/server/scripts/Spells/spell_druid.cpp b/src/server/scripts/Spells/spell_druid.cpp index c088ae07e66..0bf5ab01f45 100644 --- a/src/server/scripts/Spells/spell_druid.cpp +++ b/src/server/scripts/Spells/spell_druid.cpp @@ -31,6 +31,13 @@ enum DruidSpells { SPELL_DRUID_BEAR_FORM_PASSIVE = 1178, SPELL_DRUID_DIRE_BEAR_FORM_PASSIVE = 9635, + SPELL_DRUID_ECLIPSE_LUNAR_PROC = 48518, + SPELL_DRUID_ECLIPSE_SOLAR_PROC = 48517, + SPELL_DRUID_FORMS_TRINKET_BEAR = 37340, + SPELL_DRUID_FORMS_TRINKET_CAT = 37341, + SPELL_DRUID_FORMS_TRINKET_MOONKIN = 37343, + SPELL_DRUID_FORMS_TRINKET_NONE = 37344, + SPELL_DRUID_FORMS_TRINKET_TREE = 37342, SPELL_DRUID_ENRAGE = 5229, SPELL_DRUID_ENRAGE_MOD_DAMAGE = 51185, SPELL_DRUID_ENRAGED_DEFENSE = 70725, @@ -48,6 +55,8 @@ enum DruidSpells SPELL_DRUID_NATURES_SPLENDOR = 57865, SPELL_DRUID_SURVIVAL_INSTINCTS = 50322, SPELL_DRUID_SAVAGE_ROAR = 62071, + SPELL_DRUID_T9_FERAL_RELIC_BEAR = 67354, + SPELL_DRUID_T9_FERAL_RELIC_CAT = 67355, SPELL_DRUID_TIGER_S_FURY_ENERGIZE = 51178 }; @@ -131,6 +140,69 @@ class spell_dru_dash : public SpellScriptLoader } }; +class spell_dru_eclipse : public SpellScriptLoader +{ +public: + spell_dru_eclipse() : SpellScriptLoader("spell_dru_eclipse") { } + + class spell_dru_eclipse_AuraScript : public AuraScript + { + PrepareAuraScript(spell_dru_eclipse_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_DRUID_ECLIPSE_LUNAR_PROC)) + return false; + if (!sSpellMgr->GetSpellInfo(SPELL_DRUID_ECLIPSE_SOLAR_PROC)) + return false; + return true; + } + + bool CheckProc(ProcEventInfo& eventInfo) + { + if (!eventInfo.GetSpellInfo()) + return false; + + if (eventInfo.GetActor()->HasAura(SPELL_DRUID_ECLIPSE_LUNAR_PROC) || eventInfo.GetActor()->HasAura(SPELL_DRUID_ECLIPSE_SOLAR_PROC)) + return false; + + // Triggered by Wrath? + if (eventInfo.GetSpellInfo()->SpellFamilyFlags[0] & 1) + return roll_chance_f(GetSpellInfo()->ProcChance * 0.6f) && _lunarProcCooldownEnd <= std::chrono::steady_clock::now(); + + return _solarProcCooldownEnd <= std::chrono::steady_clock::now(); + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + if (eventInfo.GetSpellInfo()->SpellFamilyFlags[0] & 1) + { + _lunarProcCooldownEnd = std::chrono::steady_clock::now() + Seconds(aurEff->GetAmount()); + eventInfo.GetActor()->CastSpell(eventInfo.GetActor(), SPELL_DRUID_ECLIPSE_LUNAR_PROC, TRIGGERED_FULL_MASK, nullptr, aurEff); + } + else + { + _solarProcCooldownEnd = std::chrono::steady_clock::now() + Seconds(aurEff->GetAmount()); + eventInfo.GetActor()->CastSpell(eventInfo.GetActor(), SPELL_DRUID_ECLIPSE_SOLAR_PROC, TRIGGERED_FULL_MASK, nullptr, aurEff); + } + } + + void Register() override + { + DoCheckProc += AuraCheckProcFn(spell_dru_eclipse_AuraScript::CheckProc); + OnEffectProc += AuraEffectProcFn(spell_dru_eclipse_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_DUMMY); + } + + std::chrono::steady_clock::time_point _lunarProcCooldownEnd = std::chrono::steady_clock::time_point::min(); + std::chrono::steady_clock::time_point _solarProcCooldownEnd = std::chrono::steady_clock::time_point::min(); + }; + + AuraScript* GetAuraScript() const override + { + return new spell_dru_eclipse_AuraScript(); + } +}; + // 5229 - Enrage class spell_dru_enrage : public SpellScriptLoader { @@ -197,6 +269,91 @@ class spell_dru_enrage : public SpellScriptLoader } }; +// 37336 - Druid Forms Trinket +class spell_dru_forms_trinket : public SpellScriptLoader +{ +public: + spell_dru_forms_trinket() : SpellScriptLoader("spell_dru_forms_trinket") { } + + class spell_dru_forms_trinket_AuraScript : public AuraScript + { + PrepareAuraScript(spell_dru_forms_trinket_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_DRUID_FORMS_TRINKET_BEAR) || + !sSpellMgr->GetSpellInfo(SPELL_DRUID_FORMS_TRINKET_CAT) || + !sSpellMgr->GetSpellInfo(SPELL_DRUID_FORMS_TRINKET_MOONKIN) || + !sSpellMgr->GetSpellInfo(SPELL_DRUID_FORMS_TRINKET_NONE) || + !sSpellMgr->GetSpellInfo(SPELL_DRUID_FORMS_TRINKET_TREE)) + return false; + return true; + } + + bool CheckProc(ProcEventInfo& eventInfo) + { + Unit* target = eventInfo.GetActor(); + + switch (target->GetShapeshiftForm()) + { + case FORM_BEAR: + case FORM_DIREBEAR: + case FORM_CAT: + case FORM_MOONKIN: + case FORM_NONE: + case FORM_TREE: + return true; + default: + break; + } + + return false; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + Unit* target = eventInfo.GetActor(); + uint32 triggerspell = 0; + + switch (target->GetShapeshiftForm()) + { + case FORM_BEAR: + case FORM_DIREBEAR: + triggerspell = SPELL_DRUID_FORMS_TRINKET_BEAR; + break; + case FORM_CAT: + triggerspell = SPELL_DRUID_FORMS_TRINKET_CAT; + break; + case FORM_MOONKIN: + triggerspell = SPELL_DRUID_FORMS_TRINKET_MOONKIN; + break; + case FORM_NONE: + triggerspell = SPELL_DRUID_FORMS_TRINKET_NONE; + break; + case FORM_TREE: + triggerspell = SPELL_DRUID_FORMS_TRINKET_TREE; + break; + default: + return; + } + + target->CastSpell(target, triggerspell, true, nullptr, aurEff); + } + + void Register() override + { + DoCheckProc += AuraCheckProcFn(spell_dru_forms_trinket_AuraScript::CheckProc); + OnEffectProc += AuraEffectProcFn(spell_dru_forms_trinket_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_dru_forms_trinket_AuraScript(); + } +}; + // 54846 - Glyph of Starfire class spell_dru_glyph_of_starfire : public SpellScriptLoader { @@ -1079,6 +1236,77 @@ class spell_dru_typhoon : public SpellScriptLoader } }; +// 67353 - T9 Feral Relic (Idol of Mutilation) +class spell_dru_t9_feral_relic : public SpellScriptLoader +{ +public: + spell_dru_t9_feral_relic() : SpellScriptLoader("spell_dru_t9_feral_relic") { } + + class spell_dru_t9_feral_relic_AuraScript : public AuraScript + { + PrepareAuraScript(spell_dru_t9_feral_relic_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_DRUID_T9_FERAL_RELIC_BEAR) || + !sSpellMgr->GetSpellInfo(SPELL_DRUID_T9_FERAL_RELIC_CAT)) + return false; + return true; + } + + bool CheckProc(ProcEventInfo& eventInfo) + { + Unit* target = eventInfo.GetActor(); + + switch (target->GetShapeshiftForm()) + { + case FORM_BEAR: + case FORM_DIREBEAR: + case FORM_CAT: + return true; + default: + break; + } + + return false; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + uint32 triggerspell = 0; + + Unit* target = eventInfo.GetActor(); + + switch (target->GetShapeshiftForm()) + { + case FORM_BEAR: + case FORM_DIREBEAR: + triggerspell = SPELL_DRUID_T9_FERAL_RELIC_BEAR; + break; + case FORM_CAT: + triggerspell = SPELL_DRUID_T9_FERAL_RELIC_CAT; + break; + default: + return; + } + + target->CastSpell(target, triggerspell, true, nullptr, aurEff); + } + + void Register() override + { + DoCheckProc += AuraCheckProcFn(spell_dru_t9_feral_relic_AuraScript::CheckProc); + OnEffectProc += AuraEffectProcFn(spell_dru_t9_feral_relic_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_dru_t9_feral_relic_AuraScript(); + } +}; + // 70691 - Item T10 Restoration 4P Bonus class spell_dru_t10_restoration_4p_bonus : public SpellScriptLoader { @@ -1208,7 +1436,9 @@ void AddSC_druid_spell_scripts() { new spell_dru_bear_form_passive(); new spell_dru_dash(); + new spell_dru_eclipse(); new spell_dru_enrage(); + new spell_dru_forms_trinket(); new spell_dru_glyph_of_starfire(); new spell_dru_idol_lifebloom(); new spell_dru_innervate(); @@ -1230,6 +1460,7 @@ void AddSC_druid_spell_scripts() new spell_dru_flight_form(); new spell_dru_tiger_s_fury(); new spell_dru_typhoon(); + new spell_dru_t9_feral_relic(); new spell_dru_t10_restoration_4p_bonus(); new spell_dru_wild_growth(); } diff --git a/src/server/scripts/Spells/spell_generic.cpp b/src/server/scripts/Spells/spell_generic.cpp index 8b8c5300a9e..e8ad73ceadb 100644 --- a/src/server/scripts/Spells/spell_generic.cpp +++ b/src/server/scripts/Spells/spell_generic.cpp @@ -430,6 +430,61 @@ class spell_gen_bandage : public SpellScriptLoader } }; +// Blood Reserve - 64568 +enum BloodReserve +{ + SPELL_GEN_BLOOD_RESERVE_AURA = 64568, + SPELL_GEN_BLOOD_RESERVE_HEAL = 64569 +}; + +class spell_gen_blood_reserve : public SpellScriptLoader +{ + public: + spell_gen_blood_reserve() : SpellScriptLoader("spell_gen_blood_reserve") { } + + class spell_gen_blood_reserve_AuraScript : public AuraScript + { + PrepareAuraScript(spell_gen_blood_reserve_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_GEN_BLOOD_RESERVE_HEAL)) + return false; + return true; + } + + bool CheckProc(ProcEventInfo& eventInfo) + { + if (DamageInfo* dmgInfo = eventInfo.GetDamageInfo()) + if (Unit* caster = eventInfo.GetActionTarget()) + if (caster->HealthBelowPctDamaged(35, dmgInfo->GetDamage())) + return true; + + return false; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + + Unit* caster = eventInfo.GetActionTarget(); + caster->CastCustomSpell(SPELL_GEN_BLOOD_RESERVE_HEAL, SPELLVALUE_BASE_POINT0, aurEff->GetAmount(), caster, TRIGGERED_FULL_MASK, nullptr, aurEff); + caster->RemoveAura(SPELL_GEN_BLOOD_RESERVE_AURA); + } + + void Register() override + { + DoCheckProc += AuraCheckProcFn(spell_gen_blood_reserve_AuraScript::CheckProc); + OnEffectProc += AuraEffectProcFn(spell_gen_blood_reserve_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_gen_blood_reserve_AuraScript(); + } +}; + enum Bonked { SPELL_BONKED = 62991, @@ -2085,7 +2140,7 @@ class spell_gen_mounted_charge: public SpellScriptLoader } // If target isn't a training dummy there's a chance of failing the charge - if (!target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE) && roll_chance_f(12.5f)) + if (!target->IsCharmedOwnedByPlayerOrPlayer() && roll_chance_f(12.5f)) spellId = SPELL_CHARGE_MISS_EFFECT; if (Unit* vehicle = GetCaster()->GetVehicleBase()) @@ -4199,6 +4254,7 @@ void AddSC_generic_spell_scripts() new spell_gen_aura_service_uniform(); new spell_gen_av_drekthar_presence(); new spell_gen_bandage(); + new spell_gen_blood_reserve(); new spell_gen_bonked(); new spell_gen_break_shield("spell_gen_break_shield"); new spell_gen_break_shield("spell_gen_tournament_counterattack"); diff --git a/src/server/scripts/Spells/spell_hunter.cpp b/src/server/scripts/Spells/spell_hunter.cpp index 82d9d134445..0e952818a2f 100644 --- a/src/server/scripts/Spells/spell_hunter.cpp +++ b/src/server/scripts/Spells/spell_hunter.cpp @@ -51,9 +51,11 @@ enum HunterSpells SPELL_HUNTER_PET_HEART_OF_THE_PHOENIX_TRIGGERED = 54114, SPELL_HUNTER_PET_HEART_OF_THE_PHOENIX_DEBUFF = 55711, SPELL_HUNTER_PET_CARRION_FEEDER_TRIGGERED = 54045, + SPELL_HUNTER_PIERCING_SHOTS = 63468, SPELL_HUNTER_READINESS = 23989, SPELL_HUNTER_SNIPER_TRAINING_R1 = 53302, SPELL_HUNTER_SNIPER_TRAINING_BUFF_R1 = 64418, + SPELL_HUNTER_T9_4P_GREATNESS = 68130, SPELL_HUNTER_VICIOUS_VIPER = 61609, SPELL_HUNTER_VIPER_ATTACK_SPEED = 60144, SPELL_DRAENEI_GIFT_OF_THE_NAARU = 59543 @@ -704,6 +706,63 @@ class spell_hun_pet_heart_of_the_phoenix : public SpellScriptLoader } }; +// -53234 - Piercing Shots +class spell_hun_piercing_shots : public SpellScriptLoader +{ +public: + spell_hun_piercing_shots() : SpellScriptLoader("spell_hun_piercing_shots") { } + + class spell_hun_piercing_shots_AuraScript : public AuraScript + { + PrepareAuraScript(spell_hun_piercing_shots_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_HUNTER_PIERCING_SHOTS)) + return false; + return true; + } + + bool CheckProc(ProcEventInfo& eventInfo) + { + if (eventInfo.GetActionTarget()) + return true; + return false; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + Unit* caster = eventInfo.GetActor(); + Unit* target = eventInfo.GetActionTarget(); + + if (DamageInfo* dmgInfo = eventInfo.GetDamageInfo()) + { + SpellInfo const* piercingShots = sSpellMgr->AssertSpellInfo(SPELL_HUNTER_PIERCING_SHOTS); + int32 duration = piercingShots->GetMaxDuration(); + uint32 amplitude = piercingShots->Effects[EFFECT_0].Amplitude; + uint32 dmg = dmgInfo->GetDamage(); + + uint32 bp = CalculatePct(int32(dmg), aurEff->GetAmount()) / (duration / int32(amplitude)); + bp += target->GetRemainingPeriodicAmount(target->GetGUID(), SPELL_HUNTER_PIERCING_SHOTS, SPELL_AURA_PERIODIC_DAMAGE); + + caster->CastCustomSpell(SPELL_HUNTER_PIERCING_SHOTS, SPELLVALUE_BASE_POINT0, bp, target, true, nullptr, aurEff); + } + } + + void Register() override + { + DoCheckProc += AuraCheckProcFn(spell_hun_piercing_shots_AuraScript::CheckProc); + OnEffectProc += AuraEffectProcFn(spell_hun_piercing_shots_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_hun_piercing_shots_AuraScript(); + } +}; + // 56654, 58882 - Rapid Recuperation class spell_hun_rapid_recuperation : public SpellScriptLoader { @@ -967,6 +1026,51 @@ class spell_hun_target_only_pet_and_owner : public SpellScriptLoader } }; +// 67151 - T9 4P Bonus +class spell_hun_t9_4p_bonus : public SpellScriptLoader +{ +public: + spell_hun_t9_4p_bonus() : SpellScriptLoader("spell_hun_t9_4p_bonus") { } + + class spell_hun_t9_4p_bonus_AuraScript : public AuraScript + { + PrepareAuraScript(spell_hun_t9_4p_bonus_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_HUNTER_T9_4P_GREATNESS)) + return false; + return true; + } + + bool CheckProc(ProcEventInfo& eventInfo) + { + if (eventInfo.GetActor()->GetTypeId() == TYPEID_PLAYER && eventInfo.GetActor()->ToPlayer()->GetPet()) + return true; + return false; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + Unit* caster = eventInfo.GetActor(); + + caster->CastSpell(caster->ToPlayer()->GetPet(), SPELL_HUNTER_T9_4P_GREATNESS, true, nullptr, aurEff); + } + + void Register() override + { + DoCheckProc += AuraCheckProcFn(spell_hun_t9_4p_bonus_AuraScript::CheckProc); + OnEffectProc += AuraEffectProcFn(spell_hun_t9_4p_bonus_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_hun_t9_4p_bonus_AuraScript(); + } +}; + // 60144 - Viper Attack Speed class spell_hun_viper_attack_speed : public SpellScriptLoader { @@ -1025,11 +1129,13 @@ void AddSC_hunter_spell_scripts() new spell_hun_misdirection_proc(); new spell_hun_pet_carrion_feeder(); new spell_hun_pet_heart_of_the_phoenix(); + new spell_hun_piercing_shots(); new spell_hun_rapid_recuperation(); new spell_hun_readiness(); new spell_hun_scatter_shot(); new spell_hun_sniper_training(); new spell_hun_tame_beast(); new spell_hun_target_only_pet_and_owner(); + new spell_hun_t9_4p_bonus(); new spell_hun_viper_attack_speed(); } diff --git a/src/server/scripts/Spells/spell_item.cpp b/src/server/scripts/Spells/spell_item.cpp index 0abff255e4b..f7c2cefa202 100644 --- a/src/server/scripts/Spells/spell_item.cpp +++ b/src/server/scripts/Spells/spell_item.cpp @@ -201,6 +201,55 @@ class spell_item_blessing_of_ancient_kings : public SpellScriptLoader } }; +// 47770 - Roll Dice +class spell_item_decahedral_dwarven_dice : public SpellScriptLoader +{ + public: + spell_item_decahedral_dwarven_dice() : SpellScriptLoader("spell_item_decahedral_dwarven_dice") { } + + class spell_item_decahedral_dwarven_dice_SpellScript : public SpellScript + { + PrepareSpellScript(spell_item_decahedral_dwarven_dice_SpellScript); + + enum + { + TEXT_DECAHEDRAL_DWARVEN_DICE = 26147 + }; + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sObjectMgr->GetBroadcastText(TEXT_DECAHEDRAL_DWARVEN_DICE)) + return false; + return true; + } + + bool Load() override + { + return GetCaster()->GetTypeId() == TYPEID_PLAYER; + } + + void HandleScript(SpellEffIndex /*effIndex*/) + { + GetCaster()->TextEmote(TEXT_DECAHEDRAL_DWARVEN_DICE, GetHitUnit()); + + static uint32 const minimum = 1; + static uint32 const maximum = 100; + + GetCaster()->ToPlayer()->DoRandomRoll(minimum, maximum); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_item_decahedral_dwarven_dice_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_item_decahedral_dwarven_dice_SpellScript(); + } +}; + // 8342 - Defibrillate (Goblin Jumper Cables) have 33% chance on success // 22999 - Defibrillate (Goblin Jumper Cables XL) have 50% chance on success // 54732 - Defibrillate (Gnomish Army Knife) have 67% chance on success @@ -1319,6 +1368,57 @@ class spell_item_underbelly_elixir : public SpellScriptLoader } }; +// 47776 - Roll 'dem Bones +class spell_item_worn_troll_dice : public SpellScriptLoader +{ + public: + spell_item_worn_troll_dice() : SpellScriptLoader("spell_item_worn_troll_dice") { } + + class spell_item_worn_troll_dice_SpellScript : public SpellScript + { + PrepareSpellScript(spell_item_worn_troll_dice_SpellScript); + + enum + { + TEXT_WORN_TROLL_DICE = 26152 + }; + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sObjectMgr->GetBroadcastText(TEXT_WORN_TROLL_DICE)) + return false; + return true; + } + + bool Load() override + { + return GetCaster()->GetTypeId() == TYPEID_PLAYER; + } + + void HandleScript(SpellEffIndex /*effIndex*/) + { + GetCaster()->TextEmote(TEXT_WORN_TROLL_DICE, GetHitUnit()); + + static uint32 const minimum = 1; + static uint32 const maximum = 6; + + // roll twice + GetCaster()->ToPlayer()->DoRandomRoll(minimum, maximum); + GetCaster()->ToPlayer()->DoRandomRoll(minimum, maximum); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_item_worn_troll_dice_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_item_worn_troll_dice_SpellScript(); + } +}; + enum AirRifleSpells { SPELL_AIR_RIFLE_HOLD_VISUAL = 65582, @@ -2631,6 +2731,70 @@ public: } }; +enum SoulPreserver +{ + SPELL_SOUL_PRESERVER_DRUID = 60512, + SPELL_SOUL_PRESERVER_PALADIN = 60513, + SPELL_SOUL_PRESERVER_PRIEST = 60514, + SPELL_SOUL_PRESERVER_SHAMAN = 60515, +}; + +class spell_item_soul_preserver : public SpellScriptLoader +{ +public: + spell_item_soul_preserver() : SpellScriptLoader("spell_item_soul_preserver") { } + + class spell_item_soul_preserver_AuraScript : public AuraScript + { + PrepareAuraScript(spell_item_soul_preserver_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_SOUL_PRESERVER_DRUID) || + !sSpellMgr->GetSpellInfo(SPELL_SOUL_PRESERVER_PALADIN) || + !sSpellMgr->GetSpellInfo(SPELL_SOUL_PRESERVER_PRIEST) || + !sSpellMgr->GetSpellInfo(SPELL_SOUL_PRESERVER_SHAMAN)) + return false; + return true; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + + Unit* caster = eventInfo.GetActor(); + + switch (caster->getClass()) + { + case CLASS_DRUID: + caster->CastSpell(caster, SPELL_SOUL_PRESERVER_DRUID, true, nullptr, aurEff); + break; + case CLASS_PALADIN: + caster->CastSpell(caster, SPELL_SOUL_PRESERVER_PALADIN, true, nullptr, aurEff); + break; + case CLASS_PRIEST: + caster->CastSpell(caster, SPELL_SOUL_PRESERVER_PRIEST, true, nullptr, aurEff); + break; + case CLASS_SHAMAN: + caster->CastSpell(caster, SPELL_SOUL_PRESERVER_SHAMAN, true, nullptr, aurEff); + break; + default: + break; + } + } + + void Register() override + { + OnEffectProc += AuraEffectProcFn(spell_item_soul_preserver_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_item_soul_preserver_AuraScript(); + } +}; + class spell_item_toy_train_set_pulse : public SpellScriptLoader { public: @@ -2668,6 +2832,336 @@ public: } }; +enum DeathChoiceSpells +{ + SPELL_DEATH_CHOICE_NORMAL_AURA = 67702, + SPELL_DEATH_CHOICE_NORMAL_AGILITY = 67703, + SPELL_DEATH_CHOICE_NORMAL_STRENGTH = 67708, + SPELL_DEATH_CHOICE_HEROIC_AURA = 67771, + SPELL_DEATH_CHOICE_HEROIC_AGILITY = 67772, + SPELL_DEATH_CHOICE_HEROIC_STRENGTH = 67773 +}; + +class spell_item_death_choice : public SpellScriptLoader +{ +public: + spell_item_death_choice() : SpellScriptLoader("spell_item_death_choice") { } + + class spell_item_death_choice_AuraScript : public AuraScript + { + PrepareAuraScript(spell_item_death_choice_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_DEATH_CHOICE_NORMAL_STRENGTH) || + !sSpellMgr->GetSpellInfo(SPELL_DEATH_CHOICE_NORMAL_AGILITY) || + !sSpellMgr->GetSpellInfo(SPELL_DEATH_CHOICE_HEROIC_STRENGTH) || + !sSpellMgr->GetSpellInfo(SPELL_DEATH_CHOICE_HEROIC_AGILITY)) + return false; + return true; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + + Unit* caster = eventInfo.GetActor(); + float str = caster->GetStat(STAT_STRENGTH); + float agi = caster->GetStat(STAT_AGILITY); + + switch (aurEff->GetId()) + { + case SPELL_DEATH_CHOICE_NORMAL_AURA: + { + if (str > agi) + caster->CastSpell(caster, SPELL_DEATH_CHOICE_NORMAL_STRENGTH, true, nullptr, aurEff); + else + caster->CastSpell(caster, SPELL_DEATH_CHOICE_NORMAL_AGILITY, true, nullptr, aurEff); + break; + } + case SPELL_DEATH_CHOICE_HEROIC_AURA: + { + if (str > agi) + caster->CastSpell(caster, SPELL_DEATH_CHOICE_HEROIC_STRENGTH, true, nullptr, aurEff); + else + caster->CastSpell(caster, SPELL_DEATH_CHOICE_HEROIC_AGILITY, true, nullptr, aurEff); + break; + } + default: + break; + } + } + + void Register() override + { + OnEffectProc += AuraEffectProcFn(spell_item_death_choice_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_item_death_choice_AuraScript(); + } +}; + +enum TrinketStackSpells +{ + SPELL_LIGHTNING_CAPACITOR_AURA = 37657, // Lightning Capacitor + SPELL_LIGHTNING_CAPACITOR_STACK = 37658, + SPELL_LIGHTNING_CAPACITOR_TRIGGER = 37661, + SPELL_THUNDER_CAPACITOR_AURA = 54841, // Thunder Capacitor + SPELL_THUNDER_CAPACITOR_STACK = 54842, + SPELL_THUNDER_CAPACITOR_TRIGGER = 54843, + SPELL_TOC25_CASTER_TRINKET_NORMAL_AURA = 67712, // Item - Coliseum 25 Normal Caster Trinket + SPELL_TOC25_CASTER_TRINKET_NORMAL_STACK = 67713, + SPELL_TOC25_CASTER_TRINKET_NORMAL_TRIGGER = 67714, + SPELL_TOC25_CASTER_TRINKET_HEROIC_AURA = 67758, // Item - Coliseum 25 Heroic Caster Trinket + SPELL_TOC25_CASTER_TRINKET_HEROIC_STACK = 67759, + SPELL_TOC25_CASTER_TRINKET_HEROIC_TRIGGER = 67760, +}; + +class spell_item_trinket_stack : public SpellScriptLoader +{ +public: + spell_item_trinket_stack(char const* scriptName, uint32 stackSpell, uint32 triggerSpell) : SpellScriptLoader(scriptName), + _stackSpell(stackSpell), _triggerSpell(triggerSpell) + { + } + + class spell_item_trinket_stack_AuraScript : public AuraScript + { + PrepareAuraScript(spell_item_trinket_stack_AuraScript); + + public: + spell_item_trinket_stack_AuraScript(uint32 stackSpell, uint32 triggerSpell) : _stackSpell(stackSpell), _triggerSpell(triggerSpell) + { + } + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(_stackSpell) || !sSpellMgr->GetSpellInfo(_triggerSpell)) + return false; + return true; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + + Unit* caster = eventInfo.GetActor(); + + caster->CastSpell(caster, _stackSpell, true, nullptr, aurEff); // cast the stack + + Aura* dummy = caster->GetAura(_stackSpell); // retrieve aura + + //dont do anything if it's not the right amount of stacks; + if (!dummy || dummy->GetStackAmount() < aurEff->GetAmount()) + return; + + // if right amount, remove the aura and cast real trigger + caster->RemoveAurasDueToSpell(_stackSpell); + if (Unit* target = eventInfo.GetActionTarget()) + caster->CastSpell(target, _triggerSpell, true, nullptr, aurEff); + } + + void Register() override + { + OnEffectProc += AuraEffectProcFn(spell_item_trinket_stack_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL); + } + + private: + uint32 _stackSpell; + uint32 _triggerSpell; + }; + + AuraScript* GetAuraScript() const override + { + return new spell_item_trinket_stack_AuraScript(_stackSpell, _triggerSpell); + } + +private: + uint32 _stackSpell; + uint32 _triggerSpell; +}; + +// 57345 - Darkmoon Card: Greatness +enum DarkmoonCardSpells +{ + SPELL_DARKMOON_CARD_STRENGHT = 60229, + SPELL_DARKMOON_CARD_AGILITY = 60233, + SPELL_DARKMOON_CARD_INTELLECT = 60234, + SPELL_DARKMOON_CARD_SPIRIT = 60235, +}; + +class spell_item_darkmoon_card_greatness : public SpellScriptLoader +{ +public: + spell_item_darkmoon_card_greatness() : SpellScriptLoader("spell_item_darkmoon_card_greatness") { } + + class spell_item_darkmoon_card_greatness_AuraScript : public AuraScript + { + PrepareAuraScript(spell_item_darkmoon_card_greatness_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_DARKMOON_CARD_STRENGHT) || + !sSpellMgr->GetSpellInfo(SPELL_DARKMOON_CARD_AGILITY) || + !sSpellMgr->GetSpellInfo(SPELL_DARKMOON_CARD_INTELLECT) || + !sSpellMgr->GetSpellInfo(SPELL_DARKMOON_CARD_SPIRIT)) + return false; + return true; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + + Unit* caster = eventInfo.GetActor(); + float str = caster->GetStat(STAT_STRENGTH); + float agi = caster->GetStat(STAT_AGILITY); + float intl = caster->GetStat(STAT_INTELLECT); + float spi = caster->GetStat(STAT_SPIRIT); + float stat = 0.0f; + + uint32 spellTrigger = SPELL_DARKMOON_CARD_STRENGHT; + + if (str > stat) + { + spellTrigger = SPELL_DARKMOON_CARD_STRENGHT; + stat = str; + } + + if (agi > stat) + { + spellTrigger = SPELL_DARKMOON_CARD_AGILITY; + stat = agi; + } + + if (intl > stat) + { + spellTrigger = SPELL_DARKMOON_CARD_INTELLECT; + stat = intl; + } + + if (spi > stat) + { + spellTrigger = SPELL_DARKMOON_CARD_SPIRIT; + stat = spi; + } + + caster->CastSpell(caster, spellTrigger, true, nullptr, aurEff); + } + + void Register() override + { + OnEffectProc += AuraEffectProcFn(spell_item_darkmoon_card_greatness_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_item_darkmoon_card_greatness_AuraScript(); + } +}; + +// 43820 - Amani Charm of the Witch Doctor +enum CharmWitchDoctor +{ + SPELL_CHARM_WITCH_DOCTOR_PROC = 43821 +}; + +class spell_item_charm_witch_doctor : public SpellScriptLoader +{ +public: + spell_item_charm_witch_doctor() : SpellScriptLoader("spell_item_charm_witch_doctor") { } + + class spell_item_charm_witch_doctor_AuraScript : public AuraScript + { + PrepareAuraScript(spell_item_charm_witch_doctor_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_CHARM_WITCH_DOCTOR_PROC)) + return false; + return true; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + + Unit* caster = eventInfo.GetActor(); + Unit* target = eventInfo.GetActionTarget(); + + if (target) + { + int32 bp = CalculatePct(target->GetCreateHealth(),aurEff->GetSpellInfo()->Effects[1].CalcValue()); + caster->CastCustomSpell(target, SPELL_CHARM_WITCH_DOCTOR_PROC, &bp, nullptr, nullptr, true, nullptr, aurEff); + } + } + + void Register() override + { + OnEffectProc += AuraEffectProcFn(spell_item_charm_witch_doctor_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_item_charm_witch_doctor_AuraScript(); + } +}; + +// 27522,40336 - Mana Drain +enum ManaDrainSpells +{ + SPELL_MANA_DRAIN_ENERGIZE = 29471, + SPELL_MANA_DRAIN_LEECH = 27526 +}; + +class spell_item_mana_drain : public SpellScriptLoader +{ +public: + spell_item_mana_drain() : SpellScriptLoader("spell_item_mana_drain") { } + + class spell_item_mana_drain_AuraScript : public AuraScript + { + PrepareAuraScript(spell_item_mana_drain_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_MANA_DRAIN_ENERGIZE) + || !sSpellMgr->GetSpellInfo(SPELL_MANA_DRAIN_LEECH)) + return false; + return true; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + + Unit* caster = eventInfo.GetActor(); + Unit* target = eventInfo.GetActionTarget(); + + if (caster->IsAlive()) + caster->CastSpell(caster, SPELL_MANA_DRAIN_ENERGIZE, true, nullptr, aurEff); + + if (target && target->IsAlive()) + caster->CastSpell(target, SPELL_MANA_DRAIN_LEECH, true, nullptr, aurEff); + } + + void Register() override + { + OnEffectProc += AuraEffectProcFn(spell_item_mana_drain_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_item_mana_drain_AuraScript(); + } +}; + void AddSC_item_spell_scripts() { // 23074 Arcanite Dragonling @@ -2682,6 +3176,7 @@ void AddSC_item_spell_scripts() new spell_item_aegis_of_preservation(); new spell_item_arcane_shroud(); new spell_item_blessing_of_ancient_kings(); + new spell_item_decahedral_dwarven_dice(); new spell_item_defibrillate("spell_item_goblin_jumper_cables", 67, SPELL_GOBLIN_JUMPER_CABLES_FAIL); new spell_item_defibrillate("spell_item_goblin_jumper_cables_xl", 50, SPELL_GOBLIN_JUMPER_CABLES_XL_FAIL); new spell_item_defibrillate("spell_item_gnomish_army_knife", 33); @@ -2706,6 +3201,7 @@ void AddSC_item_spell_scripts() new spell_item_six_demon_bag(); new spell_item_the_eye_of_diminution(); new spell_item_underbelly_elixir(); + new spell_item_worn_troll_dice(); new spell_item_red_rider_air_rifle(); new spell_item_create_heart_candy(); @@ -2736,5 +3232,14 @@ void AddSC_item_spell_scripts() new spell_item_chicken_cover(); new spell_item_muisek_vessel(); new spell_item_greatmothers_soulcatcher(); + new spell_item_soul_preserver(); new spell_item_toy_train_set_pulse(); + new spell_item_death_choice(); + new spell_item_trinket_stack("spell_item_lightning_capacitor", SPELL_LIGHTNING_CAPACITOR_STACK, SPELL_LIGHTNING_CAPACITOR_TRIGGER); + new spell_item_trinket_stack("spell_item_thunder_capacitor", SPELL_THUNDER_CAPACITOR_STACK, SPELL_THUNDER_CAPACITOR_TRIGGER); + new spell_item_trinket_stack("spell_item_toc25_normal_caster_trinket", SPELL_TOC25_CASTER_TRINKET_NORMAL_STACK, SPELL_TOC25_CASTER_TRINKET_NORMAL_TRIGGER); + new spell_item_trinket_stack("spell_item_toc25_heroic_caster_trinket", SPELL_TOC25_CASTER_TRINKET_HEROIC_STACK, SPELL_TOC25_CASTER_TRINKET_HEROIC_TRIGGER); + new spell_item_darkmoon_card_greatness(); + new spell_item_charm_witch_doctor(); + new spell_item_mana_drain(); } diff --git a/src/server/scripts/Spells/spell_mage.cpp b/src/server/scripts/Spells/spell_mage.cpp index 2f4e4fa6f44..bacbe31630c 100644 --- a/src/server/scripts/Spells/spell_mage.cpp +++ b/src/server/scripts/Spells/spell_mage.cpp @@ -29,6 +29,7 @@ enum MageSpells { + SPELL_MAGE_BLAZING_SPEED = 31643, SPELL_MAGE_BURNOUT = 29077, SPELL_MAGE_COLD_SNAP = 11958, SPELL_MAGE_FOCUS_MAGIC_PROC = 54648, @@ -116,6 +117,42 @@ class spell_mage_blast_wave : public SpellScriptLoader } }; +// -31641 - Blazing Speed +class spell_mage_blazing_speed : public SpellScriptLoader +{ +public: + spell_mage_blazing_speed() : SpellScriptLoader("spell_mage_blazing_speed") { } + + class spell_mage_blazing_speed_AuraScript : public AuraScript + { + PrepareAuraScript(spell_mage_blazing_speed_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_MAGE_BLAZING_SPEED)) + return false; + return true; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + if (Unit* target = eventInfo.GetActionTarget()) + target->CastSpell(target, SPELL_MAGE_BLAZING_SPEED, true, nullptr, aurEff); + } + + void Register() override + { + OnEffectProc += AuraEffectProcFn(spell_mage_blazing_speed_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_mage_blazing_speed_AuraScript(); + } +}; + // -44449 - Burnout class spell_mage_burnout : public SpellScriptLoader { @@ -647,6 +684,7 @@ class spell_mage_summon_water_elemental : public SpellScriptLoader void AddSC_mage_spell_scripts() { new spell_mage_blast_wave(); + new spell_mage_blazing_speed(); new spell_mage_burnout(); new spell_mage_cold_snap(); new spell_mage_fire_frost_ward(); diff --git a/src/server/scripts/Spells/spell_paladin.cpp b/src/server/scripts/Spells/spell_paladin.cpp index d9fd36f5fd4..eed84d4ff6b 100644 --- a/src/server/scripts/Spells/spell_paladin.cpp +++ b/src/server/scripts/Spells/spell_paladin.cpp @@ -37,6 +37,7 @@ enum PaladinSpells SPELL_PALADIN_HOLY_SHOCK_R1 = 20473, SPELL_PALADIN_HOLY_SHOCK_R1_DAMAGE = 25912, SPELL_PALADIN_HOLY_SHOCK_R1_HEALING = 25914, + SPELL_PALADIN_ILLUMINATION_ENERGIZE = 20272, SPELL_PALADIN_BLESSING_OF_LOWER_CITY_DRUID = 37878, SPELL_PALADIN_BLESSING_OF_LOWER_CITY_PALADIN = 37879, @@ -871,6 +872,61 @@ class spell_pal_holy_shock : public SpellScriptLoader } }; +// -20210 - Illumination +class spell_pal_illumination : public SpellScriptLoader +{ +public: + spell_pal_illumination() : SpellScriptLoader("spell_pal_illumination") { } + + class spell_pal_illumination_AuraScript : public AuraScript + { + PrepareAuraScript(spell_pal_illumination_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_PALADIN_HOLY_SHOCK_R1_HEALING) || + !sSpellMgr->GetSpellInfo(SPELL_PALADIN_ILLUMINATION_ENERGIZE) || + !sSpellMgr->GetSpellInfo(SPELL_PALADIN_HOLY_SHOCK_R1)) + return false; + return true; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + + // this script is valid only for the Holy Shock procs of illumination + if (eventInfo.GetHealInfo() && eventInfo.GetHealInfo()->GetSpellInfo()) + { + if (eventInfo.GetHealInfo()->GetSpellInfo()->SpellFamilyFlags[1] & 0x00010000) + { + PreventDefaultAction(); + Unit* target = eventInfo.GetActor(); // Paladin is the target of the energize + + // proc comes from the Holy Shock heal, need to get mana cost of original spell + uint32 originalspellid = sSpellMgr->GetSpellWithRank(SPELL_PALADIN_HOLY_SHOCK_R1, eventInfo.GetHealInfo()->GetSpellInfo()->GetRank()); + SpellInfo const* originalSpell = sSpellMgr->GetSpellInfo(originalspellid); + if (originalSpell && aurEff->GetSpellInfo()) + { + uint32 bp = CalculatePct(originalSpell->CalcPowerCost(target, originalSpell->GetSchoolMask()), aurEff->GetSpellInfo()->Effects[EFFECT_1].CalcValue()); + target->CastCustomSpell(SPELL_PALADIN_ILLUMINATION_ENERGIZE, SPELLVALUE_BASE_POINT0, bp, target, true, nullptr, aurEff); + } + } + } + } + + void Register() override + { + OnEffectProc += AuraEffectProcFn(spell_pal_illumination_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_pal_illumination_AuraScript(); + } +}; + // Maybe this is incorrect // These spells should always be cast on login, regardless of whether the player has the talent or not @@ -1393,6 +1449,7 @@ void AddSC_paladin_spell_scripts() new spell_pal_hand_of_sacrifice(); new spell_pal_hand_of_salvation(); new spell_pal_holy_shock(); + new spell_pal_illumination(); new spell_pal_improved_aura("spell_pal_improved_concentraction_aura", SPELL_PALADIN_IMPROVED_CONCENTRACTION_AURA); new spell_pal_improved_aura("spell_pal_improved_devotion_aura", SPELL_PALADIN_IMPROVED_DEVOTION_AURA); new spell_pal_improved_aura("spell_pal_sanctified_retribution", SPELL_PALADIN_SANCTIFIED_RETRIBUTION_AURA); diff --git a/src/server/scripts/Spells/spell_priest.cpp b/src/server/scripts/Spells/spell_priest.cpp index 51f03346df1..9e2d265aa9c 100644 --- a/src/server/scripts/Spells/spell_priest.cpp +++ b/src/server/scripts/Spells/spell_priest.cpp @@ -29,6 +29,7 @@ enum PriestSpells { + SPELL_PRIEST_BLESSED_RECOVERY_R1 = 27813, SPELL_PRIEST_DIVINE_AEGIS = 47753, SPELL_PRIEST_EMPOWERED_RENEW = 63544, SPELL_PRIEST_GLYPH_OF_CIRCLE_OF_HEALING = 55675, @@ -88,6 +89,50 @@ class RaidCheck Unit const* _caster; }; +// -27811 - Blessed Recovery +class spell_pri_blessed_recovery : public SpellScriptLoader +{ +public: + spell_pri_blessed_recovery() : SpellScriptLoader("spell_pri_blessed_recovery") { } + + class spell_pri_blessed_recovery_AuraScript : public AuraScript + { + PrepareAuraScript(spell_pri_blessed_recovery_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_PRIEST_BLESSED_RECOVERY_R1)) + return false; + return true; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + if (DamageInfo* dmgInfo = eventInfo.GetDamageInfo()) + { + if (Unit* target = eventInfo.GetActionTarget()) + { + uint32 triggerSpell = sSpellMgr->GetSpellWithRank(SPELL_PRIEST_BLESSED_RECOVERY_R1, aurEff->GetSpellInfo()->GetRank()); + uint32 bp = CalculatePct(int32(dmgInfo->GetDamage()), aurEff->GetAmount()) / 3; + bp += target->GetRemainingPeriodicAmount(target->GetGUID(), triggerSpell, SPELL_AURA_PERIODIC_HEAL); + target->CastCustomSpell(triggerSpell, SPELLVALUE_BASE_POINT0, bp, target, true, nullptr, aurEff); + } + } + } + + void Register() override + { + OnEffectProc += AuraEffectProcFn(spell_pri_blessed_recovery_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_pri_blessed_recovery_AuraScript(); + } +}; + // -34861 - Circle of Healing class spell_pri_circle_of_healing : public SpellScriptLoader { @@ -869,6 +914,7 @@ class spell_pri_vampiric_touch : public SpellScriptLoader void AddSC_priest_spell_scripts() { + new spell_pri_blessed_recovery(); new spell_pri_circle_of_healing(); new spell_pri_divine_aegis(); new spell_pri_divine_hymn(); diff --git a/src/server/scripts/Spells/spell_rogue.cpp b/src/server/scripts/Spells/spell_rogue.cpp index affc4d1c26c..1abb6741e0d 100644 --- a/src/server/scripts/Spells/spell_rogue.cpp +++ b/src/server/scripts/Spells/spell_rogue.cpp @@ -43,7 +43,8 @@ enum RogueSpells SPELL_ROGUE_TRICKS_OF_THE_TRADE_PROC = 59628, SPELL_ROGUE_HONOR_AMONG_THIEVES = 51698, SPELL_ROGUE_HONOR_AMONG_THIEVES_PROC = 52916, - SPELL_ROGUE_HONOR_AMONG_THIEVES_2 = 51699 + SPELL_ROGUE_HONOR_AMONG_THIEVES_2 = 51699, + SPELL_ROGUE_T10_2P_BONUS = 70804, }; // 13877, 33735, (check 51211, 65956) - Blade Flurry @@ -843,6 +844,40 @@ public: } }; +// 70805 - Rogue T10 2P Bonus -- THIS SHOULD BE REMOVED WITH NEW PROC SYSTEM. +class spell_rog_t10_2p_bonus : public SpellScriptLoader +{ +public: + spell_rog_t10_2p_bonus() : SpellScriptLoader("spell_rog_t10_2p_bonus") { } + + class spell_rog_t10_2p_bonus_AuraScript : public AuraScript + { + PrepareAuraScript(spell_rog_t10_2p_bonus_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_ROGUE_T10_2P_BONUS)) + return false; + return true; + } + + bool CheckProc(ProcEventInfo& eventInfo) + { + return eventInfo.GetActor() == eventInfo.GetActionTarget(); + } + + void Register() override + { + DoCheckProc += AuraCheckProcFn(spell_rog_t10_2p_bonus_AuraScript::CheckProc); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_rog_t10_2p_bonus_AuraScript(); + } +}; + void AddSC_rogue_spell_scripts() { new spell_rog_blade_flurry(); @@ -858,4 +893,5 @@ void AddSC_rogue_spell_scripts() new spell_rog_tricks_of_the_trade_proc(); new spell_rog_honor_among_thieves(); new spell_rog_honor_among_thieves_proc(); + new spell_rog_t10_2p_bonus(); } diff --git a/src/server/scripts/Spells/spell_shaman.cpp b/src/server/scripts/Spells/spell_shaman.cpp index 41e72b1388b..ad65c7c6ec7 100644 --- a/src/server/scripts/Spells/spell_shaman.cpp +++ b/src/server/scripts/Spells/spell_shaman.cpp @@ -48,8 +48,10 @@ enum ShamanSpells SPELL_SHAMAN_ITEM_MANA_SURGE = 23571, SPELL_SHAMAN_LAVA_FLOWS_R1 = 51480, SPELL_SHAMAN_LAVA_FLOWS_TRIGGERED_R1 = 64694, + SPELL_SHAMAN_LIGHTNING_SHIELD_R1 = 26364, SPELL_SHAMAN_MANA_SPRING_TOTEM_ENERGIZE = 52032, SPELL_SHAMAN_MANA_TIDE_TOTEM = 39609, + SPELL_SHAMAN_NATURE_GUARDIAN = 31616, SPELL_SHAMAN_SATED = 57724, SPELL_SHAMAN_STORM_EARTH_AND_FIRE = 51483, SPELL_SHAMAN_TOTEM_EARTHBIND_EARTHGRAB = 64695, @@ -671,7 +673,7 @@ class spell_sha_heroism : public SpellScriptLoader } }; -// 23551 - Lightning Shield +// 23551 - Lightning Shield T2 Bonus class spell_sha_item_lightning_shield : public SpellScriptLoader { public: @@ -706,7 +708,7 @@ class spell_sha_item_lightning_shield : public SpellScriptLoader } }; -// 23552 - Lightning Shield +// 23552 - Lightning Shield T2 Bonus class spell_sha_item_lightning_shield_trigger : public SpellScriptLoader { public: @@ -718,7 +720,7 @@ class spell_sha_item_lightning_shield_trigger : public SpellScriptLoader bool Validate(SpellInfo const* /*spellInfo*/) override { - if (!sSpellMgr->GetSpellInfo(SPELL_SHAMAN_ITEM_MANA_SURGE)) + if (!sSpellMgr->GetSpellInfo(SPELL_SHAMAN_ITEM_LIGHTNING_SHIELD_DAMAGE)) return false; return true; } @@ -753,7 +755,7 @@ class spell_sha_item_mana_surge : public SpellScriptLoader bool Validate(SpellInfo const* /*spellInfo*/) override { - if (!sSpellMgr->GetSpellInfo(SPELL_SHAMAN_ITEM_LIGHTNING_SHIELD_DAMAGE)) + if (!sSpellMgr->GetSpellInfo(SPELL_SHAMAN_ITEM_MANA_SURGE)) return false; return true; } @@ -865,6 +867,51 @@ class spell_sha_lava_lash : public SpellScriptLoader } }; +// -324 - Lightning Shield +class spell_sha_lightning_shield : public SpellScriptLoader +{ +public: + spell_sha_lightning_shield() : SpellScriptLoader("spell_sha_lightning_shield") { } + + class spell_sha_lightning_shield_AuraScript : public AuraScript + { + PrepareAuraScript(spell_sha_lightning_shield_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_SHAMAN_LIGHTNING_SHIELD_R1)) + return false; + return true; + } + + bool CheckProc(ProcEventInfo& eventInfo) + { + if (eventInfo.GetActionTarget()) + return true; + return false; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + uint32 triggerSpell = sSpellMgr->GetSpellWithRank(SPELL_SHAMAN_LIGHTNING_SHIELD_R1, aurEff->GetSpellInfo()->GetRank()); + + eventInfo.GetActionTarget()->CastSpell(eventInfo.GetActor(), triggerSpell, true, nullptr, aurEff); + } + + void Register() override + { + DoCheckProc += AuraCheckProcFn(spell_sha_lightning_shield_AuraScript::CheckProc); + OnEffectProc += AuraEffectProcFn(spell_sha_lightning_shield_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_sha_lightning_shield_AuraScript(); + } +}; + // 52031, 52033, 52034, 52035, 52036, 58778, 58779, 58780 - Mana Spring Totem class spell_sha_mana_spring_totem : public SpellScriptLoader { @@ -924,6 +971,7 @@ class spell_sha_mana_tide_totem : public SpellScriptLoader void HandleDummy(SpellEffIndex /*effIndex*/) { if (Unit* caster = GetCaster()) + { if (Unit* unitTarget = GetHitUnit()) { if (unitTarget->getPowerType() == POWER_MANA) @@ -938,6 +986,7 @@ class spell_sha_mana_tide_totem : public SpellScriptLoader caster->CastCustomSpell(unitTarget, SPELL_SHAMAN_MANA_TIDE_TOTEM, &effBasePoints0, NULL, NULL, true, NULL, NULL, GetOriginalCaster()->GetGUID()); } } + } } void Register() override @@ -952,6 +1001,56 @@ class spell_sha_mana_tide_totem : public SpellScriptLoader } }; +// -30881 - Nature's Guardian +class spell_sha_nature_guardian : public SpellScriptLoader +{ +public: + spell_sha_nature_guardian() : SpellScriptLoader("spell_sha_nature_guardian") { } + + class spell_sha_nature_guardian_AuraScript : public AuraScript + { + PrepareAuraScript(spell_sha_nature_guardian_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_SHAMAN_NATURE_GUARDIAN)) + return false; + return true; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + int32 healthpct = aurEff->GetSpellInfo()->Effects[EFFECT_1].CalcValue(); // %s2 - the 30% threshold for health + + if (Unit* target = eventInfo.GetActionTarget()) + { + if (target->HealthBelowPctDamaged(healthpct, eventInfo.GetDamageInfo()->GetDamage())) + { + + uint32 bp = CalculatePct(target->GetMaxHealth(), aurEff->GetAmount()); + target->CastCustomSpell(SPELL_SHAMAN_NATURE_GUARDIAN, SPELLVALUE_BASE_POINT0, bp, target, true, nullptr, aurEff); + + // Threat reduction is around 10% confirmed in retail and from wiki + Unit* attacker = eventInfo.GetActor(); + if (attacker->IsAlive()) + attacker->getThreatManager().modifyThreatPercent(target, -10); + } + } + } + + void Register() override + { + OnEffectProc += AuraEffectProcFn(spell_sha_nature_guardian_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_sha_nature_guardian_AuraScript(); + } +}; + // 6495 - Sentry Totem class spell_sha_sentry_totem : public SpellScriptLoader { @@ -1085,8 +1184,10 @@ void AddSC_shaman_spell_scripts() new spell_sha_item_mana_surge(); new spell_sha_item_t10_elemental_2p_bonus(); new spell_sha_lava_lash(); + new spell_sha_lightning_shield(); new spell_sha_mana_spring_totem(); new spell_sha_mana_tide_totem(); + new spell_sha_nature_guardian(); new spell_sha_sentry_totem(); new spell_sha_thunderstorm(); new spell_sha_totemic_mastery(); diff --git a/src/server/scripts/Spells/spell_warlock.cpp b/src/server/scripts/Spells/spell_warlock.cpp index a0a6189cbe2..5e0074bf9f7 100644 --- a/src/server/scripts/Spells/spell_warlock.cpp +++ b/src/server/scripts/Spells/spell_warlock.cpp @@ -50,6 +50,12 @@ enum WarlockSpells SPELL_WARLOCK_IMPROVED_HEALTH_FUNNEL_BUFF_R2 = 60956, SPELL_WARLOCK_LIFE_TAP_ENERGIZE = 31818, SPELL_WARLOCK_LIFE_TAP_ENERGIZE_2 = 32553, + SPELL_WARLOCK_NETHER_PROTECTION_HOLY = 54370, + SPELL_WARLOCK_NETHER_PROTECTION_FIRE = 54371, + SPELL_WARLOCK_NETHER_PROTECTION_FROST = 54372, + SPELL_WARLOCK_NETHER_PROTECTION_ARCANE = 54373, + SPELL_WARLOCK_NETHER_PROTECTION_SHADOW = 54374, + SPELL_WARLOCK_NETHER_PROTECTION_NATURE = 54375, SPELL_WARLOCK_SOULSHATTER = 32835, SPELL_WARLOCK_SIPHON_LIFE_HEAL = 63106, SPELL_WARLOCK_UNSTABLE_AFFLICTION_DISPEL = 31117 @@ -377,6 +383,8 @@ class spell_warl_demonic_empowerment : public SpellScriptLoader case CREATURE_FAMILY_IMP: targetCreature->CastSpell(targetCreature, SPELL_WARLOCK_DEMONIC_EMPOWERMENT_IMP, true); break; + default: + break; } } } @@ -682,6 +690,95 @@ class spell_warl_life_tap : public SpellScriptLoader } }; +// -30299 - Nether Protection +class spell_warl_nether_protection : public SpellScriptLoader +{ +public: + spell_warl_nether_protection() : SpellScriptLoader("spell_warl_nether_protection") { } + + class spell_warl_nether_protection_AuraScript : public AuraScript + { + PrepareAuraScript(spell_warl_nether_protection_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_WARLOCK_NETHER_PROTECTION_HOLY) || + !sSpellMgr->GetSpellInfo(SPELL_WARLOCK_NETHER_PROTECTION_FIRE) || + !sSpellMgr->GetSpellInfo(SPELL_WARLOCK_NETHER_PROTECTION_FROST) || + !sSpellMgr->GetSpellInfo(SPELL_WARLOCK_NETHER_PROTECTION_ARCANE) || + !sSpellMgr->GetSpellInfo(SPELL_WARLOCK_NETHER_PROTECTION_SHADOW) || + !sSpellMgr->GetSpellInfo(SPELL_WARLOCK_NETHER_PROTECTION_NATURE)) + return false; + return true; + } + + bool CheckProc(ProcEventInfo& eventInfo) + { + if (eventInfo.GetDamageInfo()) + { + switch (GetFirstSchoolInMask(eventInfo.GetDamageInfo()->GetSchoolMask())) + { + case SPELL_SCHOOL_HOLY: + case SPELL_SCHOOL_FIRE: + case SPELL_SCHOOL_NATURE: + case SPELL_SCHOOL_FROST: + case SPELL_SCHOOL_SHADOW: + case SPELL_SCHOOL_ARCANE: + return true; + default: + break; + } + } + + return false; + } + + void HandleProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo) + { + PreventDefaultAction(); + uint32 triggerspell = 0; + + switch (GetFirstSchoolInMask(eventInfo.GetDamageInfo()->GetSchoolMask())) + { + case SPELL_SCHOOL_HOLY: + triggerspell = SPELL_WARLOCK_NETHER_PROTECTION_HOLY; + break; + case SPELL_SCHOOL_FIRE: + triggerspell = SPELL_WARLOCK_NETHER_PROTECTION_FIRE; + break; + case SPELL_SCHOOL_NATURE: + triggerspell = SPELL_WARLOCK_NETHER_PROTECTION_NATURE; + break; + case SPELL_SCHOOL_FROST: + triggerspell = SPELL_WARLOCK_NETHER_PROTECTION_FROST; + break; + case SPELL_SCHOOL_SHADOW: + triggerspell = SPELL_WARLOCK_NETHER_PROTECTION_SHADOW; + break; + case SPELL_SCHOOL_ARCANE: + triggerspell = SPELL_WARLOCK_NETHER_PROTECTION_ARCANE; + break; + default: + return; + } + + if (Unit* target = eventInfo.GetActionTarget()) + target->CastSpell(target, triggerspell, true, nullptr, aurEff); + } + + void Register() override + { + DoCheckProc += AuraCheckProcFn(spell_warl_nether_protection_AuraScript::CheckProc); + OnEffectProc += AuraEffectProcFn(spell_warl_nether_protection_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_warl_nether_protection_AuraScript(); + } +}; + // 18541 - Ritual of Doom Effect class spell_warl_ritual_of_doom_effect : public SpellScriptLoader { @@ -917,6 +1014,7 @@ void AddSC_warlock_spell_scripts() new spell_warl_haunt(); new spell_warl_health_funnel(); new spell_warl_life_tap(); + new spell_warl_nether_protection(); new spell_warl_ritual_of_doom_effect(); new spell_warl_seed_of_corruption(); new spell_warl_shadow_ward(); diff --git a/src/server/scripts/World/go_scripts.cpp b/src/server/scripts/World/go_scripts.cpp index 3094ecd660a..8f2ea5887d2 100644 --- a/src/server/scripts/World/go_scripts.cpp +++ b/src/server/scripts/World/go_scripts.cpp @@ -1171,7 +1171,7 @@ public: player->CastSpell(player, SPELL_CLEANSING_SOUL); player->SetStandState(UNIT_STAND_STATE_SIT); } - return true; + return true; } }; diff --git a/src/server/scripts/World/item_scripts.cpp b/src/server/scripts/World/item_scripts.cpp index f4241ba0819..52174e1b012 100644 --- a/src/server/scripts/World/item_scripts.cpp +++ b/src/server/scripts/World/item_scripts.cpp @@ -57,18 +57,18 @@ public: //for special scripts switch (itemId) { - case 24538: + case 24538: if (player->GetAreaId() != 3628) disabled = true; - break; - case 34489: + break; + case 34489: if (player->GetZoneId() != 4080) disabled = true; - break; - case 34475: - if (const SpellInfo* spellInfo = sSpellMgr->GetSpellInfo(SPELL_ARCANE_CHARGES)) + break; + case 34475: + if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(SPELL_ARCANE_CHARGES)) Spell::SendCastResult(player, spellInfo, 1, SPELL_FAILED_NOT_ON_GROUND); - break; + break; } // allow use in flight only diff --git a/src/server/shared/DataStores/DBCStore.h b/src/server/shared/DataStores/DBCStore.h index 7c2cab1e36a..b93bbdaea12 100644 --- a/src/server/shared/DataStores/DBCStore.h +++ b/src/server/shared/DataStores/DBCStore.h @@ -25,121 +25,6 @@ #include "DatabaseWorkerPool.h" #include "Implementation/WorldDatabase.h" #include "DatabaseEnv.h" -#include <G3D/Vector3.h> -#include <G3D/AABox.h> - - // Structures for M4 file. Source: https://wowdev.wiki -template<typename T> -struct M2SplineKey -{ - T p0; - T p1; - T p2; -}; - -struct M2Header -{ - char Magic[4]; // "MD20" - uint32 Version; // The version of the format. - uint32 lName; // Length of the model's name including the trailing \0 - uint32 ofsName; // Offset to the name, it seems like models can get reloaded by this name.should be unique, i guess. - uint32 GlobalModelFlags; // 0x0001: tilt x, 0x0002: tilt y, 0x0008: add 2 fields in header, 0x0020: load .phys data (MoP+), 0x0080: has _lod .skin files (MoP?+), 0x0100: is camera related. - uint32 nGlobalSequences; - uint32 ofsGlobalSequences; // A list of timestamps. - uint32 nAnimations; - uint32 ofsAnimations; // Information about the animations in the model. - uint32 nAnimationLookup; - uint32 ofsAnimationLookup; // Mapping of global IDs to the entries in the Animation sequences block. - uint32 nBones; // MAX_BONES = 0x100 - uint32 ofsBones; // Information about the bones in this model. - uint32 nKeyBoneLookup; - uint32 ofsKeyBoneLookup; // Lookup table for key skeletal bones. - uint32 nVertices; - uint32 ofsVertices; // Vertices of the model. - uint32 nViews; // Views (LOD) are now in .skins. - uint32 nSubmeshAnimations; - uint32 ofsSubmeshAnimations; // Submesh color and alpha animations definitions. - uint32 nTextures; - uint32 ofsTextures; // Textures of this model. - uint32 nTransparency; - uint32 ofsTransparency; // Transparency of textures. - uint32 nUVAnimation; - uint32 ofsUVAnimation; - uint32 nTexReplace; - uint32 ofsTexReplace; // Replaceable Textures. - uint32 nRenderFlags; - uint32 ofsRenderFlags; // Blending modes / render flags. - uint32 nBoneLookupTable; - uint32 ofsBoneLookupTable; // A bone lookup table. - uint32 nTexLookup; - uint32 ofsTexLookup; // The same for textures. - uint32 nTexUnits; // possibly removed with cata?! - uint32 ofsTexUnits; // And texture units. Somewhere they have to be too. - uint32 nTransLookup; - uint32 ofsTransLookup; // Everything needs its lookup. Here are the transparencies. - uint32 nUVAnimLookup; - uint32 ofsUVAnimLookup; - G3D::AABox BoundingBox; // min/max( [1].z, 2.0277779f ) - 0.16f seems to be the maximum camera height - float BoundingSphereRadius; - G3D::AABox CollisionBox; - float CollisionSphereRadius; - uint32 nBoundingTriangles; - uint32 ofsBoundingTriangles; // Our bounding volumes. Similar structure like in the old ofsViews. - uint32 nBoundingVertices; - uint32 ofsBoundingVertices; - uint32 nBoundingNormals; - uint32 ofsBoundingNormals; - uint32 nAttachments; - uint32 ofsAttachments; // Attachments are for weapons etc. - uint32 nAttachLookup; - uint32 ofsAttachLookup; // Of course with a lookup. - uint32 nEvents; - uint32 ofsEvents; // Used for playing sounds when dying and a lot else. - uint32 nLights; - uint32 ofsLights; // Lights are mainly used in loginscreens but in wands and some doodads too. - uint32 nCameras; // Format of Cameras changed with version 271! - uint32 ofsCameras; // The cameras are present in most models for having a model in the Character-Tab. - uint32 nCameraLookup; - uint32 ofsCameraLookup; // And lookup-time again. - uint32 nRibbonEmitters; - uint32 ofsRibbonEmitters; // Things swirling around. See the CoT-entrance for light-trails. - uint32 nParticleEmitters; - uint32 ofsParticleEmitters; // Spells and weapons, doodads and loginscreens use them. Blood dripping of a blade? Particles. - uint32 nBlendMaps; // This has to deal with blending. Exists IFF (flags & 0x8) != 0. When set, textures blending is overriden by the associated array. See M2/WotLK#Blend_mode_overrides - uint32 ofsBlendMaps; // Same as above. Points to an array of uint16 of nBlendMaps entries -- From WoD information.}; -}; - -struct M2Array -{ - uint32_t number; - uint32 offset_elements; -}; -struct M2Track -{ - uint16_t interpolation_type; - uint16_t global_sequence; - M2Array timestamps; - M2Array values; -}; - -struct M2Camera -{ - uint32_t type; // 0: portrait, 1: characterinfo; -1: else (flyby etc.); referenced backwards in the lookup table. - float fov; // No radians, no degrees. Multiply by 35 to get degrees. - float far_clip; - float near_clip; - M2Track positions; // How the camera's position moves. Should be 3*3 floats. - G3D::Vector3 position_base; - M2Track target_positions; // How the target moves. Should be 3*3 floats. - G3D::Vector3 target_position_base; - M2Track rolldata; // The camera can have some roll-effect. Its 0 to 2*Pi. -}; - -struct FlyByCamera -{ - uint32 timeStamp; - G3D::Vector4 locations; -}; struct SqlDbc { diff --git a/src/server/worldserver/Main.cpp b/src/server/worldserver/Main.cpp index 2b5553b4bb0..f4d736ac675 100644 --- a/src/server/worldserver/Main.cpp +++ b/src/server/worldserver/Main.cpp @@ -24,6 +24,7 @@ #include <openssl/crypto.h> #include <boost/asio/io_service.hpp> #include <boost/asio/deadline_timer.hpp> +#include <boost/filesystem/path.hpp> #include <boost/program_options.hpp> #include "Common.h" @@ -53,6 +54,7 @@ #include "AppenderDB.h" using namespace boost::program_options; +namespace fs = boost::filesystem; #ifndef _TRINITY_CORE_CONFIG #define _TRINITY_CORE_CONFIG "worldserver.conf" @@ -90,14 +92,14 @@ void ClearOnlineAccounts(); void ShutdownCLIThread(std::thread* cliThread); void ShutdownThreadPool(std::vector<std::thread>& threadPool); bool LoadRealmInfo(); -variables_map GetConsoleArguments(int argc, char** argv, std::string& cfg_file, std::string& cfg_service); +variables_map GetConsoleArguments(int argc, char** argv, fs::path& configFile, std::string& cfg_service); /// Launch the Trinity server extern int main(int argc, char** argv) { signal(SIGABRT, &Trinity::AbortHandler); - std::string configFile = _TRINITY_CORE_CONFIG; + auto configFile = fs::absolute(_TRINITY_CORE_CONFIG); std::string configService; auto vm = GetConsoleArguments(argc, argv, configFile, configService); @@ -115,7 +117,9 @@ extern int main(int argc, char** argv) #endif std::string configError; - if (!sConfigMgr->LoadInitial(configFile, configError)) + if (!sConfigMgr->LoadInitial(configFile.generic_string(), + std::vector<std::string>(argv, argv + argc), + configError)) { printf("Error in config file: %s\n", configError.c_str()); return 1; @@ -136,7 +140,7 @@ extern int main(int argc, char** argv) TC_LOG_INFO("server.worldserver", " \\/_/\\/_/ \\/_/\\/_/\\/_/\\/_/\\/__/ `/___/> \\"); TC_LOG_INFO("server.worldserver", " C O R E /\\___/"); TC_LOG_INFO("server.worldserver", "http://TrinityCore.org \\/__/\n"); - TC_LOG_INFO("server.worldserver", "Using configuration file %s.", configFile.c_str()); + TC_LOG_INFO("server.worldserver", "Using configuration file %s.", sConfigMgr->GetFilename().c_str()); TC_LOG_INFO("server.worldserver", "Using SSL version: %s (library: %s)", OPENSSL_VERSION_TEXT, SSLeay_version(SSLEAY_VERSION)); TC_LOG_INFO("server.worldserver", "Using Boost version: %i.%i.%i", BOOST_VERSION / 100000, BOOST_VERSION / 100 % 1000, BOOST_VERSION % 100); @@ -571,7 +575,7 @@ void ClearOnlineAccounts() /// @} -variables_map GetConsoleArguments(int argc, char** argv, std::string& configFile, std::string& configService) +variables_map GetConsoleArguments(int argc, char** argv, fs::path& configFile, std::string& configService) { // Silences warning about configService not be used if the OS is not Windows (void)configService; @@ -580,7 +584,8 @@ variables_map GetConsoleArguments(int argc, char** argv, std::string& configFile all.add_options() ("help,h", "print usage message") ("version,v", "print version build info") - ("config,c", value<std::string>(&configFile)->default_value(_TRINITY_CORE_CONFIG), "use <arg> as configuration file") + ("config,c", value<fs::path>(&configFile)->default_value(fs::absolute(_TRINITY_CORE_CONFIG)), + "use <arg> as configuration file") ; #ifdef _WIN32 options_description win("Windows platform specific options"); diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist index 1d425e68246..ccb784f8c2b 100644 --- a/src/server/worldserver/worldserver.conf.dist +++ b/src/server/worldserver/worldserver.conf.dist @@ -725,7 +725,7 @@ CharacterCreating.Disabled.RaceMask = 0 # 2 - (Disabled, Paladin) # 4 - (Disabled, Hunter) # 8 - (Disabled, Rogue) -# 16 - (Disabled, Undead) +# 16 - (Disabled, Priest) # 32 - (Disabled, Death Knight) # 64 - (Disabled, Shaman) # 128 - (Disabled, Mage) @@ -1658,6 +1658,14 @@ ListenRange.TextEmote = 40 ListenRange.Yell = 300 # +# Creature.MovingStopTimeForPlayer +# Description: Time (in milliseconds) during which creature will not move after +# interaction with player. +# Default: 180000 + +Creature.MovingStopTimeForPlayer = 180000 + +# ################################################################################################### ################################################################################################### @@ -1869,6 +1877,13 @@ GM.LowerSecurity = 0 GM.TicketSystem.ChanceOfGMSurvey = 50 # +# GM.ForceShutdownThreshold +# Description: Minimum shutdown time in seconds before 'force' is required if other players are connected. +# Default: 30 + +GM.ForceShutdownThreshold = 30 + +# ################################################################################################### ################################################################################################### diff --git a/src/tools/map_extractor/System.cpp b/src/tools/map_extractor/System.cpp index 1d84fc75d27..9d3dc47bce0 100644 --- a/src/tools/map_extractor/System.cpp +++ b/src/tools/map_extractor/System.cpp @@ -1041,7 +1041,7 @@ void ExtractCameraFiles(int locale, bool basicLocale) std::vector<std::string> camerafiles; size_t cam_count = camdbc.getRecordCount(); - for (uint32 i = 0; i < cam_count; ++i) + for (size_t i = 0; i < cam_count; ++i) { std::string camFile(camdbc.getRecord(i).getString(1)); size_t loc = camFile.find(".mdx"); |
