aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/genrev/CMakeLists.txt4
-rw-r--r--src/server/authserver/CMakeLists.txt6
-rw-r--r--src/server/authserver/Main.cpp35
-rw-r--r--src/server/authserver/authserver.conf.dist84
-rw-r--r--src/server/collision/CMakeLists.txt3
-rw-r--r--src/server/collision/Management/MMapManager.cpp14
-rw-r--r--src/server/collision/Maps/MapTree.cpp5
-rw-r--r--src/server/collision/Maps/TileAssembler.cpp1
-rw-r--r--src/server/collision/Models/GameObjectModel.cpp2
-rw-r--r--src/server/collision/Models/ModelInstance.cpp1
-rw-r--r--src/server/collision/Models/WorldModel.cpp1
-rw-r--r--src/server/game/AI/CoreAI/GuardAI.cpp3
-rw-r--r--src/server/game/AI/CoreAI/PassiveAI.cpp1
-rw-r--r--src/server/game/AI/CoreAI/PetAI.cpp2
-rw-r--r--src/server/game/AI/CoreAI/ReactorAI.cpp4
-rw-r--r--src/server/game/AI/CoreAI/TotemAI.cpp2
-rw-r--r--src/server/game/AI/CoreAI/UnitAI.cpp6
-rw-r--r--src/server/game/AI/CreatureAISelector.cpp1
-rw-r--r--src/server/game/AI/ScriptedAI/ScriptedCreature.cpp7
-rw-r--r--src/server/game/AI/ScriptedAI/ScriptedCreature.h1
-rw-r--r--src/server/game/AI/SmartScripts/SmartAI.cpp4
-rw-r--r--src/server/game/AI/SmartScripts/SmartScript.cpp16
-rw-r--r--src/server/game/AI/SmartScripts/SmartScript.h32
-rw-r--r--src/server/game/AI/SmartScripts/SmartScriptMgr.cpp36
-rw-r--r--src/server/game/AI/SmartScripts/SmartScriptMgr.h21
-rw-r--r--src/server/game/Achievements/AchievementMgr.cpp1281
-rw-r--r--src/server/game/Achievements/AchievementMgr.h8
-rw-r--r--src/server/game/AuctionHouse/AuctionHouseMgr.cpp5
-rw-r--r--src/server/game/AuctionHouseBot/AuctionHouseBot.cpp2
-rw-r--r--src/server/game/AuctionHouseBot/AuctionHouseBot.h6
-rw-r--r--src/server/game/AuctionHouseBot/AuctionHouseBotBuyer.cpp2
-rw-r--r--src/server/game/Battlefield/Battlefield.cpp1
-rw-r--r--src/server/game/Battlefield/BattlefieldMgr.cpp1
-rw-r--r--src/server/game/Battlegrounds/ArenaTeam.cpp2
-rw-r--r--src/server/game/Battlegrounds/Battleground.cpp4
-rw-r--r--src/server/game/Battlegrounds/BattlegroundMgr.cpp2
-rw-r--r--src/server/game/Battlegrounds/BattlegroundQueue.cpp2
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp2
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp1
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp1
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp1
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp1
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp2
-rw-r--r--src/server/game/CMakeLists.txt4
-rw-r--r--src/server/game/Chat/Chat.cpp33
-rw-r--r--src/server/game/Chat/Chat.h22
-rw-r--r--src/server/game/Chat/ChatLink.cpp2
-rw-r--r--src/server/game/Combat/HostileRefManager.cpp1
-rw-r--r--src/server/game/Combat/ThreatManager.cpp4
-rw-r--r--src/server/game/Conditions/ConditionMgr.cpp23
-rw-r--r--src/server/game/Conditions/ConditionMgr.h3
-rw-r--r--src/server/game/DungeonFinding/LFG.cpp3
-rw-r--r--src/server/game/DungeonFinding/LFG.h4
-rw-r--r--src/server/game/DungeonFinding/LFGGroupData.cpp12
-rw-r--r--src/server/game/DungeonFinding/LFGGroupData.h4
-rw-r--r--src/server/game/DungeonFinding/LFGMgr.cpp44
-rw-r--r--src/server/game/DungeonFinding/LFGMgr.h3
-rw-r--r--src/server/game/DungeonFinding/LFGQueue.cpp5
-rw-r--r--src/server/game/Entities/Corpse/Corpse.cpp3
-rw-r--r--src/server/game/Entities/Creature/Creature.cpp9
-rw-r--r--src/server/game/Entities/Creature/TemporarySummon.cpp1
-rw-r--r--src/server/game/Entities/DynamicObject/DynamicObject.cpp2
-rw-r--r--src/server/game/Entities/GameObject/GameObject.cpp2
-rw-r--r--src/server/game/Entities/Object/Object.cpp47
-rw-r--r--src/server/game/Entities/Object/Object.h1
-rw-r--r--src/server/game/Entities/Object/ObjectGuid.cpp1
-rw-r--r--src/server/game/Entities/Object/ObjectGuid.h2
-rw-r--r--src/server/game/Entities/Pet/Pet.cpp3
-rw-r--r--src/server/game/Entities/Player/Player.cpp131
-rw-r--r--src/server/game/Entities/Player/Player.h2
-rw-r--r--src/server/game/Entities/Totem/Totem.cpp2
-rw-r--r--src/server/game/Entities/Transport/Transport.cpp4
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp121
-rwxr-xr-xsrc/server/game/Entities/Vehicle/Vehicle.cpp4
-rw-r--r--src/server/game/Events/GameEventMgr.cpp1
-rw-r--r--src/server/game/Globals/ObjectAccessor.cpp8
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp33
-rw-r--r--src/server/game/Grids/Notifiers/GridNotifiers.cpp5
-rw-r--r--src/server/game/Grids/Notifiers/GridNotifiers.h2
-rw-r--r--src/server/game/Grids/ObjectGridLoader.cpp1
-rw-r--r--src/server/game/Groups/Group.cpp1
-rw-r--r--src/server/game/Handlers/AddonHandler.cpp1
-rw-r--r--src/server/game/Handlers/BattlefieldHandler.cpp2
-rw-r--r--src/server/game/Handlers/CharacterHandler.cpp1
-rw-r--r--src/server/game/Handlers/ChatHandler.cpp1
-rw-r--r--src/server/game/Handlers/CombatHandler.cpp2
-rw-r--r--src/server/game/Handlers/DuelHandler.cpp2
-rw-r--r--src/server/game/Handlers/GuildHandler.cpp3
-rw-r--r--src/server/game/Handlers/ItemHandler.cpp2
-rw-r--r--src/server/game/Handlers/MiscHandler.cpp8
-rw-r--r--src/server/game/Handlers/MovementHandler.cpp1
-rw-r--r--src/server/game/Handlers/NPCHandler.cpp2
-rw-r--r--src/server/game/Handlers/PetHandler.cpp22
-rw-r--r--src/server/game/Handlers/PetitionsHandler.cpp2
-rw-r--r--src/server/game/Handlers/QueryHandler.cpp2
-rw-r--r--src/server/game/Handlers/QuestHandler.cpp2
-rw-r--r--src/server/game/Handlers/SkillHandler.cpp2
-rw-r--r--src/server/game/Handlers/SpellHandler.cpp5
-rw-r--r--src/server/game/Handlers/TaxiHandler.cpp1
-rw-r--r--src/server/game/Handlers/VoiceChatHandler.cpp1
-rw-r--r--src/server/game/Instances/InstanceSaveMgr.cpp3
-rw-r--r--src/server/game/Instances/InstanceScript.cpp6
-rw-r--r--src/server/game/Instances/InstanceScript.h8
-rw-r--r--src/server/game/Loot/LootMgr.cpp2
-rw-r--r--src/server/game/Maps/Map.cpp33
-rw-r--r--src/server/game/Maps/MapManager.cpp1
-rw-r--r--src/server/game/Miscellaneous/Language.h3
-rw-r--r--src/server/game/Movement/MotionMaster.cpp40
-rw-r--r--src/server/game/Movement/MotionMaster.h1
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp2
-rw-r--r--src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp1
-rw-r--r--src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp1
-rw-r--r--src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp2
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp5
-rw-r--r--src/server/game/Movement/Spline/MoveSpline.cpp2
-rw-r--r--src/server/game/Movement/Spline/MoveSplineInit.cpp1
-rw-r--r--src/server/game/Movement/Spline/MovementUtil.cpp1
-rw-r--r--src/server/game/OutdoorPvP/OutdoorPvP.cpp1
-rw-r--r--src/server/game/Reputation/ReputationMgr.cpp3
-rw-r--r--src/server/game/Reputation/ReputationMgr.h4
-rw-r--r--src/server/game/Scripting/MapScripts.cpp2
-rw-r--r--src/server/game/Scripting/ScriptLoader.cpp8
-rw-r--r--src/server/game/Scripting/ScriptMgr.cpp3
-rw-r--r--src/server/game/Scripting/ScriptMgr.h2
-rw-r--r--src/server/game/Server/WorldSession.cpp31
-rw-r--r--src/server/game/Server/WorldSocket.cpp10
-rw-r--r--src/server/game/Server/WorldSocketMgr.cpp3
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.cpp55
-rw-r--r--src/server/game/Spells/Auras/SpellAuras.cpp13
-rw-r--r--src/server/game/Spells/Auras/SpellAuras.h4
-rw-r--r--src/server/game/Spells/Spell.cpp155
-rw-r--r--src/server/game/Spells/SpellEffects.cpp28
-rw-r--r--src/server/game/Spells/SpellInfo.cpp96
-rw-r--r--src/server/game/Spells/SpellInfo.h10
-rw-r--r--src/server/game/Spells/SpellMgr.cpp8
-rw-r--r--src/server/game/Spells/SpellScript.cpp1
-rw-r--r--src/server/game/Warden/Warden.cpp2
-rw-r--r--src/server/game/Warden/WardenCheckMgr.cpp1
-rw-r--r--src/server/game/Warden/WardenWin.cpp1
-rw-r--r--src/server/game/Weather/Weather.cpp9
-rw-r--r--src/server/game/Weather/WeatherMgr.cpp6
-rw-r--r--src/server/game/World/World.cpp36
-rw-r--r--src/server/game/World/World.h3
-rw-r--r--src/server/scripts/CMakeLists.txt4
-rw-r--r--src/server/scripts/Commands/cs_lfg.cpp10
-rw-r--r--src/server/scripts/Commands/cs_misc.cpp4
-rw-r--r--src/server/scripts/EasternKingdoms/Karazhan/karazhan.cpp6
-rw-r--r--src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp2
-rw-r--r--src/server/scripts/EasternKingdoms/SunkenTemple/sunken_temple.cpp26
-rw-r--r--src/server/scripts/EasternKingdoms/ZulAman/boss_hexlord.cpp81
-rw-r--r--src/server/scripts/EasternKingdoms/zone_redridge_mountains.cpp2
-rw-r--r--src/server/scripts/EasternKingdoms/zone_undercity.cpp242
-rw-r--r--src/server/scripts/Kalimdor/CMakeLists.txt1
-rw-r--r--src/server/scripts/Kalimdor/RazorfenKraul/razorfen_kraul.cpp124
-rw-r--r--src/server/scripts/Kalimdor/zone_bloodmyst_isle.cpp722
-rw-r--r--src/server/scripts/Kalimdor/zone_felwood.cpp37
-rw-r--r--src/server/scripts/Kalimdor/zone_mulgore.cpp306
-rw-r--r--src/server/scripts/Kalimdor/zone_the_barrens.cpp1
-rw-r--r--src/server/scripts/Northrend/CMakeLists.txt3
-rw-r--r--src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/instance_trial_of_the_crusader.cpp8
-rw-r--r--src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.cpp18
-rw-r--r--src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_bronjahm.cpp190
-rw-r--r--src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_devourer_of_souls.cpp22
-rw-r--r--src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/forge_of_souls.h54
-rw-r--r--src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/instance_forge_of_souls.cpp15
-rw-r--r--src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp23
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_rotface.cpp51
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp1
-rw-r--r--src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp43
-rw-r--r--src/server/scripts/Northrend/Nexus/Nexus/boss_commander_kolurg.cpp80
-rw-r--r--src/server/scripts/Northrend/Nexus/Nexus/boss_commander_stoutbeard.cpp72
-rw-r--r--src/server/scripts/Northrend/Nexus/Nexus/boss_nexus_commanders.cpp110
-rw-r--r--src/server/scripts/Northrend/Nexus/Nexus/nexus.h23
-rw-r--r--src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp243
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp21
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp53
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h1
-rw-r--r--src/server/scripts/Northrend/VioletHold/boss_zuramat.cpp9
-rw-r--r--src/server/scripts/Northrend/VioletHold/instance_violet_hold.cpp1
-rw-r--r--src/server/scripts/Northrend/zone_borean_tundra.cpp49
-rw-r--r--src/server/scripts/Northrend/zone_grizzly_hills.cpp39
-rw-r--r--src/server/scripts/Northrend/zone_storm_peaks.cpp92
-rw-r--r--src/server/scripts/Outland/BlackTemple/boss_shade_of_akama.cpp146
-rw-r--r--src/server/scripts/Outland/TempestKeep/arcatraz/arcatraz.cpp7
-rw-r--r--src/server/scripts/Outland/TempestKeep/arcatraz/boss_harbinger_skyriss.cpp5
-rw-r--r--src/server/scripts/Outland/zone_shadowmoon_valley.cpp327
-rw-r--r--src/server/scripts/Spells/spell_generic.cpp38
-rw-r--r--src/server/scripts/Spells/spell_quest.cpp31
-rw-r--r--src/server/shared/CMakeLists.txt8
-rw-r--r--src/server/shared/Configuration/Config.cpp1
-rw-r--r--src/server/shared/Cryptography/ARC4.cpp1
-rw-r--r--src/server/shared/Cryptography/BigNumber.cpp8
-rw-r--r--src/server/shared/Database/DatabaseLoader.cpp191
-rw-r--r--src/server/shared/Database/DatabaseLoader.h71
-rw-r--r--src/server/shared/Database/DatabaseWorker.cpp2
-rw-r--r--src/server/shared/Database/DatabaseWorkerPool.h147
-rw-r--r--src/server/shared/Database/Implementation/CharacterDatabase.cpp4
-rw-r--r--src/server/shared/Database/Implementation/CharacterDatabase.h2
-rw-r--r--src/server/shared/Database/MySQLConnection.cpp26
-rw-r--r--src/server/shared/Database/MySQLConnection.h5
-rw-r--r--src/server/shared/Database/QueryHolder.cpp23
-rw-r--r--src/server/shared/Database/QueryHolder.h5
-rw-r--r--src/server/shared/Database/Transaction.cpp15
-rw-r--r--src/server/shared/Database/Transaction.h5
-rw-r--r--src/server/shared/Debugging/WheatyExceptionReport.cpp14
-rw-r--r--src/server/shared/Debugging/WheatyExceptionReport.h2
-rw-r--r--src/server/shared/Logging/Appender.cpp35
-rw-r--r--src/server/shared/Logging/Appender.h18
-rw-r--r--src/server/shared/Logging/AppenderConsole.cpp10
-rw-r--r--src/server/shared/Logging/AppenderConsole.h2
-rw-r--r--src/server/shared/Logging/AppenderDB.cpp12
-rw-r--r--src/server/shared/Logging/AppenderDB.h2
-rw-r--r--src/server/shared/Logging/AppenderFile.cpp14
-rw-r--r--src/server/shared/Logging/AppenderFile.h2
-rw-r--r--src/server/shared/Logging/Log.cpp52
-rw-r--r--src/server/shared/Logging/Log.h67
-rw-r--r--src/server/shared/Logging/LogOperation.cpp8
-rw-r--r--src/server/shared/Logging/LogOperation.h10
-rw-r--r--src/server/shared/Logging/Logger.cpp4
-rw-r--r--src/server/shared/Logging/Logger.h2
-rw-r--r--src/server/shared/Networking/Socket.h4
-rw-r--r--src/server/shared/Networking/SocketMgr.h2
-rw-r--r--src/server/shared/Updater/DBUpdater.cpp380
-rw-r--r--src/server/shared/Updater/DBUpdater.h79
-rw-r--r--src/server/shared/Updater/UpdateFetcher.cpp401
-rw-r--r--src/server/shared/Updater/UpdateFetcher.h127
-rw-r--r--src/server/shared/Utilities/StringFormat.h34
-rw-r--r--src/server/worldserver/CMakeLists.txt6
-rw-r--r--src/server/worldserver/CommandLine/CliRunnable.cpp7
-rw-r--r--src/server/worldserver/Main.cpp80
-rw-r--r--src/server/worldserver/RemoteAccess/RASession.h2
-rw-r--r--src/server/worldserver/worldserver.conf.dist90
232 files changed, 4779 insertions, 3382 deletions
diff --git a/src/genrev/CMakeLists.txt b/src/genrev/CMakeLists.txt
index 8ab3494cd70..e72643c6a6b 100644
--- a/src/genrev/CMakeLists.txt
+++ b/src/genrev/CMakeLists.txt
@@ -10,6 +10,6 @@
# Need to pass old ${CMAKE_BINARY_DIR} as param because its different at build stage
add_custom_target(revision.h ALL
- COMMAND ${CMAKE_COMMAND} -DNO_GIT=${WITHOUT_GIT} -DGIT_EXEC=${GIT_EXECUTABLE} -DBUILDDIR=${CMAKE_BINARY_DIR} -P ${CMAKE_SOURCE_DIR}/cmake/genrev.cmake
- WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
+ COMMAND "${CMAKE_COMMAND}" -DBUILDDIR="${CMAKE_BINARY_DIR}" -P "${CMAKE_SOURCE_DIR}/cmake/genrev.cmake" "${CMAKE_BINARY_DIR}"
+ WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
)
diff --git a/src/server/authserver/CMakeLists.txt b/src/server/authserver/CMakeLists.txt
index edd87a5c347..7c76df5d06c 100644
--- a/src/server/authserver/CMakeLists.txt
+++ b/src/server/authserver/CMakeLists.txt
@@ -43,6 +43,8 @@ endif()
include_directories(
${CMAKE_BINARY_DIR}
+ ${CMAKE_SOURCE_DIR}/dep/cppformat
+ ${CMAKE_SOURCE_DIR}/dep/process
${CMAKE_SOURCE_DIR}/src/server/shared
${CMAKE_SOURCE_DIR}/src/server/shared/Configuration
${CMAKE_SOURCE_DIR}/src/server/shared/Database
@@ -53,6 +55,7 @@ include_directories(
${CMAKE_SOURCE_DIR}/src/server/shared/Logging
${CMAKE_SOURCE_DIR}/src/server/shared/Networking
${CMAKE_SOURCE_DIR}/src/server/shared/Threading
+ ${CMAKE_SOURCE_DIR}/src/server/shared/Updater
${CMAKE_SOURCE_DIR}/src/server/shared/Utilities
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/Authentication
@@ -63,6 +66,8 @@ include_directories(
${VALGRIND_INCLUDE_DIR}
)
+GroupSources(${CMAKE_CURRENT_SOURCE_DIR})
+
add_executable(authserver
${authserver_SRCS}
${authserver_PCH_SRC}
@@ -78,6 +83,7 @@ endif()
target_link_libraries(authserver
shared
+ format
${MYSQL_LIBRARY}
${OPENSSL_LIBRARIES}
${CMAKE_THREAD_LIBS_INIT}
diff --git a/src/server/authserver/Main.cpp b/src/server/authserver/Main.cpp
index cd58ec2bf68..c748e9d28a8 100644
--- a/src/server/authserver/Main.cpp
+++ b/src/server/authserver/Main.cpp
@@ -28,14 +28,13 @@
#include "Common.h"
#include "Config.h"
#include "DatabaseEnv.h"
+#include "DatabaseLoader.h"
#include "Log.h"
#include "ProcessPriority.h"
#include "RealmList.h"
#include "SystemConfig.h"
#include "Util.h"
-#include <cstdlib>
#include <iostream>
-#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/program_options.hpp>
#include <openssl/opensslv.h>
#include <openssl/crypto.h>
@@ -150,33 +149,15 @@ bool StartDB()
{
MySQL::Library_Init();
- std::string dbstring = sConfigMgr->GetStringDefault("LoginDatabaseInfo", "");
- if (dbstring.empty())
- {
- TC_LOG_ERROR("server.authserver", "Database not specified");
- return false;
- }
-
- int32 worker_threads = sConfigMgr->GetIntDefault("LoginDatabase.WorkerThreads", 1);
- if (worker_threads < 1 || worker_threads > 32)
- {
- TC_LOG_ERROR("server.authserver", "Improper value specified for LoginDatabase.WorkerThreads, defaulting to 1.");
- worker_threads = 1;
- }
+ // Load databases
+ // NOTE: While authserver is singlethreaded you should keep synch_threads == 1.
+ // Increasing it is just silly since only 1 will be used ever.
+ DatabaseLoader loader("server.authserver", DatabaseLoader::DATABASE_NONE);
+ loader
+ .AddDatabase(LoginDatabase, "Login");
- int32 synch_threads = sConfigMgr->GetIntDefault("LoginDatabase.SynchThreads", 1);
- if (synch_threads < 1 || synch_threads > 32)
- {
- TC_LOG_ERROR("server.authserver", "Improper value specified for LoginDatabase.SynchThreads, defaulting to 1.");
- synch_threads = 1;
- }
-
- // NOTE: While authserver is singlethreaded you should keep synch_threads == 1. Increasing it is just silly since only 1 will be used ever.
- if (!LoginDatabase.Open(dbstring, uint8(worker_threads), uint8(synch_threads)))
- {
- TC_LOG_ERROR("server.authserver", "Cannot connect to database");
+ if (!loader.Load())
return false;
- }
TC_LOG_INFO("server.authserver", "Started auth database connection pool.");
sLog->SetRealmId(0); // Enables DB appenders when realm is set.
diff --git a/src/server/authserver/authserver.conf.dist b/src/server/authserver/authserver.conf.dist
index b7dee9ac08b..ba9cb5b23b4 100644
--- a/src/server/authserver/authserver.conf.dist
+++ b/src/server/authserver/authserver.conf.dist
@@ -9,6 +9,7 @@
# EXAMPLE CONFIG
# AUTH SERVER SETTINGS
# MYSQL SETTINGS
+# UPDATE SETTINGS
# LOGGING SYSTEM SETTINGS
#
###################################################################################################
@@ -158,6 +159,89 @@ Wrong.Password.Login.Logging = 0
###################################################################################################
###################################################################################################
+# UPDATE SETTINGS
+#
+# Updates.EnableDatabases
+# Description: A mask that describes which databases shall be updated.
+#
+# Following flags are available
+# DATABASE_LOGIN = 1, // Auth database
+#
+# Default: 0 - (All Disabled)
+# 1 - (All Enabled)
+
+Updates.EnableDatabases = 0
+
+#
+# Updates.SourcePath
+# Description: The path to your TrinityCore source directory.
+# If the path is left empty, built-in CMAKE_SOURCE_DIR is used.
+# Example: "../TrinityCore"
+# Default: ""
+
+Updates.SourcePath = ""
+
+#
+# Updates.SourcePath
+# Description: The path to your mysql cli binary.
+# If the path is left empty, built-in path from cmake is used.
+# Example: "C:/Program Files/MySQL/MySQL Server 5.6/bin/mysql.exe"
+# "mysql.exe"
+# "/usr/bin/mysql"
+# Default: ""
+
+Updates.MySqlCLIPath = ""
+
+#
+# Updates.AutoSetup
+# Description: Auto populate empty databases.
+# Default: 1 - (Enabled)
+# 0 - (Disabled)
+
+Updates.AutoSetup = 1
+
+#
+# Updates.Redundancy
+# Description: Perform data redundancy checks through hashing
+# to detect changes on sql updates and reapply it.
+# Default: 1 - (Enabled)
+# 0 - (Disabled)
+
+Updates.Redundancy = 1
+
+#
+# Updates.ArchivedRedundancy
+# Description: Check hashes of archived updates (slows down startup).
+# Default: 0 - (Disabled)
+# 1 - (Enabled)
+
+Updates.ArchivedRedundancy = 0
+
+#
+# Updates.AllowRehash
+# Description: Inserts the current file hash in the database if it is left empty.
+# Useful if you want to mark a file as applied but you don't know its hash.
+# Default: 1 - (Enabled)
+# 0 - (Disabled)
+
+Updates.AllowRehash = 1
+
+#
+# Updates.CleanDeadRefMaxCount
+# Description: Cleans dead/ orphaned references that occur if an update was removed or renamed and edited in one step.
+# It only starts the clean up if the count of the missing updates is below or equal the Updates.CleanDeadRefMaxCount value.
+# This way prevents erasing of the update history due to wrong source directory state (maybe wrong branch or bad revision).
+# Disable this if you want to know if the database is in a possible "dirty state".
+# Default: 3 - (Enabled)
+# 0 - (Disabled)
+# -1 - (Enabled - unlimited)
+
+Updates.CleanDeadRefMaxCount = 3
+
+#
+###################################################################################################
+
+###################################################################################################
#
# LOGGING SYSTEM SETTINGS
#
diff --git a/src/server/collision/CMakeLists.txt b/src/server/collision/CMakeLists.txt
index e3c77736d5e..f394fe791be 100644
--- a/src/server/collision/CMakeLists.txt
+++ b/src/server/collision/CMakeLists.txt
@@ -35,6 +35,7 @@ include_directories(
${CMAKE_SOURCE_DIR}/dep/g3dlite/include
${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour
${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour/Include
+ ${CMAKE_SOURCE_DIR}/dep/cppformat
${CMAKE_SOURCE_DIR}/src/server/shared
${CMAKE_SOURCE_DIR}/src/server/shared/Configuration
${CMAKE_SOURCE_DIR}/src/server/shared/Debugging
@@ -79,6 +80,8 @@ include_directories(
${VALGRIND_INCLUDE_DIR}
)
+GroupSources(${CMAKE_CURRENT_SOURCE_DIR})
+
add_library(collision STATIC
${collision_STAT_SRCS}
${collision_STAT_PCH_SRC}
diff --git a/src/server/collision/Management/MMapManager.cpp b/src/server/collision/Management/MMapManager.cpp
index 170350d4de4..847b7bbd001 100644
--- a/src/server/collision/Management/MMapManager.cpp
+++ b/src/server/collision/Management/MMapManager.cpp
@@ -73,7 +73,7 @@ namespace MMAP
delete [] fileName;
- TC_LOG_INFO("maps", "MMAP:loadMapData: Loaded %03i.mmap", mapId);
+ TC_LOG_DEBUG("maps", "MMAP:loadMapData: Loaded %03i.mmap", mapId);
// store inside our map list
MMapData* mmap_data = new MMapData(mesh);
@@ -156,7 +156,7 @@ namespace MMAP
{
mmap->mmapLoadedTiles.insert(std::pair<uint32, dtTileRef>(packedGridPos, tileRef));
++loadedTiles;
- TC_LOG_INFO("maps", "MMAP:loadMap: Loaded mmtile %03i[%02i, %02i] into %03i[%02i, %02i]", mapId, x, y, mapId, header->x, header->y);
+ TC_LOG_DEBUG("maps", "MMAP:loadMap: Loaded mmtile %03i[%02i, %02i] into %03i[%02i, %02i]", mapId, x, y, mapId, header->x, header->y);
return true;
}
else
@@ -205,7 +205,7 @@ namespace MMAP
{
mmap->mmapLoadedTiles.erase(packedGridPos);
--loadedTiles;
- TC_LOG_INFO("maps", "MMAP:unloadMap: Unloaded mmtile %03i[%02i, %02i] from %03i", mapId, x, y, mapId);
+ TC_LOG_DEBUG("maps", "MMAP:unloadMap: Unloaded mmtile %03i[%02i, %02i] from %03i", mapId, x, y, mapId);
return true;
}
@@ -232,13 +232,13 @@ namespace MMAP
else
{
--loadedTiles;
- TC_LOG_INFO("maps", "MMAP:unloadMap: Unloaded mmtile %03i[%02i, %02i] from %03i", mapId, x, y, mapId);
+ TC_LOG_DEBUG("maps", "MMAP:unloadMap: Unloaded mmtile %03i[%02i, %02i] from %03i", mapId, x, y, mapId);
}
}
delete mmap;
loadedMMaps.erase(mapId);
- TC_LOG_INFO("maps", "MMAP:unloadMap: Unloaded %03i.mmap", mapId);
+ TC_LOG_DEBUG("maps", "MMAP:unloadMap: Unloaded %03i.mmap", mapId);
return true;
}
@@ -264,7 +264,7 @@ namespace MMAP
dtFreeNavMeshQuery(query);
mmap->navMeshQueries.erase(instanceId);
- TC_LOG_INFO("maps", "MMAP:unloadMapInstance: Unloaded mapId %03u instanceId %u", mapId, instanceId);
+ TC_LOG_DEBUG("maps", "MMAP:unloadMapInstance: Unloaded mapId %03u instanceId %u", mapId, instanceId);
return true;
}
@@ -295,7 +295,7 @@ namespace MMAP
return NULL;
}
- TC_LOG_INFO("maps", "MMAP:GetNavMeshQuery: created dtNavMeshQuery for mapId %03u instanceId %u", mapId, instanceId);
+ TC_LOG_DEBUG("maps", "MMAP:GetNavMeshQuery: created dtNavMeshQuery for mapId %03u instanceId %u", mapId, instanceId);
mmap->navMeshQueries.insert(std::pair<uint32, dtNavMeshQuery*>(instanceId, query));
}
diff --git a/src/server/collision/Maps/MapTree.cpp b/src/server/collision/Maps/MapTree.cpp
index 72435594ad0..b493ec18f5f 100644
--- a/src/server/collision/Maps/MapTree.cpp
+++ b/src/server/collision/Maps/MapTree.cpp
@@ -386,13 +386,12 @@ namespace VMAP
{
if (!iLoadedSpawns.count(referencedVal))
{
-#ifdef VMAP_DEBUG
if (referencedVal > iNTreeValues)
{
- TC_LOG_DEBUG("maps", "StaticMapTree::LoadMapTile() : invalid tree element (%u/%u)", referencedVal, iNTreeValues);
+ VMAP_ERROR_LOG("maps", "StaticMapTree::LoadMapTile() : invalid tree element (%u/%u) referenced in tile %s", referencedVal, iNTreeValues, tilefile.c_str());
continue;
}
-#endif
+
iTreeValues[referencedVal] = ModelInstance(spawn, model);
iLoadedSpawns[referencedVal] = 1;
}
diff --git a/src/server/collision/Maps/TileAssembler.cpp b/src/server/collision/Maps/TileAssembler.cpp
index ee978211577..ec7b759f975 100644
--- a/src/server/collision/Maps/TileAssembler.cpp
+++ b/src/server/collision/Maps/TileAssembler.cpp
@@ -24,7 +24,6 @@
#include <set>
#include <iomanip>
#include <sstream>
-#include <iomanip>
using G3D::Vector3;
using G3D::AABox;
diff --git a/src/server/collision/Models/GameObjectModel.cpp b/src/server/collision/Models/GameObjectModel.cpp
index 05bd5d360c6..0355d2e848c 100644
--- a/src/server/collision/Models/GameObjectModel.cpp
+++ b/src/server/collision/Models/GameObjectModel.cpp
@@ -24,8 +24,6 @@
#include "GameObjectModel.h"
#include "Log.h"
#include "GameObject.h"
-#include "Creature.h"
-#include "TemporarySummon.h"
#include "Object.h"
#include "DBCStores.h"
#include "World.h"
diff --git a/src/server/collision/Models/ModelInstance.cpp b/src/server/collision/Models/ModelInstance.cpp
index 025352eeb58..45440a99666 100644
--- a/src/server/collision/Models/ModelInstance.cpp
+++ b/src/server/collision/Models/ModelInstance.cpp
@@ -19,7 +19,6 @@
#include "ModelInstance.h"
#include "WorldModel.h"
#include "MapTree.h"
-#include "VMapDefinitions.h"
using G3D::Vector3;
using G3D::Ray;
diff --git a/src/server/collision/Models/WorldModel.cpp b/src/server/collision/Models/WorldModel.cpp
index 3af120045cb..86ab9366c71 100644
--- a/src/server/collision/Models/WorldModel.cpp
+++ b/src/server/collision/Models/WorldModel.cpp
@@ -17,7 +17,6 @@
*/
#include "WorldModel.h"
-#include "ModelInstance.h"
#include "VMapDefinitions.h"
#include "MapTree.h"
diff --git a/src/server/game/AI/CoreAI/GuardAI.cpp b/src/server/game/AI/CoreAI/GuardAI.cpp
index 14e5faaf723..7fd1493cbde 100644
--- a/src/server/game/AI/CoreAI/GuardAI.cpp
+++ b/src/server/game/AI/CoreAI/GuardAI.cpp
@@ -19,9 +19,6 @@
#include "GuardAI.h"
#include "Errors.h"
#include "Player.h"
-#include "ObjectAccessor.h"
-#include "World.h"
-#include "CreatureAIImpl.h"
int GuardAI::Permissible(Creature const* creature)
{
diff --git a/src/server/game/AI/CoreAI/PassiveAI.cpp b/src/server/game/AI/CoreAI/PassiveAI.cpp
index fb16d39dab3..5c482120b21 100644
--- a/src/server/game/AI/CoreAI/PassiveAI.cpp
+++ b/src/server/game/AI/CoreAI/PassiveAI.cpp
@@ -18,7 +18,6 @@
#include "PassiveAI.h"
#include "Creature.h"
-#include "TemporarySummon.h"
PassiveAI::PassiveAI(Creature* c) : CreatureAI(c) { me->SetReactState(REACT_PASSIVE); }
PossessedAI::PossessedAI(Creature* c) : CreatureAI(c) { me->SetReactState(REACT_PASSIVE); }
diff --git a/src/server/game/AI/CoreAI/PetAI.cpp b/src/server/game/AI/CoreAI/PetAI.cpp
index f532e4cd862..abb6126ca2c 100644
--- a/src/server/game/AI/CoreAI/PetAI.cpp
+++ b/src/server/game/AI/CoreAI/PetAI.cpp
@@ -20,12 +20,10 @@
#include "Errors.h"
#include "Pet.h"
#include "Player.h"
-#include "DBCStores.h"
#include "Spell.h"
#include "ObjectAccessor.h"
#include "SpellMgr.h"
#include "Creature.h"
-#include "World.h"
#include "Util.h"
#include "Group.h"
#include "SpellInfo.h"
diff --git a/src/server/game/AI/CoreAI/ReactorAI.cpp b/src/server/game/AI/CoreAI/ReactorAI.cpp
index ebb57038737..9ab86047dc8 100644
--- a/src/server/game/AI/CoreAI/ReactorAI.cpp
+++ b/src/server/game/AI/CoreAI/ReactorAI.cpp
@@ -18,10 +18,6 @@
#include "ByteBuffer.h"
#include "ReactorAI.h"
-#include "Errors.h"
-#include "Log.h"
-#include "ObjectAccessor.h"
-#include "CreatureAIImpl.h"
int ReactorAI::Permissible(const Creature* creature)
{
diff --git a/src/server/game/AI/CoreAI/TotemAI.cpp b/src/server/game/AI/CoreAI/TotemAI.cpp
index 983e212b33c..57e926744e2 100644
--- a/src/server/game/AI/CoreAI/TotemAI.cpp
+++ b/src/server/game/AI/CoreAI/TotemAI.cpp
@@ -19,10 +19,8 @@
#include "TotemAI.h"
#include "Totem.h"
#include "Creature.h"
-#include "DBCStores.h"
#include "ObjectAccessor.h"
#include "SpellMgr.h"
-
#include "GridNotifiers.h"
#include "GridNotifiersImpl.h"
#include "CellImpl.h"
diff --git a/src/server/game/AI/CoreAI/UnitAI.cpp b/src/server/game/AI/CoreAI/UnitAI.cpp
index e7d39d715eb..5aa6ea8ea7a 100644
--- a/src/server/game/AI/CoreAI/UnitAI.cpp
+++ b/src/server/game/AI/CoreAI/UnitAI.cpp
@@ -141,7 +141,7 @@ void UnitAI::DoCast(uint32 spellId)
{
if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId))
{
- bool playerOnly = (spellInfo->AttributesEx3 & SPELL_ATTR3_ONLY_TARGET_PLAYERS) != 0;
+ bool playerOnly = spellInfo->HasAttribute(SPELL_ATTR3_ONLY_TARGET_PLAYERS);
target = SelectTarget(SELECT_TARGET_RANDOM, 0, spellInfo->GetMaxRange(false), playerOnly);
}
break;
@@ -156,7 +156,7 @@ void UnitAI::DoCast(uint32 spellId)
{
if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId))
{
- bool playerOnly = (spellInfo->AttributesEx3 & SPELL_ATTR3_ONLY_TARGET_PLAYERS) != 0;
+ bool playerOnly = spellInfo->HasAttribute(SPELL_ATTR3_ONLY_TARGET_PLAYERS);
float range = spellInfo->GetMaxRange(false);
DefaultTargetSelector targetSelector(me, range, playerOnly, -(int32)spellId);
@@ -213,7 +213,7 @@ void UnitAI::FillAISpellInfo()
if (!spellInfo)
continue;
- if (spellInfo->Attributes & SPELL_ATTR0_CASTABLE_WHILE_DEAD)
+ if (spellInfo->HasAttribute(SPELL_ATTR0_CASTABLE_WHILE_DEAD))
AIInfo->condition = AICOND_DIE;
else if (spellInfo->IsPassive() || spellInfo->GetDuration() == -1)
AIInfo->condition = AICOND_AGGRO;
diff --git a/src/server/game/AI/CreatureAISelector.cpp b/src/server/game/AI/CreatureAISelector.cpp
index 9d025e3c2e2..07bd49bdcc6 100644
--- a/src/server/game/AI/CreatureAISelector.cpp
+++ b/src/server/game/AI/CreatureAISelector.cpp
@@ -21,7 +21,6 @@
#include "PassiveAI.h"
#include "MovementGenerator.h"
-#include "Pet.h"
#include "TemporarySummon.h"
#include "CreatureAIFactory.h"
#include "ScriptMgr.h"
diff --git a/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp b/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp
index b00a24129c3..aa7ec3b847f 100644
--- a/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp
+++ b/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp
@@ -17,14 +17,12 @@
*/
#include "ScriptedCreature.h"
-#include "Item.h"
#include "Spell.h"
#include "GridNotifiers.h"
#include "GridNotifiersImpl.h"
#include "Cell.h"
#include "CellImpl.h"
#include "ObjectMgr.h"
-#include "TemporarySummon.h"
// Spell summary for ScriptedAI::SelectSpell
struct TSpellSummary
@@ -663,3 +661,8 @@ void GetGameObjectListWithEntryInGrid(std::list<GameObject*>& list, WorldObject*
{
source->GetGameObjectListWithEntryInGrid(list, entry, 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 cff628a847e..1a4c3064a59 100644
--- a/src/server/game/AI/ScriptedAI/ScriptedCreature.h
+++ b/src/server/game/AI/ScriptedAI/ScriptedCreature.h
@@ -425,5 +425,6 @@ Creature* GetClosestCreatureWithEntry(WorldObject* source, uint32 entry, float m
GameObject* GetClosestGameObjectWithEntry(WorldObject* source, uint32 entry, float maxSearchRange);
void GetCreatureListWithEntryInGrid(std::list<Creature*>& list, WorldObject* source, uint32 entry, float maxSearchRange);
void GetGameObjectListWithEntryInGrid(std::list<GameObject*>& list, WorldObject* source, uint32 entry, float maxSearchRange);
+void GetPlayerListInGrid(std::list<Player*>& list, WorldObject* source, float maxSearchRange);
#endif // SCRIPTEDCREATURE_H_
diff --git a/src/server/game/AI/SmartScripts/SmartAI.cpp b/src/server/game/AI/SmartScripts/SmartAI.cpp
index 76f08952664..20a7ca05d93 100644
--- a/src/server/game/AI/SmartScripts/SmartAI.cpp
+++ b/src/server/game/AI/SmartScripts/SmartAI.cpp
@@ -21,11 +21,7 @@
#include "GridDefines.h"
#include "GridNotifiers.h"
#include "SpellMgr.h"
-#include "GridNotifiersImpl.h"
#include "Cell.h"
-#include "CellImpl.h"
-#include "InstanceScript.h"
-#include "ScriptedCreature.h"
#include "Group.h"
#include "SmartAI.h"
#include "ScriptMgr.h"
diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp
index e7e5f53f7a2..a5698092d69 100644
--- a/src/server/game/AI/SmartScripts/SmartScript.cpp
+++ b/src/server/game/AI/SmartScripts/SmartScript.cpp
@@ -35,7 +35,6 @@
#include "SmartScript.h"
#include "SpellMgr.h"
#include "Vehicle.h"
-#include "MoveSplineInit.h"
#include "GameEventMgr.h"
SmartScript::SmartScript()
@@ -61,6 +60,7 @@ SmartScript::~SmartScript()
delete itr->second;
delete mTargetStorage;
+ mCounterList.clear();
}
void SmartScript::OnReset()
@@ -77,6 +77,7 @@ void SmartScript::OnReset()
}
ProcessEventsFor(SMART_EVENT_RESET);
mLastInvoker.Clear();
+ mCounterList.clear();
}
void SmartScript::ProcessEventsFor(SMART_EVENT e, Unit* unit, uint32 var0, uint32 var1, bool bvar, const SpellInfo* spell, GameObject* gob)
@@ -1318,6 +1319,11 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
ENSURE_AI(SmartAI, me->AI())->SetSwim(e.action.setSwim.swim != 0);
break;
}
+ case SMART_ACTION_SET_COUNTER:
+ {
+ StoreCounter(e.action.setCounter.counterId, e.action.setCounter.value, e.action.setCounter.reset);
+ break;
+ }
case SMART_ACTION_WP_START:
{
if (!IsSmart())
@@ -3167,7 +3173,7 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui
std::list<Creature*> list;
me->GetCreatureListWithEntryInGrid(list, e.event.distance.entry, (float)e.event.distance.dist);
- if (list.size() > 0)
+ if (!list.empty())
creature = list.front();
}
@@ -3198,7 +3204,7 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui
std::list<GameObject*> list;
me->GetGameObjectListWithEntryInGrid(list, e.event.distance.entry, (float)e.event.distance.dist);
- if (list.size() > 0)
+ if (!list.empty())
gameobject = list.front();
}
@@ -3207,6 +3213,10 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui
break;
}
+ case SMART_EVENT_COUNTER_SET:
+ if (GetCounterId(e.event.counter.id) != 0 && GetCounterValue(e.event.counter.id) == e.event.counter.value)
+ ProcessTimedAction(e, e.event.counter.cooldownMin, e.event.counter.cooldownMax);
+ break;
default:
TC_LOG_ERROR("sql.sql", "SmartScript::ProcessEvent: Unhandled Event type %u", e.GetEventType());
break;
diff --git a/src/server/game/AI/SmartScripts/SmartScript.h b/src/server/game/AI/SmartScripts/SmartScript.h
index ed1c63de207..a3d75f1889b 100644
--- a/src/server/game/AI/SmartScripts/SmartScript.h
+++ b/src/server/game/AI/SmartScripts/SmartScript.h
@@ -145,6 +145,36 @@ class SmartScript
return NULL;
}
+ void StoreCounter(uint32 id, uint32 value, uint32 reset)
+ {
+ CounterMap::const_iterator itr = mCounterList.find(id);
+ if (itr != mCounterList.end())
+ {
+ if (reset == 0)
+ value += GetCounterValue(id);
+ mCounterList.erase(id);
+ }
+
+ mCounterList.insert(std::make_pair(id, value));
+ ProcessEventsFor(SMART_EVENT_COUNTER_SET);
+ }
+
+ uint32 GetCounterId(uint32 id)
+ {
+ CounterMap::iterator itr = mCounterList.find(id);
+ if (itr != mCounterList.end())
+ return itr->first;
+ return 0;
+ }
+
+ uint32 GetCounterValue(uint32 id)
+ {
+ CounterMap::iterator itr = mCounterList.find(id);
+ if (itr != mCounterList.end())
+ return itr->second;
+ return 0;
+ }
+
GameObject* FindGameObjectNear(WorldObject* searchObject, uint32 guid) const
{
GameObject* gameObject = NULL;
@@ -205,6 +235,8 @@ class SmartScript
void SetScript9(SmartScriptHolder& e, uint32 entry);
Unit* GetLastInvoker();
ObjectGuid mLastInvoker;
+ typedef std::unordered_map<uint32, uint32> CounterMap;
+ CounterMap mCounterList;
private:
void IncPhase(int32 p = 1)
diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp
index becc3bd92cd..37187d9b04c 100644
--- a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp
+++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp
@@ -17,18 +17,12 @@
#include "DatabaseEnv.h"
#include "ObjectMgr.h"
-#include "ObjectDefines.h"
#include "GridDefines.h"
#include "GridNotifiers.h"
#include "SpellMgr.h"
-#include "GridNotifiersImpl.h"
#include "Cell.h"
-#include "CellImpl.h"
-#include "InstanceScript.h"
-#include "ScriptedCreature.h"
#include "GameEventMgr.h"
#include "CreatureTextMgr.h"
-#include "SpellMgr.h"
#include "SpellInfo.h"
#include "SmartScriptMgr.h"
@@ -695,6 +689,22 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
return false;
}
break;
+ case SMART_EVENT_COUNTER_SET:
+ if (!IsMinMaxValid(e, e.event.counter.cooldownMin, e.event.counter.cooldownMax))
+ return false;
+
+ if (e.event.counter.id == 0)
+ {
+ TC_LOG_ERROR("sql.sql", "SmartAIMgr: Event SMART_EVENT_COUNTER_SET using invalid counter id %u, skipped.", e.event.counter.id);
+ return false;
+ }
+
+ if (e.event.counter.value == 0)
+ {
+ TC_LOG_ERROR("sql.sql", "SmartAIMgr: Event SMART_EVENT_COUNTER_SET using invalid value %u, skipped.", e.event.counter.value);
+ return false;
+ }
+ break;
case SMART_EVENT_LINK:
case SMART_EVENT_GO_STATE_CHANGED:
case SMART_EVENT_GO_EVENT_INFORM:
@@ -998,6 +1008,20 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
return false;
}
break;
+ case SMART_ACTION_SET_COUNTER:
+ if (e.action.setCounter.counterId == 0)
+ {
+ TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry %d SourceType %u Event %u Action %u uses wrong counterId %u, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.setCounter.counterId);
+ return false;
+ }
+
+ if (e.action.setCounter.value == 0)
+ {
+ TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry %d SourceType %u Event %u Action %u uses wrong value %u, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.setCounter.value);
+ return false;
+ }
+
+ break;
case SMART_ACTION_INSTALL_AI_TEMPLATE:
if (e.action.installTtemplate.id >= SMARTAI_TEMPLATE_END)
{
diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.h b/src/server/game/AI/SmartScripts/SmartScriptMgr.h
index 0ed8542c72a..1f4891d6c24 100644
--- a/src/server/game/AI/SmartScripts/SmartScriptMgr.h
+++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.h
@@ -167,8 +167,9 @@ enum SMART_EVENT
SMART_EVENT_FRIENDLY_HEALTH_PCT = 74, // minHpPct, maxHpPct, repeatMin, repeatMax
SMART_EVENT_DISTANCE_CREATURE = 75, // guid, entry, distance, repeat
SMART_EVENT_DISTANCE_GAMEOBJECT = 76, // guid, entry, distance, repeat
+ SMART_EVENT_COUNTER_SET = 77, // id, value, cooldownMin, cooldownMax
- SMART_EVENT_END = 77
+ SMART_EVENT_END = 78
};
struct SmartEvent
@@ -398,6 +399,14 @@ struct SmartEvent
struct
{
+ uint32 id;
+ uint32 value;
+ uint32 cooldownMin;
+ uint32 cooldownMax;
+ } counter;
+
+ struct
+ {
uint32 param1;
uint32 param2;
uint32 param3;
@@ -479,7 +488,7 @@ enum SMART_ACTION
SMART_ACTION_SET_FLY = 60, // 0/1
SMART_ACTION_SET_SWIM = 61, // 0/1
SMART_ACTION_TELEPORT = 62, // mapID,
- // 63 unused
+ SMART_ACTION_SET_COUNTER = 63, // id, value, reset (0/1)
SMART_ACTION_STORE_TARGET_LIST = 64, // varID,
SMART_ACTION_WP_RESUME = 65, // none
SMART_ACTION_SET_ORIENTATION = 66, //
@@ -824,6 +833,13 @@ struct SmartAction
struct
{
+ uint32 counterId;
+ uint32 value;
+ uint32 reset;
+ } setCounter;
+
+ struct
+ {
uint32 id;
uint32 number;
} storeVar;
@@ -1294,6 +1310,7 @@ const uint32 SmartAIEventMask[SMART_EVENT_END][2] =
{SMART_EVENT_FRIENDLY_HEALTH_PCT, SMART_SCRIPT_TYPE_MASK_CREATURE },
{SMART_EVENT_DISTANCE_CREATURE, SMART_SCRIPT_TYPE_MASK_CREATURE },
{SMART_EVENT_DISTANCE_GAMEOBJECT, SMART_SCRIPT_TYPE_MASK_CREATURE },
+ {SMART_EVENT_COUNTER_SET, SMART_SCRIPT_TYPE_MASK_CREATURE + SMART_SCRIPT_TYPE_MASK_GAMEOBJECT }
};
enum SmartEventFlags
diff --git a/src/server/game/Achievements/AchievementMgr.cpp b/src/server/game/Achievements/AchievementMgr.cpp
index c1fde9f53d3..51106d7cfe1 100644
--- a/src/server/game/Achievements/AchievementMgr.cpp
+++ b/src/server/game/Achievements/AchievementMgr.cpp
@@ -55,6 +55,7 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria)
case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE:
case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE:
case ACHIEVEMENT_CRITERIA_TYPE_WIN_BG:
+ case ACHIEVEMENT_CRITERIA_TYPE_DEATH_IN_DUNGEON:
case ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING:
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST: // only hardcoded list
case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL:
@@ -700,58 +701,100 @@ void AchievementMgr::CheckAllAchievementCriteria()
}
static const uint32 achievIdByArenaSlot[MAX_ARENA_SLOT] = { 1057, 1107, 1108 };
-static const uint32 achievIdForDungeon[][4] =
-{
- // ach_cr_id, is_dungeon, is_raid, is_heroic_dungeon
- { 321, true, true, true },
- { 916, false, true, false },
- { 917, false, true, false },
- { 918, true, false, false },
- { 2219, false, false, true },
- { 0, false, false, false }
-};
/**
* this function will be called whenever the user might have done a criteria relevant action
*/
void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, uint32 miscValue1 /*= 0*/, uint32 miscValue2 /*= 0*/, Unit* unit /*= NULL*/)
{
- TC_LOG_DEBUG("achievement", "AchievementMgr::UpdateAchievementCriteria(%u, %u, %u)", type, miscValue1, miscValue2);
+ if (type >= ACHIEVEMENT_CRITERIA_TYPE_TOTAL)
+ {
+ TC_LOG_DEBUG("achievement", "UpdateAchievementCriteria: Wrong criteria type %u", type);
+ return;
+ }
// disable for gamemasters with GM-mode enabled
if (m_player->IsGameMaster())
+ {
+ TC_LOG_DEBUG("achievement", "UpdateAchievementCriteria: [Player %s GM mode on] %s, %s (%u), %u, %u"
+ , m_player->GetName().c_str(), m_player->GetGUID().ToString().c_str(), AchievementGlobalMgr::GetCriteriaTypeString(type), type, miscValue1, miscValue2);
return;
+ }
+
+ TC_LOG_DEBUG("achievement", "UpdateAchievementCriteria: %s, %s (%u), %u, %u"
+ , m_player->GetGUID().ToString().c_str(), AchievementGlobalMgr::GetCriteriaTypeString(type), type, miscValue1, miscValue2);
AchievementCriteriaEntryList const& achievementCriteriaList = sAchievementMgr->GetAchievementCriteriaByType(type);
- for (AchievementCriteriaEntryList::const_iterator i = achievementCriteriaList.begin(); i != achievementCriteriaList.end(); ++i)
+ for (AchievementCriteriaEntry const* achievementCriteria : achievementCriteriaList)
{
- AchievementCriteriaEntry const* achievementCriteria = (*i);
AchievementEntry const* achievement = sAchievementMgr->GetAchievement(achievementCriteria->referredAchievement);
if (!achievement)
continue;
- if (!CanUpdateCriteria(achievementCriteria, achievement))
+ if (!CanUpdateCriteria(achievementCriteria, achievement, miscValue1, miscValue2, unit))
continue;
switch (type)
{
+ // special cases, db data is checked later
+ case ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA:
+ case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT:
+ case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT:
+ break;
+ default:
+ if (AchievementCriteriaDataSet const* data = sAchievementMgr->GetCriteriaDataSet(achievementCriteria))
+ if (!data->Meets(GetPlayer(), unit, miscValue1))
+ continue;
+ break;
+ }
+
+ switch (type)
+ {
// std. case: increment at 1
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST:
+ case ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP:
+ case ACHIEVEMENT_CRITERIA_TYPE_DEATH:
+ case ACHIEVEMENT_CRITERIA_TYPE_DEATH_IN_DUNGEON:
+ case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE:
+ case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER:
+ case ACHIEVEMENT_CRITERIA_TYPE_DEATHS_FROM:
+ case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET:
+ case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL:
+ case ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE:
+ case ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL_AT_AREA:
+ case ACHIEVEMENT_CRITERIA_TYPE_WIN_ARENA: // This also behaves like ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA
+ case ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL:
+ case ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM:
+ case ACHIEVEMENT_CRITERIA_TYPE_HK_CLASS:
+ case ACHIEVEMENT_CRITERIA_TYPE_HK_RACE:
+ case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE:
+ case ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS:
case ACHIEVEMENT_CRITERIA_TYPE_NUMBER_OF_TALENT_RESETS:
+ case ACHIEVEMENT_CRITERIA_TYPE_USE_GAMEOBJECT:
+ case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2:
+ case ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL:
+ case ACHIEVEMENT_CRITERIA_TYPE_FISH_IN_GAMEOBJECT:
+ case ACHIEVEMENT_CRITERIA_TYPE_ON_LOGIN:
+ case ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL:
case ACHIEVEMENT_CRITERIA_TYPE_LOSE_DUEL:
case ACHIEVEMENT_CRITERIA_TYPE_CREATE_AUCTION:
- case ACHIEVEMENT_CRITERIA_TYPE_WON_AUCTIONS: /* FIXME: for online player only currently */
+ case ACHIEVEMENT_CRITERIA_TYPE_WON_AUCTIONS: /* FIXME: for online player only currently */
+ case ACHIEVEMENT_CRITERIA_TYPE_LOOT_EPIC_ITEM:
+ case ACHIEVEMENT_CRITERIA_TYPE_RECEIVE_EPIC_ITEM:
case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED:
case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED:
case ACHIEVEMENT_CRITERIA_TYPE_QUEST_ABANDONED:
case ACHIEVEMENT_CRITERIA_TYPE_FLIGHT_PATHS_TAKEN:
+ case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2:
case ACHIEVEMENT_CRITERIA_TYPE_ACCEPTED_SUMMONINGS:
case ACHIEVEMENT_CRITERIA_TYPE_USE_LFD_TO_GROUP_WITH_PLAYERS:
- // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
- if (!miscValue1)
- continue;
SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
break;
// std case: increment at miscvalue1
+ case ACHIEVEMENT_CRITERIA_TYPE_WIN_BG:
+ case ACHIEVEMENT_CRITERIA_TYPE_DAMAGE_DONE:
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND:
+ case ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE:
case ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_VENDORS:
case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TALENTS:
case ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD:
@@ -759,14 +802,19 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_AT_BARBER:
case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_MAIL:
case ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY:
- case ACHIEVEMENT_CRITERIA_TYPE_GOLD_EARNED_BY_AUCTIONS:/* FIXME: for online player only currently */
+ case ACHIEVEMENT_CRITERIA_TYPE_GOLD_EARNED_BY_AUCTIONS: /* FIXME: for online player only currently */
case ACHIEVEMENT_CRITERIA_TYPE_TOTAL_DAMAGE_RECEIVED:
case ACHIEVEMENT_CRITERIA_TYPE_TOTAL_HEALING_RECEIVED:
- // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
- if (!miscValue1)
- continue;
SetCriteriaProgress(achievementCriteria, miscValue1, PROGRESS_ACCUMULATE);
break;
+ // std case: increment at miscvalue2
+ case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE:
+ case ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM:
+ case ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM:
+ case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE:
+ case ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE:
+ SetCriteriaProgress(achievementCriteria, miscValue2, PROGRESS_ACCUMULATE);
+ break;
// std case: high value at miscvalue1
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_BID:
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_SOLD: /* FIXME: for online player only currently */
@@ -774,92 +822,27 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_RECEIVED:
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEAL_CAST:
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEALING_RECEIVED:
- // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
- if (!miscValue1)
- continue;
SetCriteriaProgress(achievementCriteria, miscValue1, PROGRESS_HIGHEST);
break;
-
- // specialized cases
- case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST:
- {
- // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
- if (!miscValue1)
- continue;
-
- if (achievement->categoryId == CATEGORY_CHILDRENS_WEEK)
- {
- AchievementCriteriaDataSet const* data = sAchievementMgr->GetCriteriaDataSet(achievementCriteria);
- if (!data || !data->Meets(GetPlayer(), NULL))
- continue;
- }
-
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
- break;
- }
- case ACHIEVEMENT_CRITERIA_TYPE_WIN_BG:
- {
- // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
- if (!miscValue1)
- continue;
- if (achievementCriteria->win_bg.bgMapID != GetPlayer()->GetMapId())
- continue;
-
- // those requirements couldn't be found in the dbc
- AchievementCriteriaDataSet const* data = sAchievementMgr->GetCriteriaDataSet(achievementCriteria);
- if (!data || !data->Meets(GetPlayer(), unit))
- continue;
-
- SetCriteriaProgress(achievementCriteria, miscValue1, PROGRESS_ACCUMULATE);
- break;
- }
- case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE:
- {
- // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
- if (!miscValue1)
- continue;
- if (achievementCriteria->kill_creature.creatureID != miscValue1)
- continue;
-
- // those requirements couldn't be found in the dbc
- AchievementCriteriaDataSet const* data = sAchievementMgr->GetCriteriaDataSet(achievementCriteria);
- if (!data || !data->Meets(GetPlayer(), unit))
- continue;
-
- SetCriteriaProgress(achievementCriteria, miscValue2, PROGRESS_ACCUMULATE);
+ // std. case: set at 1
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST:
+ case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL:
+ case ACHIEVEMENT_CRITERIA_TYPE_EXPLORE_AREA:
+ case ACHIEVEMENT_CRITERIA_TYPE_VISIT_BARBER_SHOP:
+ case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM:
+ case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM:
+ SetCriteriaProgress(achievementCriteria, 1, PROGRESS_SET);
break;
- }
- case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE:
- {
- // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
- if (!miscValue2)
- continue;
-
- // those requirements couldn't be found in the dbc
- AchievementCriteriaDataSet const* data = sAchievementMgr->GetCriteriaDataSet(achievementCriteria);
- if (!data || !data->Meets(GetPlayer(), unit, miscValue1))
- continue;
- SetCriteriaProgress(achievementCriteria, miscValue2, PROGRESS_ACCUMULATE);
- break;
- }
+ // specialized cases
case ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL:
- if (AchievementCriteriaDataSet const* data = sAchievementMgr->GetCriteriaDataSet(achievementCriteria))
- if (!data->Meets(GetPlayer(), unit))
- continue;
SetCriteriaProgress(achievementCriteria, GetPlayer()->getLevel());
break;
case ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL:
- // update at loading or specific skill update
- if (miscValue1 && miscValue1 != achievementCriteria->reach_skill_level.skillID)
- continue;
if (uint32 skillvalue = GetPlayer()->GetBaseSkillValue(achievementCriteria->reach_skill_level.skillID))
SetCriteriaProgress(achievementCriteria, skillvalue);
break;
case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL:
- // update at loading or specific skill update
- if (miscValue1 && miscValue1 != achievementCriteria->learn_skill_level.skillID)
- continue;
if (uint32 maxSkillvalue = GetPlayer()->GetPureMaxSkillValue(achievementCriteria->learn_skill_level.skillID))
SetCriteriaProgress(achievementCriteria, maxSkillvalue);
break;
@@ -868,14 +851,12 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
SetCriteriaProgress(achievementCriteria, 1);
break;
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT:
- {
SetCriteriaProgress(achievementCriteria, GetPlayer()->GetRewardedQuestCount());
break;
- }
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST_DAILY:
{
time_t nextDailyResetTime = sWorld->GetNextDailyQuestsResetTime();
- CriteriaProgress *progress = GetCriteriaProgress(achievementCriteria);
+ CriteriaProgress const* progress = GetCriteriaProgress(achievementCriteria);
if (!miscValue1) // Login case.
{
@@ -904,10 +885,6 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
}
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE:
{
- // speedup for non-login case
- if (miscValue1 && miscValue1 != achievementCriteria->complete_quests_in_zone.zoneID)
- continue;
-
uint32 counter = 0;
const RewardedQuestSet &rewQuests = GetPlayer()->getRewardedQuests();
@@ -920,231 +897,11 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
SetCriteriaProgress(achievementCriteria, counter);
break;
}
- case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND:
- // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
- if (!miscValue1)
- continue;
- if (GetPlayer()->GetMapId() != achievementCriteria->complete_battleground.mapID)
- continue;
- SetCriteriaProgress(achievementCriteria, miscValue1, PROGRESS_ACCUMULATE);
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP:
- // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
- if (!miscValue1)
- continue;
- if (GetPlayer()->GetMapId() != achievementCriteria->death_at_map.mapID)
- continue;
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_DEATH:
- {
- // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
- if (!miscValue1)
- continue;
- // skip wrong arena achievements, if not achievIdByArenaSlot then normal total death counter
- bool notfit = false;
- for (int j = 0; j < MAX_ARENA_SLOT; ++j)
- {
- if (achievIdByArenaSlot[j] == achievement->ID)
- {
- Battleground* bg = GetPlayer()->GetBattleground();
- if (!bg || !bg->isArena() || ArenaTeam::GetSlotByType(bg->GetArenaType()) != j)
- notfit = true;
-
- break;
- }
- }
- if (notfit)
- continue;
-
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
- break;
- }
- case ACHIEVEMENT_CRITERIA_TYPE_DEATH_IN_DUNGEON:
- {
- // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
- if (!miscValue1)
- continue;
-
- Map const* map = GetPlayer()->IsInWorld() ? GetPlayer()->GetMap() : sMapMgr->FindMap(GetPlayer()->GetMapId(), GetPlayer()->GetInstanceId());
- if (!map || !map->IsDungeon())
- continue;
-
- // search case
- bool found = false;
- for (int j = 0; achievIdForDungeon[j][0]; ++j)
- {
- if (achievIdForDungeon[j][0] == achievement->ID)
- {
- if (map->IsRaid())
- {
- // if raid accepted (ignore difficulty)
- if (!achievIdForDungeon[j][2])
- break; // for
- }
- else if (GetPlayer()->GetDungeonDifficulty() == DUNGEON_DIFFICULTY_NORMAL)
- {
- // dungeon in normal mode accepted
- if (!achievIdForDungeon[j][1])
- break; // for
- }
- else
- {
- // dungeon in heroic mode accepted
- if (!achievIdForDungeon[j][3])
- break; // for
- }
-
- found = true;
- break; // for
- }
- }
- if (!found)
- continue;
-
- //FIXME: work only for instances where max == min for players
- if (map->ToInstanceMap()->GetMaxPlayers() != achievementCriteria->death_in_dungeon.manLimit)
- continue;
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
- break;
-
- }
- case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE:
- // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
- if (!miscValue1)
- continue;
- if (miscValue1 != achievementCriteria->killed_by_creature.creatureEntry)
- continue;
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER:
- // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
- if (!miscValue1)
- continue;
-
- // if team check required: must kill by opposition faction
- if (achievement->ID == 318 && miscValue2 == GetPlayer()->GetTeam())
- continue;
-
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
- break;
case ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING:
- {
- // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
- if (!miscValue1)
- continue;
-
- // those requirements couldn't be found in the dbc
- AchievementCriteriaDataSet const* data = sAchievementMgr->GetCriteriaDataSet(achievementCriteria);
- if (!data || !data->Meets(GetPlayer(), unit))
- continue;
-
// miscvalue1 is the ingame fallheight*100 as stored in dbc
SetCriteriaProgress(achievementCriteria, miscValue1);
break;
- }
- case ACHIEVEMENT_CRITERIA_TYPE_DEATHS_FROM:
- // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
- if (!miscValue1)
- continue;
- if (miscValue2 != achievementCriteria->death_from.type)
- continue;
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST:
- {
- // if miscvalues != 0, it contains the questID.
- if (miscValue1)
- {
- if (miscValue1 != achievementCriteria->complete_quest.questID)
- continue;
- }
- else
- {
- // login case.
- if (!GetPlayer()->GetQuestRewardStatus(achievementCriteria->complete_quest.questID))
- continue;
- }
-
- if (AchievementCriteriaDataSet const* data = sAchievementMgr->GetCriteriaDataSet(achievementCriteria))
- if (!data->Meets(GetPlayer(), unit))
- continue;
-
- SetCriteriaProgress(achievementCriteria, 1);
- break;
- }
- case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET:
- case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2:
- {
- if (!miscValue1 || miscValue1 != achievementCriteria->be_spell_target.spellID)
- continue;
-
- // those requirements couldn't be found in the dbc
- AchievementCriteriaDataSet const* data = sAchievementMgr->GetCriteriaDataSet(achievementCriteria);
- if (!data)
- continue;
-
- if (!data->Meets(GetPlayer(), unit))
- continue;
-
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
- break;
- }
- case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL:
- case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2:
- {
- if (!miscValue1 || miscValue1 != achievementCriteria->cast_spell.spellID)
- continue;
-
- // those requirements couldn't be found in the dbc
- AchievementCriteriaDataSet const* data = sAchievementMgr->GetCriteriaDataSet(achievementCriteria);
- if (!data)
- continue;
-
- if (!data->Meets(GetPlayer(), unit))
- continue;
-
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
- break;
- }
- case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL:
- if (miscValue1 && miscValue1 != achievementCriteria->learn_spell.spellID)
- continue;
-
- if (GetPlayer()->HasSpell(achievementCriteria->learn_spell.spellID))
- SetCriteriaProgress(achievementCriteria, 1);
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE:
- {
- // miscvalue1=loot_type (note: 0 = LOOT_CORPSE and then it ignored)
- // miscvalue2=count of item loot
- if (!miscValue1 || !miscValue2)
- continue;
- if (miscValue1 != achievementCriteria->loot_type.lootType)
- continue;
-
- // zone specific
- if (achievementCriteria->loot_type.lootTypeCount == 1)
- {
- // those requirements couldn't be found in the dbc
- AchievementCriteriaDataSet const* data = sAchievementMgr->GetCriteriaDataSet(achievementCriteria);
- if (!data || !data->Meets(GetPlayer(), unit))
- continue;
- }
-
- SetCriteriaProgress(achievementCriteria, miscValue2, PROGRESS_ACCUMULATE);
- break;
- }
- case ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM:
- // speedup for non-login case
- if (miscValue1 && achievementCriteria->own_item.itemID != miscValue1)
- continue;
- SetCriteriaProgress(achievementCriteria, miscValue2, PROGRESS_ACCUMULATE);
- break;
case ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA:
- if (!miscValue1) // no update at login
- continue;
-
// additional requirements
if (achievementCriteria->additionalRequirements[0].additionalRequirement_type == ACHIEVEMENT_CRITERIA_CONDITION_NO_LOSE)
{
@@ -1160,198 +917,36 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
break;
- case ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM:
- // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
- if (!miscValue1)
- continue;
-
- if (achievementCriteria->use_item.itemID != miscValue1)
- continue;
-
- // Children's Week achievements have extra requirements
- if (achievement->categoryId == CATEGORY_CHILDRENS_WEEK)
- {
- AchievementCriteriaDataSet const* data = sAchievementMgr->GetCriteriaDataSet(achievementCriteria);
- if (!data || !data->Meets(GetPlayer(), NULL))
- continue;
- }
-
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM:
- // You _have_ to loot that item, just owning it when logging in does _not_ count!
- if (!miscValue1)
- continue;
- if (miscValue1 != achievementCriteria->own_item.itemID)
- continue;
- SetCriteriaProgress(achievementCriteria, miscValue2, PROGRESS_ACCUMULATE);
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_EXPLORE_AREA:
- {
- WorldMapOverlayEntry const* worldOverlayEntry = sWorldMapOverlayStore.LookupEntry(achievementCriteria->explore_area.areaReference);
- if (!worldOverlayEntry)
- break;
-
- bool matchFound = false;
- for (int j = 0; j < MAX_WORLD_MAP_OVERLAY_AREA_IDX; ++j)
- {
- uint32 area_id = worldOverlayEntry->areatableID[j];
- if (!area_id) // array have 0 only in empty tail
- break;
-
- int32 exploreFlag = GetAreaFlagByAreaID(area_id);
- if (exploreFlag < 0)
- continue;
-
- uint32 playerIndexOffset = uint32(exploreFlag) / 32;
- uint32 mask = 1<< (uint32(exploreFlag) % 32);
-
- if (GetPlayer()->GetUInt32Value(PLAYER_EXPLORED_ZONES_1 + playerIndexOffset) & mask)
- {
- matchFound = true;
- break;
- }
- }
-
- if (matchFound)
- SetCriteriaProgress(achievementCriteria, 1);
- break;
- }
case ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT:
SetCriteriaProgress(achievementCriteria, GetPlayer()->GetBankBagSlotCount());
break;
case ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION:
{
- // skip faction check only at loading
- if (miscValue1 && miscValue1 != achievementCriteria->gain_reputation.factionID)
- continue;
-
int32 reputation = GetPlayer()->GetReputationMgr().GetReputation(achievementCriteria->gain_reputation.factionID);
if (reputation > 0)
SetCriteriaProgress(achievementCriteria, reputation);
break;
}
case ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION:
- {
SetCriteriaProgress(achievementCriteria, GetPlayer()->GetReputationMgr().GetExaltedFactionCount());
break;
- }
- case ACHIEVEMENT_CRITERIA_TYPE_VISIT_BARBER_SHOP:
- {
- // skip for login case
- if (!miscValue1)
- continue;
- SetCriteriaProgress(achievementCriteria, 1);
- break;
- }
- case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM:
- {
- // miscvalue1 = itemid
- // miscvalue2 = itemSlot
- if (!miscValue1)
- continue;
-
- if (miscValue2 != achievementCriteria->equip_epic_item.itemSlot)
- continue;
-
- // check item level and quality via achievement_criteria_data
- AchievementCriteriaDataSet const* data = sAchievementMgr->GetCriteriaDataSet(achievementCriteria);
- if (!data || !data->Meets(GetPlayer(), nullptr, miscValue1))
- continue;
-
- SetCriteriaProgress(achievementCriteria, 1);
- break;
- }
case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT:
case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT:
{
- // miscvalue1 = itemid
- // miscvalue2 = diced value
- if (!miscValue1)
- continue;
- if (miscValue2 != achievementCriteria->roll_greed_on_loot.rollValue)
- continue;
-
- ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(miscValue1);
- if (!pProto)
+ ItemTemplate const* proto = sObjectMgr->GetItemTemplate(miscValue1);
+ if (!proto)
continue;
// check item level via achievement_criteria_data
AchievementCriteriaDataSet const* data = sAchievementMgr->GetCriteriaDataSet(achievementCriteria);
- if (!data || !data->Meets(GetPlayer(), nullptr, pProto->ItemLevel))
- continue;
-
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
- break;
- }
- case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE:
- {
- // miscvalue1 = emote
- if (!miscValue1)
- continue;
- if (miscValue1 != achievementCriteria->do_emote.emoteID)
+ if (!data || !data->Meets(GetPlayer(), nullptr, proto->ItemLevel))
continue;
- if (achievementCriteria->do_emote.count)
- {
- // those requirements couldn't be found in the dbc
- AchievementCriteriaDataSet const* data = sAchievementMgr->GetCriteriaDataSet(achievementCriteria);
- if (!data || !data->Meets(GetPlayer(), unit))
- continue;
- }
SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
break;
}
- case ACHIEVEMENT_CRITERIA_TYPE_DAMAGE_DONE:
- case ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE:
- {
- if (!miscValue1)
- continue;
-
- if (achievementCriteria->additionalRequirements[0].additionalRequirement_type == ACHIEVEMENT_CRITERIA_CONDITION_BG_MAP)
- {
- if (GetPlayer()->GetMapId() != achievementCriteria->additionalRequirements[0].additionalRequirement_value)
- continue;
-
- // map specific case (BG in fact) expected player targeted damage/heal
- if (!unit || unit->GetTypeId() != TYPEID_PLAYER)
- continue;
- }
-
- SetCriteriaProgress(achievementCriteria, miscValue1, PROGRESS_ACCUMULATE);
- break;
- }
- case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM:
- // miscvalue1 = item_id
- if (!miscValue1)
- continue;
- if (miscValue1 != achievementCriteria->equip_item.itemID)
- continue;
-
- SetCriteriaProgress(achievementCriteria, 1);
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_USE_GAMEOBJECT:
- // miscvalue1 = go entry
- if (!miscValue1)
- continue;
- if (miscValue1 != achievementCriteria->use_gameobject.goEntry)
- continue;
-
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_FISH_IN_GAMEOBJECT:
- if (!miscValue1)
- continue;
- if (miscValue1 != achievementCriteria->fish_in_gameobject.goEntry)
- continue;
-
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
- break;
case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS:
{
- if (miscValue1 && miscValue1 != achievementCriteria->learn_skillline_spell.skillLine)
- continue;
-
uint32 spellCount = 0;
for (PlayerSpellMap::const_iterator spellIter = GetPlayer()->GetSpellMap().begin();
spellIter != GetPlayer()->GetSpellMap().end();
@@ -1367,24 +962,6 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
SetCriteriaProgress(achievementCriteria, spellCount);
break;
}
- case ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL:
- // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
- if (!miscValue1)
- continue;
-
- if (achievementCriteria->win_duel.duelCount)
- {
- // those requirements couldn't be found in the dbc
- AchievementCriteriaDataSet const* data = sAchievementMgr->GetCriteriaDataSet(achievementCriteria);
- if (!data)
- continue;
-
- if (!data->Meets(GetPlayer(), unit))
- continue;
- }
-
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
- break;
case ACHIEVEMENT_CRITERIA_TYPE_GAIN_REVERED_REPUTATION:
SetCriteriaProgress(achievementCriteria, GetPlayer()->GetReputationMgr().GetReveredFactionCount());
break;
@@ -1394,23 +971,8 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
case ACHIEVEMENT_CRITERIA_TYPE_KNOWN_FACTIONS:
SetCriteriaProgress(achievementCriteria, GetPlayer()->GetReputationMgr().GetVisibleFactionCount());
break;
- case ACHIEVEMENT_CRITERIA_TYPE_LOOT_EPIC_ITEM:
- case ACHIEVEMENT_CRITERIA_TYPE_RECEIVE_EPIC_ITEM:
- {
- // AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
- if (!miscValue1)
- continue;
- ItemTemplate const* proto = sObjectMgr->GetItemTemplate(miscValue1);
- if (!proto || proto->Quality < ITEM_QUALITY_EPIC)
- continue;
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
- break;
- }
case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LINE:
{
- if (miscValue1 && miscValue1 != achievementCriteria->learn_skill_line.skillLine)
- continue;
-
uint32 spellCount = 0;
for (PlayerSpellMap::const_iterator spellIter = GetPlayer()->GetSpellMap().begin();
spellIter != GetPlayer()->GetSpellMap().end();
@@ -1427,72 +989,21 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
case ACHIEVEMENT_CRITERIA_TYPE_EARN_HONORABLE_KILL:
SetCriteriaProgress(achievementCriteria, GetPlayer()->GetUInt32Value(PLAYER_FIELD_LIFETIME_HONORABLE_KILLS));
break;
- case ACHIEVEMENT_CRITERIA_TYPE_HK_CLASS:
- if (!miscValue1 || miscValue1 != achievementCriteria->hk_class.classID)
- continue;
-
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
- break;
- case ACHIEVEMENT_CRITERIA_TYPE_HK_RACE:
- if (!miscValue1 || miscValue1 != achievementCriteria->hk_race.raceID)
- continue;
-
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
- break;
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_GOLD_VALUE_OWNED:
SetCriteriaProgress(achievementCriteria, GetPlayer()->GetMoney(), PROGRESS_HIGHEST);
break;
case ACHIEVEMENT_CRITERIA_TYPE_EARN_ACHIEVEMENT_POINTS:
- {
if (!miscValue1)
{
uint32 points = 0;
- for (CompletedAchievementMap::iterator itr = m_completedAchievements.begin(); itr != m_completedAchievements.end(); ++itr)
- if (AchievementEntry const* pAchievement = sAchievementMgr->GetAchievement(itr->first))
- points += pAchievement->points;
+ for (CompletedAchievementMap::const_iterator itr = m_completedAchievements.begin(); itr != m_completedAchievements.end(); ++itr)
+ if (AchievementEntry const* completedAchievements = sAchievementMgr->GetAchievement(itr->first))
+ points += completedAchievements->points;
SetCriteriaProgress(achievementCriteria, points, PROGRESS_SET);
}
else
SetCriteriaProgress(achievementCriteria, miscValue1, PROGRESS_ACCUMULATE);
break;
- }
- case ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE:
- {
- if (!miscValue1 || miscValue1 != achievementCriteria->bg_objective.objectiveId)
- continue;
-
- // those requirements couldn't be found in the dbc
- AchievementCriteriaDataSet const* data = sAchievementMgr->GetCriteriaDataSet(achievementCriteria);
- if (!data || !data->Meets(GetPlayer(), unit))
- continue;
-
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
- break;
- }
- case ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL:
- case ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL:
- case ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS:
- {
- // skip login update
- if (!miscValue1)
- continue;
-
- // those requirements couldn't be found in the dbc
- AchievementCriteriaDataSet const* data = sAchievementMgr->GetCriteriaDataSet(achievementCriteria);
- if (!data || !data->Meets(GetPlayer(), unit))
- continue;
-
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
- break;
- }
- case ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL_AT_AREA:
- {
- if (!miscValue1 || miscValue1 != achievementCriteria->honorable_kill_at_area.areaID)
- continue;
-
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
- break;
- }
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_TEAM_RATING:
{
uint32 reqTeamType = achievementCriteria->highest_team_rating.teamtype;
@@ -1504,7 +1015,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
SetCriteriaProgress(achievementCriteria, miscValue1, PROGRESS_HIGHEST);
}
- else // login case
+ else // login case
{
for (uint32 arena_slot = 0; arena_slot < MAX_ARENA_SLOT; ++arena_slot)
{
@@ -1520,7 +1031,6 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
break;
}
}
-
break;
}
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_PERSONAL_RATING:
@@ -1534,7 +1044,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
SetCriteriaProgress(achievementCriteria, miscValue1, PROGRESS_HIGHEST);
}
- else // login case
+ else // login case
{
for (uint32 arena_slot = 0; arena_slot < MAX_ARENA_SLOT; ++arena_slot)
{
@@ -1556,27 +1066,6 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
break;
}
- case ACHIEVEMENT_CRITERIA_TYPE_WIN_ARENA: // This also behaves like ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA
- {
- // Check map id requirement
- if (miscValue1 == achievementCriteria->win_arena.mapID)
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
- break;
- }
- case ACHIEVEMENT_CRITERIA_TYPE_ON_LOGIN:
- {
- // This criteria is only called directly after login - with expected miscvalue1 == 1
- if (!miscValue1)
- continue;
-
- // They have no proper requirements in dbc
- AchievementCriteriaDataSet const* data = sAchievementMgr->GetCriteriaDataSet(achievementCriteria);
- if (!data || !data->Meets(GetPlayer(), unit))
- continue;
-
- SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
- break;
- }
// std case: not exist in DBC, not triggered in code as result
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEALTH:
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_SPELLPOWER:
@@ -2019,7 +1508,7 @@ void AchievementMgr::CompletedAchievement(AchievementEntry const* achievement)
if (achievement->flags & ACHIEVEMENT_FLAG_COUNTER || HasAchieved(achievement->ID))
return;
- TC_LOG_INFO("achievement", "AchievementMgr::CompletedAchievement(%u). Player: %s (%u)",
+ TC_LOG_DEBUG("achievement", "AchievementMgr::CompletedAchievement(%u). Player: %s (%u)",
achievement->ID, m_player->GetName().c_str(), m_player->GetGUIDLow());
SendAchievementEarned(achievement);
@@ -2140,18 +1629,53 @@ bool AchievementMgr::HasAchieved(uint32 achievementId) const
return m_completedAchievements.find(achievementId) != m_completedAchievements.end();
}
-bool AchievementMgr::CanUpdateCriteria(AchievementCriteriaEntry const* criteria, AchievementEntry const* achievement)
+bool AchievementMgr::CanUpdateCriteria(AchievementCriteriaEntry const* criteria, AchievementEntry const* achievement, uint32 miscValue1, uint32 miscValue2, Unit const* unit)
{
- if (DisableMgr::IsDisabledFor(DISABLE_TYPE_ACHIEVEMENT_CRITERIA, criteria->ID, NULL))
+ if (DisableMgr::IsDisabledFor(DISABLE_TYPE_ACHIEVEMENT_CRITERIA, criteria->ID, nullptr))
+ {
+ TC_LOG_TRACE("achievement", "CanUpdateCriteria: (Id: %u Type %s) Disabled",
+ criteria->ID, AchievementGlobalMgr::GetCriteriaTypeString(criteria->requiredType));
return false;
+ }
if (achievement->mapID != -1 && GetPlayer()->GetMapId() != uint32(achievement->mapID))
+ {
+ TC_LOG_TRACE("achievement", "CanUpdateCriteria: (Id: %u Type %s Achievement %u) Wrong map",
+ criteria->ID, AchievementGlobalMgr::GetCriteriaTypeString(criteria->requiredType), achievement->ID);
return false;
+ }
if ((achievement->requiredFaction == ACHIEVEMENT_FACTION_HORDE && GetPlayer()->GetTeam() != HORDE) ||
(achievement->requiredFaction == ACHIEVEMENT_FACTION_ALLIANCE && GetPlayer()->GetTeam() != ALLIANCE))
+ {
+ TC_LOG_TRACE("achievement", "CanUpdateCriteria: (Id: %u Type %s Achievement %u) Wrong faction",
+ criteria->ID, AchievementGlobalMgr::GetCriteriaTypeString(criteria->requiredType), achievement->ID);
return false;
+ }
+
+ if (!RequirementsSatisfied(criteria, achievement, miscValue1, miscValue2, unit))
+ {
+ TC_LOG_TRACE("achievement", "CanUpdateCriteria: (Id: %u Type %s) Requirements not satisfied",
+ criteria->ID, AchievementGlobalMgr::GetCriteriaTypeString(criteria->requiredType));
+ return false;
+ }
+ if (!ConditionsSatisfied(criteria))
+ {
+ TC_LOG_TRACE("achievement", "CanUpdateCriteria: (Id: %u Type %s) Conditions not satisfied",
+ criteria->ID, AchievementGlobalMgr::GetCriteriaTypeString(criteria->requiredType));
+ return false;
+ }
+
+ // don't update already completed criteria
+ if (IsCompletedCriteria(criteria, achievement))
+ return false;
+
+ return true;
+}
+
+bool AchievementMgr::ConditionsSatisfied(AchievementCriteriaEntry const* criteria) const
+{
for (uint32 i = 0; i < MAX_CRITERIA_REQUIREMENTS; ++i)
{
if (!criteria->additionalRequirements[i].additionalRequirement_type)
@@ -2172,13 +1696,558 @@ bool AchievementMgr::CanUpdateCriteria(AchievementCriteriaEntry const* criteria,
}
}
- // don't update already completed criteria
- if (IsCompletedCriteria(criteria, achievement))
- return false;
+ return true;
+}
+
+bool AchievementMgr::RequirementsSatisfied(AchievementCriteriaEntry const* achievementCriteria, AchievementEntry const* achievement, uint32 miscValue1, uint32 miscValue2, Unit const* unit) const
+{
+ switch (AchievementCriteriaTypes(achievementCriteria->requiredType))
+ {
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST:
+ case ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING:
+ case ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL:
+ case ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA:
+ case ACHIEVEMENT_CRITERIA_TYPE_VISIT_BARBER_SHOP:
+ case ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS:
+ case ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_VENDORS:
+ case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TALENTS:
+ case ACHIEVEMENT_CRITERIA_TYPE_NUMBER_OF_TALENT_RESETS:
+ case ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD:
+ case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TRAVELLING:
+ case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_AT_BARBER:
+ case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_MAIL:
+ case ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY:
+ case ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL:
+ case ACHIEVEMENT_CRITERIA_TYPE_ON_LOGIN:
+ case ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL:
+ case ACHIEVEMENT_CRITERIA_TYPE_LOSE_DUEL:
+ case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE:
+ case ACHIEVEMENT_CRITERIA_TYPE_GOLD_EARNED_BY_AUCTIONS:
+ case ACHIEVEMENT_CRITERIA_TYPE_CREATE_AUCTION:
+ case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_BID:
+ case ACHIEVEMENT_CRITERIA_TYPE_WON_AUCTIONS:
+ case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_SOLD:
+ case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED:
+ case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED:
+ case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_DEALT:
+ case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_RECEIVED:
+ case ACHIEVEMENT_CRITERIA_TYPE_TOTAL_DAMAGE_RECEIVED:
+ case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEAL_CAST:
+ case ACHIEVEMENT_CRITERIA_TYPE_TOTAL_HEALING_RECEIVED:
+ case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEALING_RECEIVED:
+ case ACHIEVEMENT_CRITERIA_TYPE_QUEST_ABANDONED:
+ case ACHIEVEMENT_CRITERIA_TYPE_FLIGHT_PATHS_TAKEN:
+ case ACHIEVEMENT_CRITERIA_TYPE_ACCEPTED_SUMMONINGS:
+ case ACHIEVEMENT_CRITERIA_TYPE_USE_LFD_TO_GROUP_WITH_PLAYERS:
+ if (!miscValue1)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL:
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT:
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT:
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST_DAILY:
+ case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_TEAM_RATING:
+ case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_PERSONAL_RATING:
+ case ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT:
+ case ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION:
+ case ACHIEVEMENT_CRITERIA_TYPE_GAIN_REVERED_REPUTATION:
+ case ACHIEVEMENT_CRITERIA_TYPE_GAIN_HONORED_REPUTATION:
+ case ACHIEVEMENT_CRITERIA_TYPE_KNOWN_FACTIONS:
+ case ACHIEVEMENT_CRITERIA_TYPE_EARN_HONORABLE_KILL:
+ case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_GOLD_VALUE_OWNED:
+ case ACHIEVEMENT_CRITERIA_TYPE_EARN_ACHIEVEMENT_POINTS:
+ break;
+
+ // specialized cases
+ case ACHIEVEMENT_CRITERIA_TYPE_WIN_BG:
+ if (!miscValue1)
+ return false;
+ if (achievementCriteria->win_bg.bgMapID != GetPlayer()->GetMapId())
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE:
+ if (!miscValue1)
+ return false;
+ if (achievementCriteria->kill_creature.creatureID != miscValue1)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL:
+ if (miscValue1 && miscValue1 != achievementCriteria->reach_skill_level.skillID)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL:
+ if (miscValue1 && miscValue1 != achievementCriteria->learn_skill_level.skillID)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE:
+ if (miscValue1 && miscValue1 != achievementCriteria->complete_quests_in_zone.zoneID)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND:
+ if (!miscValue1)
+ return false;
+ if (GetPlayer()->GetMapId() != achievementCriteria->complete_battleground.mapID)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP:
+ if (!miscValue1)
+ return false;
+ if (GetPlayer()->GetMapId() != achievementCriteria->death_at_map.mapID)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_DEATH:
+ if (!miscValue1)
+ return false;
+ for (uint8 j = 0; j < MAX_ARENA_SLOT; ++j)
+ {
+ if (achievIdByArenaSlot[j] == achievement->ID)
+ {
+ Battleground* bg = GetPlayer()->GetBattleground();
+ if (!bg || !bg->isArena() || ArenaTeam::GetSlotByType(bg->GetArenaType()) != j)
+ return false;
+ break;
+ }
+ }
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_DEATH_IN_DUNGEON:
+ {
+ if (!miscValue1)
+ return false;
+
+ Map const* map = GetPlayer()->IsInWorld() ? GetPlayer()->GetMap() : sMapMgr->FindMap(GetPlayer()->GetMapId(), GetPlayer()->GetInstanceId());
+ if (!map || !map->IsDungeon())
+ return false;
+
+ //FIXME: work only for instances where max == min for players
+ if (map->ToInstanceMap()->GetMaxPlayers() != achievementCriteria->death_in_dungeon.manLimit)
+ return false;
+ break;
+ }
+ case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE:
+ if (!miscValue1)
+ return false;
+ if (miscValue1 != achievementCriteria->killed_by_creature.creatureEntry)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER:
+ if (!miscValue1)
+ return false;
+ // if team check required: must kill by opposition faction
+ if (achievement->ID == 318 && miscValue2 == GetPlayer()->GetTeam())
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_DEATHS_FROM:
+ if (!miscValue1)
+ return false;
+ if (miscValue2 != achievementCriteria->death_from.type)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST:
+ // if miscvalues != 0, it contains the questID.
+ if (miscValue1)
+ {
+ if (miscValue1 != achievementCriteria->complete_quest.questID)
+ return false;
+ }
+ else
+ {
+ // login case.
+ if (!GetPlayer()->GetQuestRewardStatus(achievementCriteria->complete_quest.questID))
+ return false;
+ }
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET:
+ case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2:
+ if (!miscValue1 || miscValue1 != achievementCriteria->be_spell_target.spellID)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL:
+ case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2:
+ if (!miscValue1 || miscValue1 != achievementCriteria->cast_spell.spellID)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL:
+ if (miscValue1 && miscValue1 != achievementCriteria->learn_spell.spellID)
+ return false;
+ if (!GetPlayer()->HasSpell(achievementCriteria->learn_spell.spellID))
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE:
+ // miscvalue1=loot_type (note: 0 = LOOT_CORPSE and then it ignored)
+ // miscvalue2=count of item loot
+ if (!miscValue1 || !miscValue2)
+ return false;
+ if (miscValue1 != achievementCriteria->loot_type.lootType)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM:
+ if (miscValue1 && achievementCriteria->own_item.itemID != miscValue1)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM:
+ if (!miscValue1)
+ return false;
+ if (achievementCriteria->use_item.itemID != miscValue1)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM:
+ if (!miscValue1)
+ return false;
+ if (miscValue1 != achievementCriteria->own_item.itemID)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_EXPLORE_AREA:
+ {
+ WorldMapOverlayEntry const* worldOverlayEntry = sWorldMapOverlayStore.LookupEntry(achievementCriteria->explore_area.areaReference);
+ if (!worldOverlayEntry)
+ return false;
+
+ bool matchFound = false;
+ for (int j = 0; j < MAX_WORLD_MAP_OVERLAY_AREA_IDX; ++j)
+ {
+ uint32 area_id = worldOverlayEntry->areatableID[j];
+ if (!area_id) // array have 0 only in empty tail
+ break;
+
+ int32 exploreFlag = GetAreaFlagByAreaID(area_id);
+ if (exploreFlag < 0)
+ continue;
+
+ uint32 playerIndexOffset = uint32(exploreFlag) / 32;
+ uint32 mask = 1 << (uint32(exploreFlag) % 32);
+
+ if (GetPlayer()->GetUInt32Value(PLAYER_EXPLORED_ZONES_1 + playerIndexOffset) & mask)
+ {
+ matchFound = true;
+ break;
+ }
+ }
+
+ if (!matchFound)
+ return false;
+ break;
+ }
+ case ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION:
+ if (miscValue1 && miscValue1 != achievementCriteria->gain_reputation.factionID)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM:
+ // miscvalue1 = itemid
+ // miscvalue2 = itemSlot
+ if (!miscValue1)
+ return false;
+ if (miscValue2 != achievementCriteria->equip_epic_item.itemSlot)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT:
+ case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT:
+ // miscvalue1 = itemid
+ // miscvalue2 = diced value
+ if (!miscValue1)
+ return false;
+ if (miscValue2 != achievementCriteria->roll_greed_on_loot.rollValue)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE:
+ // miscvalue1 = emote
+ if (!miscValue1)
+ return false;
+ if (miscValue1 != achievementCriteria->do_emote.emoteID)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_DAMAGE_DONE:
+ case ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE:
+ if (!miscValue1)
+ return false;
+
+ if (achievementCriteria->additionalRequirements[0].additionalRequirement_type == ACHIEVEMENT_CRITERIA_CONDITION_BG_MAP)
+ {
+ if (GetPlayer()->GetMapId() != achievementCriteria->additionalRequirements[0].additionalRequirement_value)
+ return false;
+
+ // map specific case (BG in fact) expected player targeted damage/heal
+ if (!unit || unit->GetTypeId() != TYPEID_PLAYER)
+ return false;
+ }
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM:
+ if (!miscValue1)
+ return false;
+ if (miscValue1 != achievementCriteria->equip_item.itemID)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_USE_GAMEOBJECT:
+ if (!miscValue1)
+ return false;
+ if (miscValue1 != achievementCriteria->use_gameobject.goEntry)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_FISH_IN_GAMEOBJECT:
+ if (!miscValue1)
+ return false;
+ if (miscValue1 != achievementCriteria->fish_in_gameobject.goEntry)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS:
+ if (miscValue1 && miscValue1 != achievementCriteria->learn_skillline_spell.skillLine)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_LOOT_EPIC_ITEM:
+ case ACHIEVEMENT_CRITERIA_TYPE_RECEIVE_EPIC_ITEM:
+ {
+ if (!miscValue1)
+ return false;
+ ItemTemplate const* proto = sObjectMgr->GetItemTemplate(miscValue1);
+ if (!proto || proto->Quality < ITEM_QUALITY_EPIC)
+ return false;
+ break;
+ }
+ case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LINE:
+ if (miscValue1 && miscValue1 != achievementCriteria->learn_skill_line.skillLine)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_HK_CLASS:
+ if (!miscValue1 || miscValue1 != achievementCriteria->hk_class.classID)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_HK_RACE:
+ if (!miscValue1 || miscValue1 != achievementCriteria->hk_race.raceID)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE:
+ if (!miscValue1 || miscValue1 != achievementCriteria->bg_objective.objectiveId)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL_AT_AREA:
+ if (!miscValue1 || miscValue1 != achievementCriteria->honorable_kill_at_area.areaID)
+ return false;
+ break;
+ case ACHIEVEMENT_CRITERIA_TYPE_WIN_ARENA:
+ if (miscValue1 != achievementCriteria->win_arena.mapID)
+ return false;
+ break;
+ default:
+ break;
+ }
return true;
}
+char const* AchievementGlobalMgr::GetCriteriaTypeString(uint32 type)
+{
+ return GetCriteriaTypeString(AchievementCriteriaTypes(type));
+}
+
+char const* AchievementGlobalMgr::GetCriteriaTypeString(AchievementCriteriaTypes type)
+{
+ switch (type)
+ {
+ case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE:
+ return "KILL_CREATURE";
+ case ACHIEVEMENT_CRITERIA_TYPE_WIN_BG:
+ return "TYPE_WIN_BG";
+ case ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL:
+ return "REACH_LEVEL";
+ case ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL:
+ return "REACH_SKILL_LEVEL";
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT:
+ return "COMPLETE_ACHIEVEMENT";
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT:
+ return "COMPLETE_QUEST_COUNT";
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST_DAILY:
+ return "COMPLETE_DAILY_QUEST_DAILY";
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE:
+ return "COMPLETE_QUESTS_IN_ZONE";
+ case ACHIEVEMENT_CRITERIA_TYPE_DAMAGE_DONE:
+ return "DAMAGE_DONE";
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST:
+ return "COMPLETE_DAILY_QUEST";
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND:
+ return "COMPLETE_BATTLEGROUND";
+ case ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP:
+ return "DEATH_AT_MAP";
+ case ACHIEVEMENT_CRITERIA_TYPE_DEATH:
+ return "DEATH";
+ case ACHIEVEMENT_CRITERIA_TYPE_DEATH_IN_DUNGEON:
+ return "DEATH_IN_DUNGEON";
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_RAID:
+ return "COMPLETE_RAID";
+ case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE:
+ return "KILLED_BY_CREATURE";
+ case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER:
+ return "KILLED_BY_PLAYER";
+ case ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING:
+ return "FALL_WITHOUT_DYING";
+ case ACHIEVEMENT_CRITERIA_TYPE_DEATHS_FROM:
+ return "DEATHS_FROM";
+ case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST:
+ return "COMPLETE_QUEST";
+ case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET:
+ return "BE_SPELL_TARGET";
+ case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL:
+ return "CAST_SPELL";
+ case ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE:
+ return "BG_OBJECTIVE_CAPTURE";
+ case ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL_AT_AREA:
+ return "HONORABLE_KILL_AT_AREA";
+ case ACHIEVEMENT_CRITERIA_TYPE_WIN_ARENA:
+ return "WIN_ARENA";
+ case ACHIEVEMENT_CRITERIA_TYPE_PLAY_ARENA:
+ return "PLAY_ARENA";
+ case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL:
+ return "LEARN_SPELL";
+ case ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL:
+ return "HONORABLE_KILL";
+ case ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM:
+ return "OWN_ITEM";
+ case ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA:
+ return "WIN_RATED_ARENA";
+ case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_TEAM_RATING:
+ return "HIGHEST_TEAM_RATING";
+ case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_PERSONAL_RATING:
+ return "HIGHEST_PERSONAL_RATING";
+ case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL:
+ return "LEARN_SKILL_LEVEL";
+ case ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM:
+ return "USE_ITEM";
+ case ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM:
+ return "LOOT_ITEM";
+ case ACHIEVEMENT_CRITERIA_TYPE_EXPLORE_AREA:
+ return "EXPLORE_AREA";
+ case ACHIEVEMENT_CRITERIA_TYPE_OWN_RANK:
+ return "OWN_RANK";
+ case ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT:
+ return "BUY_BANK_SLOT";
+ case ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION:
+ return "GAIN_REPUTATION";
+ case ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION:
+ return "GAIN_EXALTED_REPUTATION";
+ case ACHIEVEMENT_CRITERIA_TYPE_VISIT_BARBER_SHOP:
+ return "VISIT_BARBER_SHOP";
+ case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM:
+ return "EQUIP_EPIC_ITEM";
+ case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT:
+ return "ROLL_NEED_ON_LOOT";
+ case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT:
+ return "GREED_ON_LOOT";
+ case ACHIEVEMENT_CRITERIA_TYPE_HK_CLASS:
+ return "HK_CLASS";
+ case ACHIEVEMENT_CRITERIA_TYPE_HK_RACE:
+ return "HK_RACE";
+ case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE:
+ return "DO_EMOTE";
+ case ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE:
+ return "HEALING_DONE";
+ case ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS:
+ return "GET_KILLING_BLOWS";
+ case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM:
+ return "EQUIP_ITEM";
+ case ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_VENDORS:
+ return "MONEY_FROM_VENDORS";
+ case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TALENTS:
+ return "GOLD_SPENT_FOR_TALENTS";
+ case ACHIEVEMENT_CRITERIA_TYPE_NUMBER_OF_TALENT_RESETS:
+ return "NUMBER_OF_TALENT_RESETS";
+ case ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD:
+ return "MONEY_FROM_QUEST_REWARD";
+ case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TRAVELLING:
+ return "GOLD_SPENT_FOR_TRAVELLING";
+ case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_AT_BARBER:
+ return "GOLD_SPENT_AT_BARBER";
+ case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_MAIL:
+ return "GOLD_SPENT_FOR_MAIL";
+ case ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY:
+ return "LOOT_MONEY";
+ case ACHIEVEMENT_CRITERIA_TYPE_USE_GAMEOBJECT:
+ return "USE_GAMEOBJECT";
+ case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2:
+ return "BE_SPELL_TARGET2";
+ case ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL:
+ return "SPECIAL_PVP_KILL";
+ case ACHIEVEMENT_CRITERIA_TYPE_FISH_IN_GAMEOBJECT:
+ return "FISH_IN_GAMEOBJECT";
+ case ACHIEVEMENT_CRITERIA_TYPE_ON_LOGIN:
+ return "ON_LOGIN";
+ case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS:
+ return "LEARN_SKILLLINE_SPELLS";
+ case ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL:
+ return "WIN_DUEL";
+ case ACHIEVEMENT_CRITERIA_TYPE_LOSE_DUEL:
+ return "LOSE_DUEL";
+ case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE:
+ return "KILL_CREATURE_TYPE";
+ case ACHIEVEMENT_CRITERIA_TYPE_GOLD_EARNED_BY_AUCTIONS:
+ return "GOLD_EARNED_BY_AUCTIONS";
+ case ACHIEVEMENT_CRITERIA_TYPE_CREATE_AUCTION:
+ return "CREATE_AUCTION";
+ case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_BID:
+ return "HIGHEST_AUCTION_BID";
+ case ACHIEVEMENT_CRITERIA_TYPE_WON_AUCTIONS:
+ return "WON_AUCTIONS";
+ case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_SOLD:
+ return "HIGHEST_AUCTION_SOLD";
+ case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_GOLD_VALUE_OWNED:
+ return "HIGHEST_GOLD_VALUE_OWNED";
+ case ACHIEVEMENT_CRITERIA_TYPE_GAIN_REVERED_REPUTATION:
+ return "GAIN_REVERED_REPUTATION";
+ case ACHIEVEMENT_CRITERIA_TYPE_GAIN_HONORED_REPUTATION:
+ return "GAIN_HONORED_REPUTATION";
+ case ACHIEVEMENT_CRITERIA_TYPE_KNOWN_FACTIONS:
+ return "KNOWN_FACTIONS";
+ case ACHIEVEMENT_CRITERIA_TYPE_LOOT_EPIC_ITEM:
+ return "LOOT_EPIC_ITEM";
+ case ACHIEVEMENT_CRITERIA_TYPE_RECEIVE_EPIC_ITEM:
+ return "RECEIVE_EPIC_ITEM";
+ case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED:
+ return "ROLL_NEED";
+ case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED:
+ return "ROLL_GREED";
+ case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEALTH:
+ return "HIGHEST_HEALTH";
+ case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_POWER:
+ return "HIGHEST_POWER";
+ case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_STAT:
+ return "HIGHEST_STAT";
+ case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_SPELLPOWER:
+ return "HIGHEST_SPELLPOWER";
+ case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_ARMOR:
+ return "HIGHEST_ARMOR";
+ case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_RATING:
+ return "HIGHEST_RATING";
+ case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_DEALT:
+ return "HIT_DEALT";
+ case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_RECEIVED:
+ return "HIT_RECEIVED";
+ case ACHIEVEMENT_CRITERIA_TYPE_TOTAL_DAMAGE_RECEIVED:
+ return "TOTAL_DAMAGE_RECEIVED";
+ case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEAL_CAST:
+ return "HIGHEST_HEAL_CAST";
+ case ACHIEVEMENT_CRITERIA_TYPE_TOTAL_HEALING_RECEIVED:
+ return "TOTAL_HEALING_RECEIVED";
+ case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEALING_RECEIVED:
+ return "HIGHEST_HEALING_RECEIVED";
+ case ACHIEVEMENT_CRITERIA_TYPE_QUEST_ABANDONED:
+ return "QUEST_ABANDONED";
+ case ACHIEVEMENT_CRITERIA_TYPE_FLIGHT_PATHS_TAKEN:
+ return "FLIGHT_PATHS_TAKEN";
+ case ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE:
+ return "LOOT_TYPE";
+ case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2:
+ return "CAST_SPELL2";
+ case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LINE:
+ return "LEARN_SKILL_LINE";
+ case ACHIEVEMENT_CRITERIA_TYPE_EARN_HONORABLE_KILL:
+ return "EARN_HONORABLE_KILL";
+ case ACHIEVEMENT_CRITERIA_TYPE_ACCEPTED_SUMMONINGS:
+ return "ACCEPTED_SUMMONINGS";
+ case ACHIEVEMENT_CRITERIA_TYPE_EARN_ACHIEVEMENT_POINTS:
+ return "EARN_ACHIEVEMENT_POINTS";
+ case ACHIEVEMENT_CRITERIA_TYPE_USE_LFD_TO_GROUP_WITH_PLAYERS:
+ return "USE_LFD_TO_GROUP_WITH_PLAYERS";
+ }
+ return "MISSING_TYPE";
+}
+
//==========================================================
void AchievementGlobalMgr::LoadAchievementCriteriaList()
{
@@ -2357,7 +2426,7 @@ void AchievementGlobalMgr::LoadAchievementCriteriaData()
AchievementEntry const* achievement = sAchievementMgr->GetAchievement(criteria->referredAchievement);
if (!achievement)
continue;
- if (achievement->categoryId != CATEGORY_CHILDRENS_WEEK)
+ if (achievement->categoryId != CATEGORY_CHILDRENS_WEEK && achievement->ID != 1785)
continue;
break;
}
diff --git a/src/server/game/Achievements/AchievementMgr.h b/src/server/game/Achievements/AchievementMgr.h
index f8869757e50..078229ea4c8 100644
--- a/src/server/game/Achievements/AchievementMgr.h
+++ b/src/server/game/Achievements/AchievementMgr.h
@@ -293,9 +293,12 @@ class AchievementMgr
void CompletedCriteriaFor(AchievementEntry const* achievement);
bool IsCompletedCriteria(AchievementCriteriaEntry const* achievementCriteria, AchievementEntry const* achievement);
bool IsCompletedAchievement(AchievementEntry const* entry);
- bool CanUpdateCriteria(AchievementCriteriaEntry const* criteria, AchievementEntry const* achievement);
+ bool CanUpdateCriteria(AchievementCriteriaEntry const* criteria, AchievementEntry const* achievement, uint32 miscValue1, uint32 miscValue2, Unit const* unit);
void BuildAllDataPacket(WorldPacket* data) const;
+ bool ConditionsSatisfied(AchievementCriteriaEntry const* criteria) const;
+ bool RequirementsSatisfied(AchievementCriteriaEntry const* criteria, AchievementEntry const* achievement, uint32 miscValue1, uint32 miscValue2, Unit const* unit) const;
+
Player* m_player;
CriteriaProgressMap m_criteriaProgress;
CompletedAchievementMap m_completedAchievements;
@@ -309,6 +312,9 @@ class AchievementGlobalMgr
~AchievementGlobalMgr() { }
public:
+ static char const* GetCriteriaTypeString(AchievementCriteriaTypes type);
+ static char const* GetCriteriaTypeString(uint32 type);
+
static AchievementGlobalMgr* instance()
{
static AchievementGlobalMgr instance;
diff --git a/src/server/game/AuctionHouse/AuctionHouseMgr.cpp b/src/server/game/AuctionHouse/AuctionHouseMgr.cpp
index ac2ceb78346..16d5f4b6959 100644
--- a/src/server/game/AuctionHouse/AuctionHouseMgr.cpp
+++ b/src/server/game/AuctionHouse/AuctionHouseMgr.cpp
@@ -30,7 +30,6 @@
#include "Item.h"
#include "Language.h"
#include "Log.h"
-#include <vector>
enum eAuctionHouse
{
@@ -440,8 +439,6 @@ bool AuctionHouseObject::RemoveAuction(AuctionEntry* auction)
// we need to delete the entry, it is not referenced any more
delete auction;
- auction = NULL;
-
return wasInMap;
}
@@ -469,7 +466,7 @@ void AuctionHouseObject::Update()
continue;
///- Either cancel the auction if there was no bidder
- if (auction->bidder == 0)
+ if (auction->bidder == 0 && auction->bid == 0)
{
sAuctionMgr->SendAuctionExpiredMail(auction, trans);
sScriptMgr->OnAuctionExpire(this, auction);
diff --git a/src/server/game/AuctionHouseBot/AuctionHouseBot.cpp b/src/server/game/AuctionHouseBot/AuctionHouseBot.cpp
index a04e4091778..c0c753100bc 100644
--- a/src/server/game/AuctionHouseBot/AuctionHouseBot.cpp
+++ b/src/server/game/AuctionHouseBot/AuctionHouseBot.cpp
@@ -239,7 +239,7 @@ void AuctionBotConfig::GetConfigFromFile()
char const* AuctionBotConfig::GetHouseTypeName(AuctionHouseType houseType)
{
- static char const* names[MAX_AUCTION_HOUSE_TYPE] = { "Alliance", "Horde", "Neutral" };
+ static char const* names[MAX_AUCTION_HOUSE_TYPE] = { "Neutral", "Alliance", "Horde" };
return names[houseType];
}
diff --git a/src/server/game/AuctionHouseBot/AuctionHouseBot.h b/src/server/game/AuctionHouseBot/AuctionHouseBot.h
index 29460ba13d7..d7570c37d44 100644
--- a/src/server/game/AuctionHouseBot/AuctionHouseBot.h
+++ b/src/server/game/AuctionHouseBot/AuctionHouseBot.h
@@ -39,9 +39,9 @@ enum AuctionQuality
enum AuctionHouseType
{
- AUCTION_HOUSE_ALLIANCE = 0,
- AUCTION_HOUSE_HORDE = 1,
- AUCTION_HOUSE_NEUTRAL = 2
+ AUCTION_HOUSE_NEUTRAL = 0,
+ AUCTION_HOUSE_ALLIANCE = 1,
+ AUCTION_HOUSE_HORDE = 2
};
#define MAX_AUCTION_HOUSE_TYPE 3
diff --git a/src/server/game/AuctionHouseBot/AuctionHouseBotBuyer.cpp b/src/server/game/AuctionHouseBot/AuctionHouseBotBuyer.cpp
index bd5defe2bc3..64463948574 100644
--- a/src/server/game/AuctionHouseBot/AuctionHouseBotBuyer.cpp
+++ b/src/server/game/AuctionHouseBot/AuctionHouseBotBuyer.cpp
@@ -64,7 +64,7 @@ void AuctionBotBuyer::LoadConfig()
}
}
-void AuctionBotBuyer::LoadBuyerValues(BuyerConfiguration& config)
+void AuctionBotBuyer::LoadBuyerValues(BuyerConfiguration& /* config */)
{
}
diff --git a/src/server/game/Battlefield/Battlefield.cpp b/src/server/game/Battlefield/Battlefield.cpp
index ba52c8db2f5..a22db18fa7e 100644
--- a/src/server/game/Battlefield/Battlefield.cpp
+++ b/src/server/game/Battlefield/Battlefield.cpp
@@ -21,7 +21,6 @@
#include "CellImpl.h"
#include "CreatureTextMgr.h"
#include "GridNotifiers.h"
-#include "GridNotifiersImpl.h"
#include "Group.h"
#include "GroupMgr.h"
#include "Map.h"
diff --git a/src/server/game/Battlefield/BattlefieldMgr.cpp b/src/server/game/Battlefield/BattlefieldMgr.cpp
index 066588aa6e8..0060cf4f304 100644
--- a/src/server/game/Battlefield/BattlefieldMgr.cpp
+++ b/src/server/game/Battlefield/BattlefieldMgr.cpp
@@ -17,7 +17,6 @@
#include "BattlefieldMgr.h"
#include "BattlefieldWG.h"
-#include "ObjectMgr.h"
#include "Player.h"
BattlefieldMgr::BattlefieldMgr()
diff --git a/src/server/game/Battlegrounds/ArenaTeam.cpp b/src/server/game/Battlegrounds/ArenaTeam.cpp
index 7ed05205f39..3b7e9ac3f33 100644
--- a/src/server/game/Battlegrounds/ArenaTeam.cpp
+++ b/src/server/game/Battlegrounds/ArenaTeam.cpp
@@ -179,7 +179,7 @@ bool ArenaTeam::AddMember(ObjectGuid playerGuid)
player->SetArenaTeamInfoField(GetSlot(), ARENA_TEAM_MEMBER, 1);
}
- TC_LOG_INFO("bg.arena", "Player: %s [%s] joined arena team type: %u [Id: %u, Name: %s].", playerName.c_str(), playerGuid.ToString().c_str(), GetType(), GetId(), GetName().c_str());
+ TC_LOG_DEBUG("bg.arena", "Player: %s [%s] joined arena team type: %u [Id: %u, Name: %s].", playerName.c_str(), playerGuid.ToString().c_str(), GetType(), GetId(), GetName().c_str());
return true;
}
diff --git a/src/server/game/Battlegrounds/Battleground.cpp b/src/server/game/Battlegrounds/Battleground.cpp
index e091df160a3..3e9b68d4611 100644
--- a/src/server/game/Battlegrounds/Battleground.cpp
+++ b/src/server/game/Battlegrounds/Battleground.cpp
@@ -26,12 +26,10 @@
#include "Formulas.h"
#include "GridNotifiersImpl.h"
#include "Group.h"
-#include "MapManager.h"
#include "Object.h"
#include "ObjectMgr.h"
#include "Player.h"
#include "ReputationMgr.h"
-#include "SpellAuraEffects.h"
#include "SpellAuras.h"
#include "Util.h"
#include "WorldPacket.h"
@@ -510,7 +508,7 @@ inline void Battleground::_ProcessJoin(uint32 diff)
if (!aura->IsPermanent()
&& aura->GetDuration() <= 30*IN_MILLISECONDS
&& aurApp->IsPositive()
- && (!(aura->GetSpellInfo()->Attributes & SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY))
+ && (!aura->GetSpellInfo()->HasAttribute(SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY))
&& (!aura->HasEffectType(SPELL_AURA_MOD_INVISIBILITY)))
player->RemoveAura(iter);
else
diff --git a/src/server/game/Battlegrounds/BattlegroundMgr.cpp b/src/server/game/Battlegrounds/BattlegroundMgr.cpp
index e98cf979cb6..95a51f6d915 100644
--- a/src/server/game/Battlegrounds/BattlegroundMgr.cpp
+++ b/src/server/game/Battlegrounds/BattlegroundMgr.cpp
@@ -22,7 +22,6 @@
#include "World.h"
#include "WorldPacket.h"
-#include "ArenaTeam.h"
#include "BattlegroundMgr.h"
#include "BattlegroundAV.h"
#include "BattlegroundAB.h"
@@ -37,7 +36,6 @@
#include "BattlegroundIC.h"
#include "Chat.h"
#include "Map.h"
-#include "MapInstanced.h"
#include "MapManager.h"
#include "Player.h"
#include "GameEventMgr.h"
diff --git a/src/server/game/Battlegrounds/BattlegroundQueue.cpp b/src/server/game/Battlegrounds/BattlegroundQueue.cpp
index 05bcc08f433..d9db2a9b5d1 100644
--- a/src/server/game/Battlegrounds/BattlegroundQueue.cpp
+++ b/src/server/game/Battlegrounds/BattlegroundQueue.cpp
@@ -24,8 +24,8 @@
#include "Group.h"
#include "Log.h"
#include "Language.h"
-#include "ObjectMgr.h"
#include "Player.h"
+#include "ObjectAccessor.h"
/*********************************************************/
/*** BATTLEGROUND QUEUE SYSTEM ***/
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp
index 2aec542effb..00b6862369d 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp
@@ -17,9 +17,7 @@
*/
#include "BattlegroundAB.h"
-#include "World.h"
#include "WorldPacket.h"
-#include "ObjectMgr.h"
#include "BattlegroundMgr.h"
#include "Creature.h"
#include "Language.h"
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp
index b6569a9f52d..a92cda0817b 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp
@@ -26,7 +26,6 @@
#include "Language.h"
#include "Player.h"
#include "ScriptedCreature.h"
-#include "SpellAuras.h"
#include "WorldSession.h"
BattlegroundAV::BattlegroundAV()
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp
index 92f5c72fdae..ef2e2b15411 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp
@@ -18,7 +18,6 @@
#include "BattlegroundEY.h"
#include "ObjectMgr.h"
-#include "World.h"
#include "WorldPacket.h"
#include "BattlegroundMgr.h"
#include "Creature.h"
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp
index ef5a604c509..3432c740c1f 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp
@@ -25,7 +25,6 @@
#include "ObjectMgr.h"
#include "Vehicle.h"
#include "Transport.h"
-#include "WorldSession.h"
#include "ScriptedCreature.h"
BattlegroundIC::BattlegroundIC()
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp
index cbc0c0e445d..e14e9fadafc 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp
@@ -23,7 +23,6 @@
#include "Player.h"
#include "ScriptedCreature.h"
#include "WorldPacket.h"
-#include "WorldSession.h"
BattlegroundSA::BattlegroundSA()
{
diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp
index 1fff334a27c..378ce22ba3e 100644
--- a/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp
+++ b/src/server/game/Battlegrounds/Zones/BattlegroundWS.cpp
@@ -17,14 +17,12 @@
*/
#include "BattlegroundWS.h"
-#include "Creature.h"
#include "GameObject.h"
#include "Language.h"
#include "Object.h"
#include "ObjectMgr.h"
#include "BattlegroundMgr.h"
#include "Player.h"
-#include "World.h"
#include "WorldPacket.h"
// these variables aren't used outside of this file, so declare them only here
diff --git a/src/server/game/CMakeLists.txt b/src/server/game/CMakeLists.txt
index eb8627efa44..91380b085ea 100644
--- a/src/server/game/CMakeLists.txt
+++ b/src/server/game/CMakeLists.txt
@@ -110,6 +110,7 @@ include_directories(
${CMAKE_SOURCE_DIR}/dep/recastnavigation/Recast/Include
${CMAKE_SOURCE_DIR}/dep/g3dlite/include
${CMAKE_SOURCE_DIR}/dep/SFMT
+ ${CMAKE_SOURCE_DIR}/dep/cppformat
${CMAKE_SOURCE_DIR}/dep/zlib
${CMAKE_SOURCE_DIR}/src/server/collision
${CMAKE_SOURCE_DIR}/src/server/collision/Management
@@ -128,6 +129,7 @@ include_directories(
${CMAKE_SOURCE_DIR}/src/server/shared/Networking
${CMAKE_SOURCE_DIR}/src/server/shared/Packets
${CMAKE_SOURCE_DIR}/src/server/shared/Threading
+ ${CMAKE_SOURCE_DIR}/src/server/shared/Updater
${CMAKE_SOURCE_DIR}/src/server/shared/Utilities
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/Accounts
@@ -206,6 +208,8 @@ include_directories(
${VALGRIND_INCLUDE_DIR}
)
+GroupSources(${CMAKE_CURRENT_SOURCE_DIR})
+
add_library(game STATIC
${game_STAT_SRCS}
${game_STAT_PCH_SRC}
diff --git a/src/server/game/Chat/Chat.cpp b/src/server/game/Chat/Chat.cpp
index 44df1097dd4..1716aa73525 100644
--- a/src/server/game/Chat/Chat.cpp
+++ b/src/server/game/Chat/Chat.cpp
@@ -32,7 +32,6 @@
#include "Opcodes.h"
#include "Player.h"
#include "UpdateMask.h"
-#include "SpellMgr.h"
#include "ScriptMgr.h"
#include "ChatLink.h"
@@ -104,17 +103,6 @@ ChatCommand* ChatHandler::getCommandTable()
return commandTableCache;
}
-std::string ChatHandler::PGetParseString(uint32 entry, ...) const
-{
- const char *format = GetTrinityString(entry);
- char str[1024];
- va_list ap;
- va_start(ap, entry);
- vsnprintf(str, 1024, format, ap);
- va_end(ap);
- return std::string(str);
-}
-
char const* ChatHandler::GetTrinityString(uint32 entry) const
{
return m_session->GetTrinityString(entry);
@@ -258,27 +246,6 @@ void ChatHandler::SendSysMessage(uint32 entry)
SendSysMessage(GetTrinityString(entry));
}
-void ChatHandler::PSendSysMessage(uint32 entry, ...)
-{
- const char *format = GetTrinityString(entry);
- va_list ap;
- char str [2048];
- va_start(ap, entry);
- vsnprintf(str, 2048, format, ap);
- va_end(ap);
- SendSysMessage(str);
-}
-
-void ChatHandler::PSendSysMessage(const char *format, ...)
-{
- va_list ap;
- char str [2048];
- va_start(ap, format);
- vsnprintf(str, 2048, format, ap);
- va_end(ap);
- SendSysMessage(str);
-}
-
bool ChatHandler::ExecuteCommandInTable(ChatCommand* table, const char* text, std::string const& fullcmd)
{
char const* oldtext = text;
diff --git a/src/server/game/Chat/Chat.h b/src/server/game/Chat/Chat.h
index d712740bd7d..ba59245cdaa 100644
--- a/src/server/game/Chat/Chat.h
+++ b/src/server/game/Chat/Chat.h
@@ -20,6 +20,7 @@
#define TRINITYCORE_CHAT_H
#include "SharedDefines.h"
+#include "StringFormat.h"
#include "WorldSession.h"
#include "RBAC.h"
@@ -68,9 +69,24 @@ class ChatHandler
virtual void SendSysMessage(char const* str);
void SendSysMessage(uint32 entry);
- void PSendSysMessage(char const* format, ...) ATTR_PRINTF(2, 3);
- void PSendSysMessage(uint32 entry, ...);
- std::string PGetParseString(uint32 entry, ...) const;
+
+ template<typename... Args>
+ void PSendSysMessage(const char* fmt, Args const&... args)
+ {
+ SendSysMessage(Trinity::StringFormat(fmt, args...).c_str());
+ }
+
+ template<typename... Args>
+ void PSendSysMessage(uint32 entry, Args const&... args)
+ {
+ SendSysMessage(PGetParseString(entry, args...).c_str());
+ }
+
+ template<typename... Args>
+ std::string PGetParseString(uint32 entry, Args const&... args) const
+ {
+ return Trinity::StringFormat(GetTrinityString(entry), args...);
+ }
bool ParseCommands(const char* text);
diff --git a/src/server/game/Chat/ChatLink.cpp b/src/server/game/Chat/ChatLink.cpp
index 1eb330cc9e1..732a770645b 100644
--- a/src/server/game/Chat/ChatLink.cpp
+++ b/src/server/game/Chat/ChatLink.cpp
@@ -285,7 +285,7 @@ bool SpellChatLink::ValidateName(char* buffer, const char* context)
ChatLink::ValidateName(buffer, context);
// spells with that flag have a prefix of "$PROFESSION: "
- if (_spell->Attributes & SPELL_ATTR0_TRADESPELL)
+ if (_spell->HasAttribute(SPELL_ATTR0_TRADESPELL))
{
SkillLineAbilityMapBounds bounds = sSpellMgr->GetSkillLineAbilityMapBounds(_spell->Id);
if (bounds.first == bounds.second)
diff --git a/src/server/game/Combat/HostileRefManager.cpp b/src/server/game/Combat/HostileRefManager.cpp
index 85afdf64607..245cc77eec3 100644
--- a/src/server/game/Combat/HostileRefManager.cpp
+++ b/src/server/game/Combat/HostileRefManager.cpp
@@ -20,7 +20,6 @@
#include "ThreatManager.h"
#include "Unit.h"
#include "DBCStructure.h"
-#include "SpellMgr.h"
#include "SpellInfo.h"
HostileRefManager::~HostileRefManager()
diff --git a/src/server/game/Combat/ThreatManager.cpp b/src/server/game/Combat/ThreatManager.cpp
index 43057409b9b..2ec84c946f6 100644
--- a/src/server/game/Combat/ThreatManager.cpp
+++ b/src/server/game/Combat/ThreatManager.cpp
@@ -19,8 +19,6 @@
#include "ThreatManager.h"
#include "Unit.h"
#include "Creature.h"
-#include "CreatureAI.h"
-#include "Map.h"
#include "Player.h"
#include "ObjectAccessor.h"
#include "UnitEvents.h"
@@ -79,7 +77,7 @@ bool ThreatCalcHelper::isValidProcess(Unit* hatedUnit, Unit* hatingUnit, SpellIn
return false;
// spell not causing threat
- if (threatSpell && threatSpell->AttributesEx & SPELL_ATTR1_NO_THREAT)
+ if (threatSpell && threatSpell->HasAttribute(SPELL_ATTR1_NO_THREAT))
return false;
ASSERT(hatingUnit->GetTypeId() == TYPEID_UNIT);
diff --git a/src/server/game/Conditions/ConditionMgr.cpp b/src/server/game/Conditions/ConditionMgr.cpp
index eb3d1708675..8400e4cee00 100644
--- a/src/server/game/Conditions/ConditionMgr.cpp
+++ b/src/server/game/Conditions/ConditionMgr.cpp
@@ -99,7 +99,8 @@ ConditionMgr::ConditionTypeInfo const ConditionMgr::StaticConditionTypeData[COND
{ "Distance", true, true, true },
{ "Alive", false, false, false },
{ "Health Value", true, true, false },
- { "Health Pct", true, true, false }
+ { "Health Pct", true, true, false },
+ { "Realm Achievement", true, false, false }
};
// Checks if object meets the condition
@@ -416,6 +417,13 @@ bool Condition::Meets(ConditionSourceInfo& sourceInfo)
condMeets = creature->GetCreatureTemplate()->type == ConditionValue1;
break;
}
+ case CONDITION_REALM_ACHIEVEMENT:
+ {
+ AchievementEntry const* achievement = sAchievementMgr->GetAchievement(ConditionValue1);
+ if (achievement && sAchievementMgr->IsRealmCompleted(achievement, std::numeric_limits<uint32>::max()))
+ condMeets = true;
+ break;
+ }
default:
condMeets = false;
break;
@@ -580,6 +588,9 @@ uint32 Condition::GetSearcherTypeMaskForCondition()
case CONDITION_CREATURE_TYPE:
mask |= GRID_MAP_TYPE_MASK_CREATURE;
break;
+ case CONDITION_REALM_ACHIEVEMENT:
+ mask |= GRID_MAP_TYPE_MASK_ALL;
+ break;
default:
ASSERT(false && "Condition::GetSearcherTypeMaskForCondition - missing condition handling!");
break;
@@ -2056,6 +2067,16 @@ bool ConditionMgr::isConditionTypeValid(Condition* cond)
case CONDITION_PHASEMASK:
case CONDITION_ALIVE:
break;
+ case CONDITION_REALM_ACHIEVEMENT:
+ {
+ AchievementEntry const* achievement = sAchievementMgr->GetAchievement(cond->ConditionValue1);
+ if (!achievement)
+ {
+ TC_LOG_ERROR("sql.sql", "%s has non existing realm first achivement id (%u), skipped.", cond->ToString(true).c_str(), cond->ConditionValue1);
+ return false;
+ }
+ break;
+ }
default:
break;
}
diff --git a/src/server/game/Conditions/ConditionMgr.h b/src/server/game/Conditions/ConditionMgr.h
index 4ca27f0d986..1fdd011633e 100644
--- a/src/server/game/Conditions/ConditionMgr.h
+++ b/src/server/game/Conditions/ConditionMgr.h
@@ -72,7 +72,8 @@ enum ConditionTypes
CONDITION_ALIVE = 36, // 0 0 0 true if unit is alive
CONDITION_HP_VAL = 37, // hpVal ComparisonType 0 true if unit's hp matches given value
CONDITION_HP_PCT = 38, // hpPct ComparisonType 0 true if unit's hp matches given pct
- CONDITION_MAX = 39 // MAX
+ CONDITION_REALM_ACHIEVEMENT = 39, // achievement_id 0 0 true if realm achievement is complete
+ CONDITION_MAX = 40 // MAX
};
/*! Documentation on implementing a new ConditionSourceType:
diff --git a/src/server/game/DungeonFinding/LFG.cpp b/src/server/game/DungeonFinding/LFG.cpp
index ab06eff7148..8ec638128d8 100644
--- a/src/server/game/DungeonFinding/LFG.cpp
+++ b/src/server/game/DungeonFinding/LFG.cpp
@@ -91,9 +91,6 @@ std::string GetStateString(LfgState state)
case LFG_STATE_DUNGEON:
entry = LANG_LFG_STATE_DUNGEON;
break;
- case LFG_STATE_BOOT:
- entry = LANG_LFG_STATE_BOOT;
- break;
case LFG_STATE_FINISHED_DUNGEON:
entry = LANG_LFG_STATE_FINISHED_DUNGEON;
break;
diff --git a/src/server/game/DungeonFinding/LFG.h b/src/server/game/DungeonFinding/LFG.h
index 6145a2324b1..84a25ee49ad 100644
--- a/src/server/game/DungeonFinding/LFG.h
+++ b/src/server/game/DungeonFinding/LFG.h
@@ -64,8 +64,8 @@ enum LfgState
LFG_STATE_ROLECHECK, // Rolecheck active
LFG_STATE_QUEUED, // Queued
LFG_STATE_PROPOSAL, // Proposal active
- LFG_STATE_BOOT, // Vote kick active
- LFG_STATE_DUNGEON, // In LFG Group, in a Dungeon
+ //LFG_STATE_BOOT, // Vote kick active
+ LFG_STATE_DUNGEON = 5, // In LFG Group, in a Dungeon
LFG_STATE_FINISHED_DUNGEON, // In LFG Group, in a finished Dungeon
LFG_STATE_RAIDBROWSER // Using Raid finder
};
diff --git a/src/server/game/DungeonFinding/LFGGroupData.cpp b/src/server/game/DungeonFinding/LFGGroupData.cpp
index 2ab1e0b1e7e..aa6916a39a4 100644
--- a/src/server/game/DungeonFinding/LFGGroupData.cpp
+++ b/src/server/game/DungeonFinding/LFGGroupData.cpp
@@ -22,7 +22,7 @@ namespace lfg
{
LfgGroupData::LfgGroupData(): m_State(LFG_STATE_NONE), m_OldState(LFG_STATE_NONE),
- m_Leader(), m_Dungeon(0), m_KicksLeft(LFG_GROUP_MAX_KICKS)
+ m_Leader(), m_Dungeon(0), m_KicksLeft(LFG_GROUP_MAX_KICKS), m_VoteKickActive(false)
{ }
LfgGroupData::~LfgGroupData()
@@ -126,4 +126,14 @@ uint8 LfgGroupData::GetKicksLeft() const
return m_KicksLeft;
}
+void LfgGroupData::SetVoteKick(bool active)
+{
+ m_VoteKickActive = active;
+}
+
+bool LfgGroupData::IsVoteKickActive() const
+{
+ return m_VoteKickActive;
+}
+
} // namespace lfg
diff --git a/src/server/game/DungeonFinding/LFGGroupData.h b/src/server/game/DungeonFinding/LFGGroupData.h
index 8d8f1dc0f3d..b573e7c309e 100644
--- a/src/server/game/DungeonFinding/LFGGroupData.h
+++ b/src/server/game/DungeonFinding/LFGGroupData.h
@@ -66,6 +66,9 @@ class LfgGroupData
// VoteKick
uint8 GetKicksLeft() const;
+ void SetVoteKick(bool active);
+ bool IsVoteKickActive() const;
+
private:
// General
LfgState m_State; ///< State if group in LFG
@@ -76,6 +79,7 @@ class LfgGroupData
uint32 m_Dungeon; ///< Dungeon entry
// Vote Kick
uint8 m_KicksLeft; ///< Number of kicks left
+ bool m_VoteKickActive;
};
} // namespace lfg
diff --git a/src/server/game/DungeonFinding/LFGMgr.cpp b/src/server/game/DungeonFinding/LFGMgr.cpp
index d670e0a2949..a2058fffeed 100644
--- a/src/server/game/DungeonFinding/LFGMgr.cpp
+++ b/src/server/game/DungeonFinding/LFGMgr.cpp
@@ -21,7 +21,6 @@
#include "DisableMgr.h"
#include "ObjectMgr.h"
#include "SocialMgr.h"
-#include "Language.h"
#include "LFGMgr.h"
#include "LFGScripts.h"
#include "LFGGroupData.h"
@@ -311,9 +310,8 @@ void LFGMgr::Update(uint32 diff)
ObjectGuid pguid = itVotes->first;
if (pguid != boot.victim)
SendLfgBootProposalUpdate(pguid, boot);
- SetState(pguid, LFG_STATE_DUNGEON);
}
- SetState(itBoot->first, LFG_STATE_DUNGEON);
+ SetVoteKick(itBoot->first, false);
BootsStore.erase(itBoot);
}
}
@@ -643,7 +641,6 @@ void LFGMgr::LeaveLfg(ObjectGuid guid)
break;
case LFG_STATE_DUNGEON:
case LFG_STATE_FINISHED_DUNGEON:
- case LFG_STATE_BOOT:
if (guid != gguid) // Player
SetState(guid, LFG_STATE_NONE);
break;
@@ -755,7 +752,7 @@ void LFGMgr::GetCompatibleDungeons(LfgDungeonSet& dungeons, GuidSet const& playe
{
ObjectGuid guid = (*it);
LfgLockMap const& cachedLockMap = GetLockedDungeons(guid);
- Player* player = ObjectAccessor::FindPlayer(guid);
+ Player* player = ObjectAccessor::FindConnectedPlayer(guid);
for (LfgLockMap::const_iterator it2 = cachedLockMap.begin(); it2 != cachedLockMap.end() && !dungeons.empty(); ++it2)
{
uint32 dungeonId = (it2->first & 0x00FFFFFF); // Compare dungeon ids
@@ -893,7 +890,7 @@ void LFGMgr::MakeNewGroup(LfgProposal const& proposal)
for (GuidList::const_iterator it = players.begin(); it != players.end(); ++it)
{
ObjectGuid pguid = (*it);
- Player* player = ObjectAccessor::FindPlayer(pguid);
+ Player* player = ObjectAccessor::FindConnectedPlayer(pguid);
if (!player)
continue;
@@ -1156,7 +1153,7 @@ void LFGMgr::RemoveProposal(LfgProposalContainer::iterator itProposal, LfgUpdate
*/
void LFGMgr::InitBoot(ObjectGuid gguid, ObjectGuid kicker, ObjectGuid victim, std::string const& reason)
{
- SetState(gguid, LFG_STATE_BOOT);
+ SetVoteKick(gguid, true);
LfgPlayerBoot& boot = BootsStore[gguid];
boot.inProgress = true;
@@ -1170,7 +1167,6 @@ void LFGMgr::InitBoot(ObjectGuid gguid, ObjectGuid kicker, ObjectGuid victim, st
for (GuidSet::const_iterator itr = players.begin(); itr != players.end(); ++itr)
{
ObjectGuid guid = (*itr);
- SetState(guid, LFG_STATE_BOOT);
boot.votes[guid] = LFG_ANSWER_PENDING;
}
@@ -1227,13 +1223,10 @@ void LFGMgr::UpdateBoot(ObjectGuid guid, bool accept)
{
ObjectGuid pguid = itVotes->first;
if (pguid != boot.victim)
- {
- SetState(pguid, LFG_STATE_DUNGEON);
SendLfgBootProposalUpdate(pguid, boot);
- }
}
- SetState(gguid, LFG_STATE_DUNGEON);
+ SetVoteKick(gguid, false);
if (agreeNum == LFG_GROUP_KICK_VOTES_NEEDED) // Vote passed - Kick player
{
if (Group* group = sGroupMgr->GetGroupByGUID(gguid.GetCounter()))
@@ -1495,12 +1488,12 @@ LfgState LFGMgr::GetState(ObjectGuid guid)
if (guid.IsGroup())
{
state = GroupsStore[guid].GetState();
- TC_LOG_TRACE("lfg.data.group.state.get", "Group: %s, State: %u", guid.ToString().c_str(), state);
+ TC_LOG_TRACE("lfg.data.group.state.get", "Group: %s, State: %s", guid.ToString().c_str(), GetStateString(state).c_str());
}
else
{
state = PlayersStore[guid].GetState();
- TC_LOG_TRACE("lfg.data.player.state.get", "Player: %s, State: %u", guid.ToString().c_str(), state);
+ TC_LOG_TRACE("lfg.data.player.state.get", "Player: %s, State: %s", guid.ToString().c_str(), GetStateString(state).c_str());
}
return state;
@@ -1523,6 +1516,16 @@ LfgState LFGMgr::GetOldState(ObjectGuid guid)
return state;
}
+bool LFGMgr::IsVoteKickActive(ObjectGuid gguid)
+{
+ ASSERT(gguid.IsGroup());
+
+ bool active = GroupsStore[gguid].IsVoteKickActive();
+ TC_LOG_TRACE("lfg.data.group.votekick.get", "Group: %s, Active: %d", gguid.ToString().c_str(), active);
+
+ return active;
+}
+
uint32 LFGMgr::GetDungeon(ObjectGuid guid, bool asId /*= true */)
{
uint32 dungeon = GroupsStore[guid].GetDungeon(asId);
@@ -1566,7 +1569,7 @@ LfgLockMap const LFGMgr::GetLockedDungeons(ObjectGuid guid)
{
TC_LOG_TRACE("lfg.data.player.dungeons.locked.get", "Player: %s, LockedDungeons.", guid.ToString().c_str());
LfgLockMap lock;
- Player* player = ObjectAccessor::FindPlayer(guid);
+ Player* player = ObjectAccessor::FindConnectedPlayer(guid);
if (!player)
{
TC_LOG_WARN("lfg.data.player.dungeons.locked.get", "Player: %s not ingame while retrieving his LockedDungeons.", guid.ToString().c_str());
@@ -1683,6 +1686,17 @@ void LFGMgr::SetState(ObjectGuid guid, LfgState state)
}
}
+void LFGMgr::SetVoteKick(ObjectGuid gguid, bool active)
+{
+ ASSERT(gguid.IsGroup());
+
+ LfgGroupData& data = GroupsStore[gguid];
+ TC_LOG_TRACE("lfg.data.group.votekick.set", "Group: %s, New state: %d, Previous: %d",
+ gguid.ToString().c_str(), active, data.IsVoteKickActive());
+
+ data.SetVoteKick(active);
+}
+
void LFGMgr::SetDungeon(ObjectGuid guid, uint32 dungeon)
{
TC_LOG_TRACE("lfg.data.group.dungeon.set", "Group: %s, Dungeon: %u", guid.ToString().c_str(), dungeon);
diff --git a/src/server/game/DungeonFinding/LFGMgr.h b/src/server/game/DungeonFinding/LFGMgr.h
index 0e5fadc85cc..fda9a8b7ce9 100644
--- a/src/server/game/DungeonFinding/LFGMgr.h
+++ b/src/server/game/DungeonFinding/LFGMgr.h
@@ -322,6 +322,8 @@ class LFGMgr
LfgDungeonSet const& GetSelectedDungeons(ObjectGuid guid);
/// Get current lfg state
LfgState GetState(ObjectGuid guid);
+ /// Get current vote kick state
+ bool IsVoteKickActive(ObjectGuid gguid);
/// Get current dungeon
uint32 GetDungeon(ObjectGuid guid, bool asId = true);
/// Get the map id of the current dungeon
@@ -425,6 +427,7 @@ class LFGMgr
void SetSelectedDungeons(ObjectGuid guid, LfgDungeonSet const& dungeons);
void DecreaseKicksLeft(ObjectGuid guid);
void SetState(ObjectGuid guid, LfgState state);
+ void SetVoteKick(ObjectGuid gguid, bool active);
void RemovePlayerData(ObjectGuid guid);
void GetCompatibleDungeons(LfgDungeonSet& dungeons, GuidSet const& players, LfgLockPartyMap& lockMap, bool isContinue);
void _SaveToDB(ObjectGuid guid, uint32 db_guid);
diff --git a/src/server/game/DungeonFinding/LFGQueue.cpp b/src/server/game/DungeonFinding/LFGQueue.cpp
index 683590cebe8..6ac20541574 100644
--- a/src/server/game/DungeonFinding/LFGQueue.cpp
+++ b/src/server/game/DungeonFinding/LFGQueue.cpp
@@ -23,9 +23,6 @@
#include "LFGQueue.h"
#include "LFGMgr.h"
#include "Log.h"
-#include "ObjectMgr.h"
-#include "World.h"
-#include "GroupMgr.h"
namespace lfg
{
@@ -377,7 +374,7 @@ LfgCompatibility LFGQueue::CheckCompatibility(GuidList check)
// Group with less that MAXGROUPSIZE members always compatible
if (check.size() == 1 && numPlayers != MAXGROUPSIZE)
{
- TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: (%s) sigle group. Compatibles", strGuids.c_str());
+ TC_LOG_DEBUG("lfg.queue.match.compatibility.check", "Guids: (%s) single group. Compatibles", strGuids.c_str());
LfgQueueDataContainer::iterator itQueue = QueueDataStore.find(check.front());
LfgCompatibilityData data(LFG_COMPATIBLES_WITH_LESS_PLAYERS);
diff --git a/src/server/game/Entities/Corpse/Corpse.cpp b/src/server/game/Entities/Corpse/Corpse.cpp
index 1e967928265..bf69b4e7443 100644
--- a/src/server/game/Entities/Corpse/Corpse.cpp
+++ b/src/server/game/Entities/Corpse/Corpse.cpp
@@ -22,9 +22,6 @@
#include "UpdateMask.h"
#include "ObjectAccessor.h"
#include "DatabaseEnv.h"
-#include "Opcodes.h"
-#include "GossipDef.h"
-#include "World.h"
Corpse::Corpse(CorpseType type) : WorldObject(type != CORPSE_BONES), m_type(type)
{
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp
index a44ca68f79b..b367ebe6a8a 100644
--- a/src/server/game/Entities/Creature/Creature.cpp
+++ b/src/server/game/Entities/Creature/Creature.cpp
@@ -34,12 +34,9 @@
#include "InstanceScript.h"
#include "Log.h"
#include "LootMgr.h"
-#include "MapManager.h"
#include "MoveSpline.h"
-#include "MoveSplineInit.h"
#include "ObjectMgr.h"
#include "Opcodes.h"
-#include "OutdoorPvPMgr.h"
#include "Player.h"
#include "PoolMgr.h"
#include "QuestDef.h"
@@ -48,10 +45,8 @@
#include "TemporarySummon.h"
#include "Util.h"
#include "Vehicle.h"
-#include "WaypointMovementGenerator.h"
#include "World.h"
#include "WorldPacket.h"
-
#include "Transport.h"
TrainerSpell const* TrainerSpellData::Find(uint32 spell_id) const
@@ -2697,7 +2692,7 @@ void Creature::FocusTarget(Spell const* focusSpell, WorldObject const* target)
_focusSpell = focusSpell;
SetGuidValue(UNIT_FIELD_TARGET, target->GetGUID());
- if (focusSpell->GetSpellInfo()->AttributesEx5 & SPELL_ATTR5_DONT_TURN_DURING_CAST)
+ if (focusSpell->GetSpellInfo()->HasAttribute(SPELL_ATTR5_DONT_TURN_DURING_CAST))
AddUnitState(UNIT_STATE_ROTATING);
// Set serverside orientation if needed (needs to be after attribute check)
@@ -2716,7 +2711,7 @@ void Creature::ReleaseFocus(Spell const* focusSpell)
else
SetGuidValue(UNIT_FIELD_TARGET, ObjectGuid::Empty);
- if (focusSpell->GetSpellInfo()->AttributesEx5 & SPELL_ATTR5_DONT_TURN_DURING_CAST)
+ if (focusSpell->GetSpellInfo()->HasAttribute(SPELL_ATTR5_DONT_TURN_DURING_CAST))
ClearUnitState(UNIT_STATE_ROTATING);
}
diff --git a/src/server/game/Entities/Creature/TemporarySummon.cpp b/src/server/game/Entities/Creature/TemporarySummon.cpp
index fc7b85aa73e..2a3e91b7574 100644
--- a/src/server/game/Entities/Creature/TemporarySummon.cpp
+++ b/src/server/game/Entities/Creature/TemporarySummon.cpp
@@ -19,7 +19,6 @@
#include "Log.h"
#include "ObjectAccessor.h"
#include "CreatureAI.h"
-#include "ObjectMgr.h"
#include "TemporarySummon.h"
#include "Pet.h"
#include "Player.h"
diff --git a/src/server/game/Entities/DynamicObject/DynamicObject.cpp b/src/server/game/Entities/DynamicObject/DynamicObject.cpp
index 60accf8ad92..71d0f13488c 100644
--- a/src/server/game/Entities/DynamicObject/DynamicObject.cpp
+++ b/src/server/game/Entities/DynamicObject/DynamicObject.cpp
@@ -18,12 +18,10 @@
#include "Common.h"
#include "UpdateMask.h"
-#include "Opcodes.h"
#include "World.h"
#include "ObjectAccessor.h"
#include "DatabaseEnv.h"
#include "GridNotifiers.h"
-#include "CellImpl.h"
#include "GridNotifiersImpl.h"
#include "ScriptMgr.h"
#include "Transport.h"
diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp
index 6ca5ab4ae5b..a73cbfa3e5c 100644
--- a/src/server/game/Entities/GameObject/GameObject.cpp
+++ b/src/server/game/Entities/GameObject/GameObject.cpp
@@ -20,7 +20,6 @@
#include "Battleground.h"
#include "CellImpl.h"
#include "CreatureAISelector.h"
-#include "DynamicTree.h"
#include "GameObjectModel.h"
#include "GridNotifiersImpl.h"
#include "Group.h"
@@ -33,7 +32,6 @@
#include "UpdateFieldFlags.h"
#include "World.h"
#include "Transport.h"
-#include <G3D/Quat.h>
GameObject::GameObject() : WorldObject(false), MapObject(),
m_model(NULL), m_goValue(), m_AI(NULL)
diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp
index b5bcbfd221f..0a52c145122 100644
--- a/src/server/game/Entities/Object/Object.cpp
+++ b/src/server/game/Entities/Object/Object.cpp
@@ -30,27 +30,19 @@
#include "UpdateData.h"
#include "UpdateMask.h"
#include "Util.h"
-#include "MapManager.h"
#include "ObjectAccessor.h"
-#include "Log.h"
#include "Transport.h"
-#include "TargetedMovementGenerator.h"
-#include "WaypointMovementGenerator.h"
#include "VMapFactory.h"
#include "CellImpl.h"
#include "GridNotifiers.h"
#include "GridNotifiersImpl.h"
-#include "SpellAuraEffects.h"
#include "UpdateFieldFlags.h"
#include "TemporarySummon.h"
#include "Totem.h"
#include "OutdoorPvPMgr.h"
#include "MovementPacketBuilder.h"
-#include "DynamicTree.h"
-#include "Group.h"
#include "BattlefieldMgr.h"
#include "Battleground.h"
-#include "Chat.h"
Object::Object() : m_PackGUID(sizeof(uint64)+1)
{
@@ -1072,32 +1064,32 @@ ByteBuffer& operator<<(ByteBuffer& buf, Position::PositionXYZOStreamer const& st
void MovementInfo::OutDebug()
{
- TC_LOG_INFO("misc", "MOVEMENT INFO");
- TC_LOG_INFO("misc", "%s", guid.ToString().c_str());
- TC_LOG_INFO("misc", "flags %u", flags);
- TC_LOG_INFO("misc", "flags2 %u", flags2);
- TC_LOG_INFO("misc", "time %u current time " UI64FMTD "", flags2, uint64(::time(NULL)));
- TC_LOG_INFO("misc", "position: `%s`", pos.ToString().c_str());
+ TC_LOG_DEBUG("misc", "MOVEMENT INFO");
+ TC_LOG_DEBUG("misc", "%s", guid.ToString().c_str());
+ TC_LOG_DEBUG("misc", "flags %u", flags);
+ TC_LOG_DEBUG("misc", "flags2 %u", flags2);
+ TC_LOG_DEBUG("misc", "time %u current time " UI64FMTD "", flags2, uint64(::time(NULL)));
+ TC_LOG_DEBUG("misc", "position: `%s`", pos.ToString().c_str());
if (flags & MOVEMENTFLAG_ONTRANSPORT)
{
- TC_LOG_INFO("misc", "TRANSPORT:");
- TC_LOG_INFO("misc", "%s", transport.guid.ToString().c_str());
- TC_LOG_INFO("misc", "position: `%s`", transport.pos.ToString().c_str());
- TC_LOG_INFO("misc", "seat: %i", transport.seat);
- TC_LOG_INFO("misc", "time: %u", transport.time);
+ TC_LOG_DEBUG("misc", "TRANSPORT:");
+ TC_LOG_DEBUG("misc", "%s", transport.guid.ToString().c_str());
+ TC_LOG_DEBUG("misc", "position: `%s`", transport.pos.ToString().c_str());
+ TC_LOG_DEBUG("misc", "seat: %i", transport.seat);
+ TC_LOG_DEBUG("misc", "time: %u", transport.time);
if (flags2 & MOVEMENTFLAG2_INTERPOLATED_MOVEMENT)
- TC_LOG_INFO("misc", "time2: %u", transport.time2);
+ TC_LOG_DEBUG("misc", "time2: %u", transport.time2);
}
if ((flags & (MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING)) || (flags2 & MOVEMENTFLAG2_ALWAYS_ALLOW_PITCHING))
- TC_LOG_INFO("misc", "pitch: %f", pitch);
+ TC_LOG_DEBUG("misc", "pitch: %f", pitch);
- TC_LOG_INFO("misc", "fallTime: %u", fallTime);
+ TC_LOG_DEBUG("misc", "fallTime: %u", fallTime);
if (flags & MOVEMENTFLAG_FALLING)
- TC_LOG_INFO("misc", "j_zspeed: %f j_sinAngle: %f j_cosAngle: %f j_xyspeed: %f", jump.zspeed, jump.sinAngle, jump.cosAngle, jump.xyspeed);
+ TC_LOG_DEBUG("misc", "j_zspeed: %f j_sinAngle: %f j_cosAngle: %f j_xyspeed: %f", jump.zspeed, jump.sinAngle, jump.cosAngle, jump.xyspeed);
if (flags & MOVEMENTFLAG_SPLINE_ELEVATION)
- TC_LOG_INFO("misc", "splineElevation: %f", splineElevation);
+ TC_LOG_DEBUG("misc", "splineElevation: %f", splineElevation);
}
WorldObject::WorldObject(bool isWorldObject) : WorldLocation(), LastUsedScriptID(0),
@@ -2255,6 +2247,13 @@ void WorldObject::GetCreatureListWithEntryInGrid(std::list<Creature*>& creatureL
cell.Visit(pair, visitor, *(this->GetMap()), *this, maxSearchRange);
}
+void WorldObject::GetPlayerListInGrid(std::list<Player*>& playerList, float maxSearchRange) const
+{
+ Trinity::AnyPlayerInObjectRangeCheck checker(this, maxSearchRange);
+ Trinity::PlayerListSearcher<Trinity::AnyPlayerInObjectRangeCheck> searcher(this, playerList, checker);
+ this->VisitNearbyWorldObject(maxSearchRange, searcher);
+}
+
/*
namespace Trinity
{
diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h
index 2aa1704f7d2..c48d8ff4d18 100644
--- a/src/server/game/Entities/Object/Object.h
+++ b/src/server/game/Entities/Object/Object.h
@@ -683,6 +683,7 @@ class WorldObject : public Object, public WorldLocation
void GetGameObjectListWithEntryInGrid(std::list<GameObject*>& lList, uint32 uiEntry, float fMaxSearchRange) const;
void GetCreatureListWithEntryInGrid(std::list<Creature*>& lList, uint32 uiEntry, float fMaxSearchRange) const;
+ void GetPlayerListInGrid(std::list<Player*>& lList, float fMaxSearchRange) const;
void DestroyForNearbyPlayers();
virtual void UpdateObjectVisibility(bool forced = true);
diff --git a/src/server/game/Entities/Object/ObjectGuid.cpp b/src/server/game/Entities/Object/ObjectGuid.cpp
index b86a253a84d..c15668c3887 100644
--- a/src/server/game/Entities/Object/ObjectGuid.cpp
+++ b/src/server/game/Entities/Object/ObjectGuid.cpp
@@ -18,7 +18,6 @@
#include "ObjectGuid.h"
#include "World.h"
-#include "ObjectMgr.h"
#include <sstream>
#include <iomanip>
diff --git a/src/server/game/Entities/Object/ObjectGuid.h b/src/server/game/Entities/Object/ObjectGuid.h
index be292751811..36dbdd72069 100644
--- a/src/server/game/Entities/Object/ObjectGuid.h
+++ b/src/server/game/Entities/Object/ObjectGuid.h
@@ -23,6 +23,7 @@
#include "ByteBuffer.h"
#include <functional>
+#include <unordered_set>
enum TypeID
{
@@ -202,6 +203,7 @@ typedef std::set<ObjectGuid> GuidSet;
typedef std::list<ObjectGuid> GuidList;
typedef std::deque<ObjectGuid> GuidDeque;
typedef std::vector<ObjectGuid> GuidVector;
+typedef std::unordered_set<ObjectGuid> GuidUnorderedSet;
// minimum buffer size for packed guid is 9 bytes
#define PACKED_GUID_MIN_BUFFER_SIZE 9
diff --git a/src/server/game/Entities/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp
index 5084031880d..d5d6bdf9831 100644
--- a/src/server/game/Entities/Pet/Pet.cpp
+++ b/src/server/game/Entities/Pet/Pet.cpp
@@ -26,7 +26,6 @@
#include "Formulas.h"
#include "SpellAuras.h"
#include "SpellAuraEffects.h"
-#include "CreatureAI.h"
#include "Unit.h"
#include "Util.h"
#include "Group.h"
@@ -1314,7 +1313,7 @@ void Pet::_LoadAuras(uint32 timediff)
}
aura->SetLoadedState(maxduration, remaintime, remaincharges, stackcount, recalculatemask, &damage[0]);
aura->ApplyForTargets();
- TC_LOG_INFO("entities.pet", "Added aura spellid %u, effectmask %u", spellInfo->Id, effmask);
+ TC_LOG_DEBUG("entities.pet", "Added aura spellid %u, effectmask %u", spellInfo->Id, effmask);
}
}
while (result->NextRow());
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 63580b355a4..9e92492d46b 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -51,7 +51,6 @@
#include "LFGMgr.h"
#include "Language.h"
#include "Log.h"
-#include "MapInstanced.h"
#include "MapManager.h"
#include "ObjectAccessor.h"
#include "ObjectMgr.h"
@@ -73,7 +72,6 @@
#include "UpdateFieldFlags.h"
#include "UpdateMask.h"
#include "Util.h"
-#include "Vehicle.h"
#include "Weather.h"
#include "WeatherMgr.h"
#include "World.h"
@@ -3902,7 +3900,7 @@ bool Player::IsNeedCastPassiveSpellAtLearn(SpellInfo const* spellInfo) const
// talent dependent passives activated at form apply have proper stance data
ShapeshiftForm form = GetShapeshiftForm();
bool need_cast = (!spellInfo->Stances || (form && (spellInfo->Stances & (1 << (form - 1)))) ||
- (!form && (spellInfo->AttributesEx2 & SPELL_ATTR2_NOT_NEED_SHAPESHIFT)));
+ (!form && spellInfo->HasAttribute(SPELL_ATTR2_NOT_NEED_SHAPESHIFT)));
//Check CasterAuraStates
return need_cast && (!spellInfo->CasterAuraState || HasAuraState(AuraStateType(spellInfo->CasterAuraState)));
@@ -4218,7 +4216,7 @@ void Player::RemoveSpellCategoryCooldown(uint32 cat, bool update /* = false */)
void Player::RemoveArenaSpellCooldowns(bool removeActivePetCooldowns)
{
- // remove cooldowns on spells that have <= 10 min CD
+ // remove cooldowns on spells that have < 10 min CD
SpellCooldowns::iterator itr, next;
for (itr = m_spellCooldowns.begin(); itr != m_spellCooldowns.end(); itr = next)
@@ -4226,10 +4224,10 @@ void Player::RemoveArenaSpellCooldowns(bool removeActivePetCooldowns)
next = itr;
++next;
SpellInfo const* entry = sSpellMgr->GetSpellInfo(itr->first);
- // check if spellentry is present and if the cooldown is less or equal to 10 min
+ // check if spellentry is present and if the cooldown is less than 10 min
if (entry &&
- entry->RecoveryTime <= 10 * MINUTE * IN_MILLISECONDS &&
- entry->CategoryRecoveryTime <= 10 * MINUTE * IN_MILLISECONDS)
+ entry->RecoveryTime < 10 * MINUTE * IN_MILLISECONDS &&
+ entry->CategoryRecoveryTime < 10 * MINUTE * IN_MILLISECONDS)
{
// remove & notify
RemoveSpellCooldown(itr->first, true);
@@ -4830,10 +4828,22 @@ void Player::DeleteFromDB(ObjectGuid playerguid, uint32 accountId, bool updateRe
stmt->setUInt32(0, guid);
trans->Append(stmt);
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHARACTER_ARENA_STATS);
+ stmt->setUInt32(0, guid);
+ trans->Append(stmt);
+
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_AURA);
stmt->setUInt32(0, guid);
trans->Append(stmt);
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PLAYER_BGDATA);
+ stmt->setUInt32(0, guid);
+ trans->Append(stmt);
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_BATTLEGROUND_RANDOM);
+ stmt->setUInt32(0, guid);
+ trans->Append(stmt);
+
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_GIFT);
stmt->setUInt32(0, guid);
trans->Append(stmt);
@@ -4923,10 +4933,6 @@ void Player::DeleteFromDB(ObjectGuid playerguid, uint32 accountId, bool updateRe
stmt->setUInt32(0, guid);
trans->Append(stmt);
- stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PLAYER_BGDATA);
- stmt->setUInt32(0, guid);
- trans->Append(stmt);
-
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_GLYPHS);
stmt->setUInt32(0, guid);
trans->Append(stmt);
@@ -4955,6 +4961,10 @@ void Player::DeleteFromDB(ObjectGuid playerguid, uint32 accountId, bool updateRe
stmt->setUInt32(0, guid);
trans->Append(stmt);
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_STATS);
+ stmt->setUInt32(0, guid);
+ trans->Append(stmt);
+
CharacterDatabase.CommitTransaction(trans);
break;
}
@@ -5002,7 +5012,7 @@ void Player::DeleteOldCharacters()
*/
void Player::DeleteOldCharacters(uint32 keepDays)
{
- TC_LOG_INFO("entities.player", "Player::DeleteOldChars: Deleting all characters which have been deleted %u days before...", keepDays);
+ TC_LOG_INFO("entities.player", "Player::DeleteOldChars: Removing characters older than %u day(s)", keepDays);
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_OLD_CHARS);
stmt->setUInt32(0, uint32(time(NULL) - time_t(keepDays * DAY)));
@@ -5010,7 +5020,7 @@ void Player::DeleteOldCharacters(uint32 keepDays)
if (result)
{
- TC_LOG_DEBUG("entities.player", "Player::DeleteOldChars: Found " UI64FMTD " character(s) to delete", result->GetRowCount());
+ TC_LOG_DEBUG("entities.player", "Player::DeleteOldChars: " UI64FMTD " character(s) to remove", result->GetRowCount());
do
{
Field* fields = result->Fetch();
@@ -6636,20 +6646,20 @@ void Player::SendActionButtons(uint32 state) const
}
GetSession()->SendPacket(&data);
- TC_LOG_INFO("network", "SMSG_ACTION_BUTTONS sent '%u' spec '%u' Sent", GetGUIDLow(), m_activeSpec);
+ TC_LOG_DEBUG("network", "SMSG_ACTION_BUTTONS sent '%u' spec '%u' Sent", GetGUIDLow(), m_activeSpec);
}
bool Player::IsActionButtonDataValid(uint8 button, uint32 action, uint8 type)
{
if (button >= MAX_ACTION_BUTTONS)
{
- TC_LOG_ERROR("entities.player", "Action %u not added into button %u for player %s (GUID: %u): button must be < %u", action, button, GetName().c_str(), GetGUIDLow(), MAX_ACTION_BUTTONS );
+ TC_LOG_DEBUG("entities.player", "Action %u not added into button %u for player %s (GUID: %u): button must be < %u", action, button, GetName().c_str(), GetGUIDLow(), MAX_ACTION_BUTTONS );
return false;
}
if (action >= MAX_ACTION_BUTTON_ACTION_VALUE)
{
- TC_LOG_ERROR("entities.player", "Action %u not added into button %u for player %s (GUID: %u): action must be < %u", action, button, GetName().c_str(), GetGUIDLow(), MAX_ACTION_BUTTON_ACTION_VALUE);
+ TC_LOG_DEBUG("entities.player", "Action %u not added into button %u for player %s (GUID: %u): action must be < %u", action, button, GetName().c_str(), GetGUIDLow(), MAX_ACTION_BUTTON_ACTION_VALUE);
return false;
}
@@ -6658,20 +6668,20 @@ bool Player::IsActionButtonDataValid(uint8 button, uint32 action, uint8 type)
case ACTION_BUTTON_SPELL:
if (!sSpellMgr->GetSpellInfo(action))
{
- TC_LOG_ERROR("entities.player", "Spell action %u not added into button %u for player %s (GUID: %u): spell not exist", action, button, GetName().c_str(), GetGUIDLow());
+ TC_LOG_DEBUG("entities.player", "Spell action %u not added into button %u for player %s (GUID: %u): spell not exist", action, button, GetName().c_str(), GetGUIDLow());
return false;
}
if (!HasSpell(action))
{
- TC_LOG_ERROR("entities.player", "Spell action %u not added into button %u for player %s (GUID: %u): player don't known this spell", action, button, GetName().c_str(), GetGUIDLow());
+ TC_LOG_DEBUG("entities.player", "Spell action %u not added into button %u for player %s (GUID: %u): player don't known this spell", action, button, GetName().c_str(), GetGUIDLow());
return false;
}
break;
case ACTION_BUTTON_ITEM:
if (!sObjectMgr->GetItemTemplate(action))
{
- TC_LOG_ERROR("entities.player", "Item action %u not added into button %u for player %s (GUID: %u): item not exist", action, button, GetName().c_str(), GetGUIDLow());
+ TC_LOG_DEBUG("entities.player", "Item action %u not added into button %u for player %s (GUID: %u): item not exist", action, button, GetName().c_str(), GetGUIDLow());
return false;
}
break;
@@ -6681,7 +6691,7 @@ bool Player::IsActionButtonDataValid(uint8 button, uint32 action, uint8 type)
case ACTION_BUTTON_EQSET:
break;
default:
- TC_LOG_ERROR("entities.player", "Unknown action type %u", type);
+ TC_LOG_DEBUG("entities.player", "Unknown action type %u", type);
return false; // other cases not checked at this moment
}
@@ -6883,7 +6893,7 @@ void Player::CheckAreaExploreAndOutdoor()
GiveXP(XP, NULL);
SendExplorationExperience(area, XP);
}
- TC_LOG_INFO("entities.player", "Player %u discovered a new area: %u", GetGUIDLow(), area);
+ TC_LOG_DEBUG("entities.player", "Player %u discovered a new area: %u", GetGUIDLow(), area);
}
}
}
@@ -7763,7 +7773,7 @@ void Player::_ApplyItemMods(Item* item, uint8 slot, bool apply)
if (item->IsBroken())
return;
- TC_LOG_INFO("entities.player.items", "applying mods for item %u ", item->GetGUIDLow());
+ TC_LOG_DEBUG("entities.player.items", "applying mods for item %u ", item->GetGUIDLow());
uint8 attacktype = Player::GetAttackBySlot(slot);
@@ -9774,7 +9784,7 @@ uint32 Player::GetXPRestBonus(uint32 xp)
SetRestBonus(GetRestBonus() - rested_bonus);
- TC_LOG_INFO("entities.player", "Player gain %u xp (+ %u Rested Bonus). Rested points=%f", xp+rested_bonus, rested_bonus, GetRestBonus());
+ TC_LOG_DEBUG("entities.player", "GetXPRestBonus: Player %s (%u) gain %u xp (+%u Rested Bonus). Rested points=%f", GetName().c_str(), GetGUIDLow(), xp+rested_bonus, rested_bonus, GetRestBonus());
return rested_bonus;
}
@@ -16361,6 +16371,8 @@ void Player::AreaExploredOrEventHappens(uint32 questId)
{
q_status.Explored = true;
m_QuestStatusSave[questId] = QUEST_DEFAULT_SAVE_TYPE;
+ SetQuestSlotState(log_slot, QUEST_STATE_COMPLETE);
+ SendQuestComplete(questId);
}
}
if (CanCompleteQuest(questId))
@@ -17999,7 +18011,7 @@ void Player::_LoadAuras(PreparedQueryResult result, uint32 timediff)
aura->SetLoadedState(maxduration, remaintime, remaincharges, stackcount, recalculatemask, &damage[0]);
aura->ApplyForTargets();
- TC_LOG_INFO("entities.player", "Added aura spellid %u, effectmask %u", spellInfo->Id, effmask);
+ TC_LOG_DEBUG("entities.player", "Added aura spellid %u, effectmask %u", spellInfo->Id, effmask);
}
}
while (result->NextRow());
@@ -19732,6 +19744,7 @@ void Player::_SaveInventory(SQLTransaction& trans)
m_itemUpdateQueue.clear();
}
+
void Player::_SaveMail(SQLTransaction& trans)
{
if (!m_mailsLoaded)
@@ -20670,8 +20683,6 @@ void Player::PetSpellInitialize()
if (!pet)
return;
- TC_LOG_DEBUG("entities.pet", "Pet Spells Groups");
-
CharmInfo* charmInfo = pet->GetCharmInfo();
WorldPacket data(SMSG_PET_SPELLS, 8+2+4+4+4*MAX_UNIT_ACTION_BAR_INDEX+1+1);
@@ -20682,6 +20693,8 @@ void Player::PetSpellInitialize()
data << uint8(charmInfo->GetCommandState());
data << uint16(0); // Flags, mostly unknown
+ TC_LOG_DEBUG("entities.pet", "Player::PetspellInitialize: Creating spellgroups for summoned pet");
+
// action bar loop
charmInfo->BuildActionBar(&data);
@@ -22043,7 +22056,7 @@ void Player::AddSpellAndCategoryCooldowns(SpellInfo const* spellInfo, uint32 ite
if (rec > 0)
ApplySpellMod(spellInfo->Id, SPELLMOD_COOLDOWN, rec, spell);
- if (catrec > 0 && !(spellInfo->AttributesEx6 & SPELL_ATTR6_IGNORE_CATEGORY_COOLDOWN_MODS))
+ if (catrec > 0 && !spellInfo->HasAttribute(SPELL_ATTR6_IGNORE_CATEGORY_COOLDOWN_MODS))
ApplySpellMod(spellInfo->Id, SPELLMOD_COOLDOWN, catrec, spell);
if (int32 cooldownMod = GetTotalAuraModifier(SPELL_AURA_MOD_COOLDOWN))
@@ -22138,6 +22151,34 @@ void Player::SendCooldownEvent(SpellInfo const* spellInfo, uint32 itemId /*= 0*/
data << uint32(spellInfo->Id);
data << uint64(GetGUID());
SendDirectMessage(&data);
+
+ uint32 cat = spellInfo->GetCategory();
+ if (cat && spellInfo->CategoryRecoveryTime)
+ {
+ SpellCategoryStore::const_iterator ct = sSpellsByCategoryStore.find(cat);
+ if (ct != sSpellsByCategoryStore.end())
+ {
+ SpellCategorySet const& catSet = ct->second;
+ for (SpellCooldowns::const_iterator i = m_spellCooldowns.begin(); i != m_spellCooldowns.end(); ++i)
+ {
+ if (i->first == spellInfo->Id) // skip main spell, already handled above
+ continue;
+
+ SpellInfo const* spellInfo2 = sSpellMgr->GetSpellInfo(i->first);
+ if (!spellInfo2 || !spellInfo2->IsCooldownStartedOnEvent())
+ continue;
+
+ if (catSet.find(i->first) != catSet.end())
+ {
+ // Send activate cooldown timer (possible 0) at client side
+ WorldPacket data(SMSG_COOLDOWN_EVENT, 4 + 8);
+ data << uint32(i->first);
+ data << uint64(GetGUID());
+ SendDirectMessage(&data);
+ }
+ }
+ }
+ }
}
void Player::UpdatePotionCooldown(Spell* spell)
@@ -22532,13 +22573,13 @@ bool Player::IsVisibleGloballyFor(Player const* u) const
}
template<class T>
-inline void UpdateVisibilityOf_helper(GuidSet& s64, T* target, std::set<Unit*>& /*v*/)
+inline void UpdateVisibilityOf_helper(GuidUnorderedSet& s64, T* target, std::set<Unit*>& /*v*/)
{
s64.insert(target->GetGUID());
}
template<>
-inline void UpdateVisibilityOf_helper(GuidSet& s64, GameObject* target, std::set<Unit*>& /*v*/)
+inline void UpdateVisibilityOf_helper(GuidUnorderedSet& s64, GameObject* target, std::set<Unit*>& /*v*/)
{
// @HACK: This is to prevent objects like deeprun tram from disappearing when player moves far from its spawn point while riding it
if ((target->GetGOInfo()->type != GAMEOBJECT_TYPE_TRANSPORT))
@@ -22546,14 +22587,14 @@ inline void UpdateVisibilityOf_helper(GuidSet& s64, GameObject* target, std::set
}
template<>
-inline void UpdateVisibilityOf_helper(GuidSet& s64, Creature* target, std::set<Unit*>& v)
+inline void UpdateVisibilityOf_helper(GuidUnorderedSet& s64, Creature* target, std::set<Unit*>& v)
{
s64.insert(target->GetGUID());
v.insert(target);
}
template<>
-inline void UpdateVisibilityOf_helper(GuidSet& s64, Player* target, std::set<Unit*>& v)
+inline void UpdateVisibilityOf_helper(GuidUnorderedSet& s64, Player* target, std::set<Unit*>& v)
{
s64.insert(target->GetGUID());
v.insert(target);
@@ -22615,9 +22656,9 @@ void Player::UpdateTriggerVisibility()
UpdateData udata;
WorldPacket packet;
- for (GuidSet::iterator itr = m_clientGUIDs.begin(); itr != m_clientGUIDs.end(); ++itr)
+ for (auto itr = m_clientGUIDs.begin(); itr != m_clientGUIDs.end(); ++itr)
{
- if (itr->IsCreature())
+ if (itr->IsCreatureOrVehicle())
{
Creature* creature = GetMap()->GetCreature(*itr);
// Update fields of triggers, transformed units or unselectable units (values dependent on GM state)
@@ -23674,7 +23715,7 @@ void Player::UpdateForQuestWorldObjects()
UpdateData udata;
WorldPacket packet;
- for (GuidSet::iterator itr = m_clientGUIDs.begin(); itr != m_clientGUIDs.end(); ++itr)
+ for (auto itr = m_clientGUIDs.begin(); itr != m_clientGUIDs.end(); ++itr)
{
if (itr->IsGameObject())
{
@@ -23863,7 +23904,7 @@ bool Player::HasItemFitToSpellRequirements(SpellInfo const* spellInfo, Item cons
bool Player::CanNoReagentCast(SpellInfo const* spellInfo) const
{
// don't take reagents for spells with SPELL_ATTR5_NO_REAGENT_WHILE_PREP
- if (spellInfo->AttributesEx5 & SPELL_ATTR5_NO_REAGENT_WHILE_PREP &&
+ if (spellInfo->HasAttribute(SPELL_ATTR5_NO_REAGENT_WHILE_PREP) &&
HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PREPARATION))
return true;
@@ -24166,18 +24207,6 @@ void Player::UpdateAreaDependentAuras(uint32 newArea)
if (itr->second->autocast && itr->second->IsFitToRequirements(this, m_zoneUpdateId, newArea))
if (!HasAura(itr->second->spellId))
CastSpell(this, itr->second->spellId, true);
-
- if (newArea == 4273 && GetVehicleCreatureBase() && GetPositionX() > 400) // Ulduar
- {
- switch (GetVehicleBase()->GetEntry())
- {
- case 33062:
- case 33109:
- case 33060:
- GetVehicleCreatureBase()->DespawnOrUnsummon();
- break;
- }
- }
}
uint32 Player::GetCorpseReclaimDelay(bool pvp) const
@@ -24308,7 +24337,7 @@ PartyResult Player::CanUninviteFromGroup(ObjectGuid guidMember) const
return ERR_PARTY_LFG_BOOT_LIMIT;
lfg::LfgState state = sLFGMgr->GetState(gguid);
- if (state == lfg::LFG_STATE_BOOT)
+ if (sLFGMgr->IsVoteKickActive(gguid))
return ERR_PARTY_LFG_BOOT_IN_PROGRESS;
if (grp->GetMembersCount() <= lfg::LFG_GROUP_KICK_VOTES_NEEDED)
@@ -24815,7 +24844,7 @@ void Player::RestoreBaseRune(uint8 index)
{
AuraEffect const* aura = m_runes->runes[index].ConvertAura;
// If rune was converted by a non-pasive aura that still active we should keep it converted
- if (aura && !(aura->GetSpellInfo()->Attributes & SPELL_ATTR0_PASSIVE))
+ if (aura && !aura->GetSpellInfo()->HasAttribute(SPELL_ATTR0_PASSIVE))
return;
ConvertRune(index, GetBaseRune(index));
SetRuneConvertAura(index, NULL);
@@ -25433,7 +25462,7 @@ void Player::LearnTalent(uint32 talentId, uint32 talentRank)
LearnSpell(spellid, false);
AddTalent(spellid, m_activeSpec, true);
- TC_LOG_INFO("entities.player", "TalentID: %u Rank: %u Spell: %u Spec: %u\n", talentId, talentRank, spellid, m_activeSpec);
+ TC_LOG_DEBUG("entities.player", "TalentID: %u Rank: %u Spell: %u Spec: %u\n", talentId, talentRank, spellid, m_activeSpec);
// update free talent points
SetFreeTalentPoints(CurTalentPoints - (talentRank - curtalent_maxrank + 1));
@@ -25568,7 +25597,7 @@ void Player::LearnPetTalent(ObjectGuid petGuid, uint32 talentId, uint32 talentRa
// learn! (other talent ranks will unlearned at learning)
pet->learnSpell(spellid);
- TC_LOG_INFO("entities.player", "PetTalentID: %u Rank: %u Spell: %u\n", talentId, talentRank, spellid);
+ TC_LOG_DEBUG("entities.player", "PetTalentID: %u Rank: %u Spell: %u\n", talentId, talentRank, spellid);
// update free talent points
pet->SetFreeTalentPoints(CurTalentPoints - (talentRank - curtalent_maxrank + 1));
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index 61141192cd1..1e928c80f3c 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -2170,7 +2170,7 @@ class Player : public Unit, public GridObject<Player>
WorldLocation GetStartPosition() const;
// currently visible objects at player client
- GuidSet m_clientGUIDs;
+ GuidUnorderedSet m_clientGUIDs;
bool HaveAtClient(WorldObject const* u) const;
diff --git a/src/server/game/Entities/Totem/Totem.cpp b/src/server/game/Entities/Totem/Totem.cpp
index 5bb13fd98cf..39a078a907f 100644
--- a/src/server/game/Entities/Totem/Totem.cpp
+++ b/src/server/game/Entities/Totem/Totem.cpp
@@ -17,9 +17,7 @@
*/
#include "Totem.h"
-#include "Log.h"
#include "Group.h"
-#include "ObjectMgr.h"
#include "Opcodes.h"
#include "Player.h"
#include "SpellMgr.h"
diff --git a/src/server/game/Entities/Transport/Transport.cpp b/src/server/game/Entities/Transport/Transport.cpp
index 84dd50c56ca..a3ed1209ce3 100644
--- a/src/server/game/Entities/Transport/Transport.cpp
+++ b/src/server/game/Entities/Transport/Transport.cpp
@@ -20,14 +20,10 @@
#include "Transport.h"
#include "MapManager.h"
#include "ObjectMgr.h"
-#include "Path.h"
#include "ScriptMgr.h"
-#include "WorldPacket.h"
#include "DBCStores.h"
-#include "World.h"
#include "GameObjectAI.h"
#include "Vehicle.h"
-#include "MapReference.h"
#include "Player.h"
#include "Cell.h"
#include "CellImpl.h"
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index fdd91368704..3e4953a188c 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -35,7 +35,6 @@
#include "InstanceSaveMgr.h"
#include "InstanceScript.h"
#include "Log.h"
-#include "MapManager.h"
#include "MoveSpline.h"
#include "MoveSplineInit.h"
#include "ObjectAccessor.h"
@@ -589,7 +588,7 @@ uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDam
// interrupting auras with AURA_INTERRUPT_FLAG_DAMAGE before checking !damage (absorbed damage breaks that type of auras)
if (spellProto)
{
- if (!(spellProto->AttributesEx4 & SPELL_ATTR4_DAMAGE_DOESNT_BREAK_AURAS))
+ if (!spellProto->HasAttribute(SPELL_ATTR4_DAMAGE_DOESNT_BREAK_AURAS))
victim->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TAKE_DAMAGE, spellProto->Id);
}
else
@@ -777,7 +776,7 @@ uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDam
if (damagetype != NODAMAGE && damage)
{
if (victim != this && victim->GetTypeId() == TYPEID_PLAYER && // does not support creature push_back
- (!spellProto || !(spellProto->AttributesEx7 & SPELL_ATTR7_NO_PUSHBACK_ON_DAMAGE)))
+ (!spellProto || !spellProto->HasAttribute(SPELL_ATTR7_NO_PUSHBACK_ON_DAMAGE)))
{
if (damagetype != DOT)
if (Spell* spell = victim->m_currentSpells[CURRENT_GENERIC_SPELL])
@@ -981,7 +980,7 @@ void Unit::CalculateSpellDamageTaken(SpellNonMeleeDamage* damageInfo, int32 dama
uint32 crTypeMask = victim->GetCreatureTypeMask();
// Spells with SPELL_ATTR4_FIXED_DAMAGE ignore resilience because their damage is based off another spell's damage.
- if (!(spellInfo->AttributesEx4 & SPELL_ATTR4_FIXED_DAMAGE))
+ if (!spellInfo->HasAttribute(SPELL_ATTR4_FIXED_DAMAGE))
{
if (IsDamageReducedByArmor(damageSchoolMask, spellInfo))
damage = CalcArmorReducedDamage(victim, damage, spellInfo, attackType);
@@ -1459,7 +1458,7 @@ bool Unit::IsDamageReducedByArmor(SpellSchoolMask schoolMask, SpellInfo const* s
if (spellInfo)
{
// there are spells with no specific attribute but they have "ignores armor" in tooltip
- if (spellInfo->AttributesCu & SPELL_ATTR0_CU_IGNORE_ARMOR)
+ if (spellInfo->HasAttribute(SPELL_ATTR0_CU_IGNORE_ARMOR))
return false;
// bleeding effects are not reduced by armor
@@ -1560,7 +1559,7 @@ uint32 Unit::CalcSpellResistance(Unit* victim, SpellSchoolMask schoolMask, Spell
return 0;
// Ignore spells that can't be resisted
- if (spellInfo && spellInfo->AttributesEx4 & SPELL_ATTR4_IGNORE_RESISTANCES)
+ if (spellInfo && spellInfo->HasAttribute(SPELL_ATTR4_IGNORE_RESISTANCES))
return 0;
uint32 const BOSS_LEVEL = 83;
@@ -2234,15 +2233,15 @@ void Unit::SendMeleeAttackStop(Unit* victim)
TC_LOG_DEBUG("entities.unit", "WORLD: Sent SMSG_ATTACKSTOP");
if (victim)
- TC_LOG_INFO("entities.unit", "%s %u stopped attacking %s %u", (GetTypeId() == TYPEID_PLAYER ? "Player" : "Creature"), GetGUIDLow(), (victim->GetTypeId() == TYPEID_PLAYER ? "player" : "creature"), victim->GetGUIDLow());
+ TC_LOG_DEBUG("entities.unit", "%s %u stopped attacking %s %u", (GetTypeId() == TYPEID_PLAYER ? "Player" : "Creature"), GetGUIDLow(), (victim->GetTypeId() == TYPEID_PLAYER ? "player" : "creature"), victim->GetGUIDLow());
else
- TC_LOG_INFO("entities.unit", "%s %u stopped attacking", (GetTypeId() == TYPEID_PLAYER ? "Player" : "Creature"), GetGUIDLow());
+ TC_LOG_DEBUG("entities.unit", "%s %u stopped attacking", (GetTypeId() == TYPEID_PLAYER ? "Player" : "Creature"), GetGUIDLow());
}
bool Unit::isSpellBlocked(Unit* victim, SpellInfo const* spellProto, WeaponAttackType attackType)
{
// These spells can't be blocked
- if (spellProto && spellProto->Attributes & SPELL_ATTR0_IMPOSSIBLE_DODGE_PARRY_BLOCK)
+ if (spellProto && spellProto->HasAttribute(SPELL_ATTR0_IMPOSSIBLE_DODGE_PARRY_BLOCK))
return false;
if (victim->HasAuraType(SPELL_AURA_IGNORE_HIT_DIRECTION) || victim->HasInArc(float(M_PI), this))
@@ -2309,7 +2308,7 @@ SpellMissInfo Unit::MeleeSpellHitResult(Unit* victim, SpellInfo const* spellInfo
{
// Spells with SPELL_ATTR3_IGNORE_HIT_RESULT will additionally fully ignore
// resist and deflect chances
- if (spellInfo->AttributesEx3 & SPELL_ATTR3_IGNORE_HIT_RESULT)
+ if (spellInfo->HasAttribute(SPELL_ATTR3_IGNORE_HIT_RESULT))
return SPELL_MISS_NONE;
WeaponAttackType attType = BASE_ATTACK;
@@ -2357,10 +2356,10 @@ SpellMissInfo Unit::MeleeSpellHitResult(Unit* victim, SpellInfo const* spellInfo
bool canDodge = true;
bool canParry = true;
- bool canBlock = (spellInfo->AttributesEx3 & SPELL_ATTR3_BLOCKABLE_SPELL) != 0;
+ bool canBlock = spellInfo->HasAttribute(SPELL_ATTR3_BLOCKABLE_SPELL);
// Same spells cannot be parry/dodge
- if (spellInfo->Attributes & SPELL_ATTR0_IMPOSSIBLE_DODGE_PARRY_BLOCK)
+ if (spellInfo->HasAttribute(SPELL_ATTR0_IMPOSSIBLE_DODGE_PARRY_BLOCK))
return SPELL_MISS_NONE;
// Chance resist mechanic
@@ -2400,7 +2399,7 @@ SpellMissInfo Unit::MeleeSpellHitResult(Unit* victim, SpellInfo const* spellInfo
}
else // Only deterrence as of 3.3.5
{
- if (spellInfo->AttributesCu & SPELL_ATTR0_CU_REQ_CASTER_BEHIND_TARGET)
+ if (spellInfo->HasAttribute(SPELL_ATTR0_CU_REQ_CASTER_BEHIND_TARGET))
canParry = false;
}
}
@@ -2491,7 +2490,7 @@ SpellMissInfo Unit::MeleeSpellHitResult(Unit* victim, SpellInfo const* spellInfo
SpellMissInfo Unit::MagicSpellHitResult(Unit* victim, SpellInfo const* spellInfo)
{
// Can`t miss on dead target (on skinning for example)
- if ((!victim->IsAlive() && victim->GetTypeId() != TYPEID_PLAYER) || spellInfo->AttributesEx3 & SPELL_ATTR3_IGNORE_HIT_RESULT)
+ if ((!victim->IsAlive() && victim->GetTypeId() != TYPEID_PLAYER) || spellInfo->HasAttribute(SPELL_ATTR3_IGNORE_HIT_RESULT))
return SPELL_MISS_NONE;
SpellSchoolMask schoolMask = spellInfo->GetSchoolMask();
@@ -3089,7 +3088,7 @@ bool Unit::IsNonMeleeSpellCast(bool withDelayed, bool skipChanneled, bool skipAu
{
if (!skipInstant || m_currentSpells[CURRENT_GENERIC_SPELL]->GetCastTime())
{
- if (!isAutoshoot || !(m_currentSpells[CURRENT_GENERIC_SPELL]->m_spellInfo->AttributesEx2 & SPELL_ATTR2_NOT_RESET_AUTO_ACTIONS))
+ if (!isAutoshoot || !(m_currentSpells[CURRENT_GENERIC_SPELL]->m_spellInfo->HasAttribute(SPELL_ATTR2_NOT_RESET_AUTO_ACTIONS)))
return true;
}
}
@@ -3097,7 +3096,7 @@ bool Unit::IsNonMeleeSpellCast(bool withDelayed, bool skipChanneled, bool skipAu
if (!skipChanneled && m_currentSpells[CURRENT_CHANNELED_SPELL] &&
(m_currentSpells[CURRENT_CHANNELED_SPELL]->getState() != SPELL_STATE_FINISHED))
{
- if (!isAutoshoot || !(m_currentSpells[CURRENT_CHANNELED_SPELL]->m_spellInfo->AttributesEx2 & SPELL_ATTR2_NOT_RESET_AUTO_ACTIONS))
+ if (!isAutoshoot || !(m_currentSpells[CURRENT_CHANNELED_SPELL]->m_spellInfo->HasAttribute(SPELL_ATTR2_NOT_RESET_AUTO_ACTIONS)))
return true;
}
// autorepeat spells may be finished or delayed, but they are still considered cast
@@ -3232,7 +3231,7 @@ Aura* Unit::_TryStackingOrRefreshingExistingAura(SpellInfo const* newAura, uint8
castItemGUID = castItem->GetGUID();
// find current aura from spell and change it's stackamount, or refresh it's duration
- if (Aura* foundAura = GetOwnedAura(newAura->Id, casterGUID, (newAura->AttributesCu & SPELL_ATTR0_CU_ENCHANT_PROC) ? castItemGUID : ObjectGuid::Empty, 0))
+ if (Aura* foundAura = GetOwnedAura(newAura->Id, casterGUID, newAura->HasAttribute(SPELL_ATTR0_CU_ENCHANT_PROC) ? castItemGUID : ObjectGuid::Empty, 0))
{
// effect masks do not match
// extremely rare case
@@ -3743,7 +3742,7 @@ void Unit::RemoveAurasDueToSpellByDispel(uint32 spellId, uint32 dispellerSpellId
// Call OnDispel hook on AuraScript
aura->CallScriptDispel(&dispelInfo);
- if (aura->GetSpellInfo()->AttributesEx7 & SPELL_ATTR7_DISPEL_CHARGES)
+ if (aura->GetSpellInfo()->HasAttribute(SPELL_ATTR7_DISPEL_CHARGES))
aura->ModCharges(-dispelInfo.GetRemovedCharges(), AURA_REMOVE_BY_ENEMY_SPELL);
else
aura->ModStackAmount(-dispelInfo.GetRemovedCharges(), AURA_REMOVE_BY_ENEMY_SPELL);
@@ -3788,7 +3787,7 @@ void Unit::RemoveAurasDueToSpellBySteal(uint32 spellId, ObjectGuid casterGUID, U
}
}
- bool stealCharge = (aura->GetSpellInfo()->AttributesEx7 & SPELL_ATTR7_DISPEL_CHARGES) != 0;
+ bool stealCharge = aura->GetSpellInfo()->HasAttribute(SPELL_ATTR7_DISPEL_CHARGES);
// Cast duration to unsigned to prevent permanent aura's such as Righteous Fury being permanently added to caster
uint32 dur = std::min(2u * MINUTE * IN_MILLISECONDS, uint32(aura->GetDuration()));
@@ -4046,9 +4045,9 @@ void Unit::RemoveArenaAuras()
{
AuraApplication const* aurApp = iter->second;
Aura const* aura = aurApp->GetBase();
- if (!(aura->GetSpellInfo()->AttributesEx4 & SPELL_ATTR4_UNK21) // don't remove stances, shadowform, pally/hunter auras
+ if (!aura->GetSpellInfo()->HasAttribute(SPELL_ATTR4_UNK21) // don't remove stances, shadowform, pally/hunter auras
&& !aura->IsPassive() // don't remove passive auras
- && (aurApp->IsPositive() || !(aura->GetSpellInfo()->AttributesEx3 & SPELL_ATTR3_DEATH_PERSISTENT))) // not negative death persistent auras
+ && (aurApp->IsPositive() || !aura->GetSpellInfo()->HasAttribute(SPELL_ATTR3_DEATH_PERSISTENT))) // not negative death persistent auras
RemoveAura(iter);
else
++iter;
@@ -4308,7 +4307,7 @@ void Unit::GetDispellableAuraList(Unit* caster, uint32 dispelMask, DispelCharges
// The charges / stack amounts don't count towards the total number of auras that can be dispelled.
// Ie: A dispel on a target with 5 stacks of Winters Chill and a Polymorph has 1 / (1 + 1) -> 50% chance to dispell
// Polymorph instead of 1 / (5 + 1) -> 16%.
- bool dispel_charges = (aura->GetSpellInfo()->AttributesEx7 & SPELL_ATTR7_DISPEL_CHARGES) != 0;
+ bool dispel_charges = aura->GetSpellInfo()->HasAttribute(SPELL_ATTR7_DISPEL_CHARGES);
uint8 charges = dispel_charges ? aura->GetCharges() : aura->GetStackAmount();
if (charges > 0)
dispelList.push_back(std::make_pair(aura, charges));
@@ -9602,7 +9601,7 @@ bool Unit::IsMagnet() const
Unit* Unit::GetMagicHitRedirectTarget(Unit* victim, SpellInfo const* spellInfo)
{
// Patch 1.2 notes: Spell Reflection no longer reflects abilities
- if (spellInfo->Attributes & SPELL_ATTR0_ABILITY || spellInfo->AttributesEx & SPELL_ATTR1_CANT_BE_REDIRECTED || spellInfo->Attributes & SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY)
+ if (spellInfo->HasAttribute(SPELL_ATTR0_ABILITY) || spellInfo->HasAttribute(SPELL_ATTR1_CANT_BE_REDIRECTED) || spellInfo->HasAttribute(SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY))
return victim;
Unit::AuraEffectList const& magnetAuras = victim->GetAuraEffectsByType(SPELL_AURA_SPELL_MAGNET);
@@ -9854,7 +9853,7 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin
return pdamage;
// Some spells don't benefit from done mods
- if (spellProto->AttributesEx3 & SPELL_ATTR3_NO_DONE_BONUS)
+ if (spellProto->HasAttribute(SPELL_ATTR3_NO_DONE_BONUS))
return pdamage;
// For totems get damage bonus from owner
@@ -9985,7 +9984,7 @@ float Unit::SpellDamagePctDone(Unit* victim, SpellInfo const* spellProto, Damage
return 1.0f;
// Some spells don't benefit from pct done mods
- if (spellProto->AttributesEx6 & SPELL_ATTR6_NO_DONE_PCT_DAMAGE_MODS)
+ if (spellProto->HasAttribute(SPELL_ATTR6_NO_DONE_PCT_DAMAGE_MODS))
return 1.0f;
// For totems pct done mods are calculated when its calculation is run on the player in SpellDamageBonusDone.
@@ -10009,7 +10008,7 @@ float Unit::SpellDamagePctDone(Unit* victim, SpellInfo const* spellProto, Damage
{
if ((*i)->GetSpellInfo()->EquippedItemClass == -1)
AddPct(DoneTotalMod, (*i)->GetAmount());
- else if (!((*i)->GetSpellInfo()->AttributesEx5 & SPELL_ATTR5_SPECIAL_ITEM_CLASS_CHECK) && ((*i)->GetSpellInfo()->EquippedItemSubClassMask == 0))
+ else if (!(*i)->GetSpellInfo()->HasAttribute(SPELL_ATTR5_SPECIAL_ITEM_CLASS_CHECK) && ((*i)->GetSpellInfo()->EquippedItemSubClassMask == 0))
AddPct(DoneTotalMod, (*i)->GetAmount());
else if (ToPlayer() && ToPlayer()->HasItemFitToSpellRequirements((*i)->GetSpellInfo()))
AddPct(DoneTotalMod, (*i)->GetAmount());
@@ -10324,7 +10323,7 @@ uint32 Unit::SpellDamageBonusTaken(Unit* caster, SpellInfo const* spellProto, ui
}
}
// Spells with SPELL_ATTR4_FIXED_DAMAGE should only benefit from mechanic damage mod auras.
- if (!(spellProto->AttributesEx4 & SPELL_ATTR4_FIXED_DAMAGE))
+ if (!spellProto->HasAttribute(SPELL_ATTR4_FIXED_DAMAGE))
{
// get all auras from caster that allow the spell to ignore resistance (sanctified wrath)
AuraEffectList const& IgnoreResistAuras = caster->GetAuraEffectsByType(SPELL_AURA_MOD_IGNORE_TARGET_RESIST);
@@ -10454,7 +10453,7 @@ float Unit::GetUnitSpellCriticalChance(Unit* victim, SpellInfo const* spellProto
return 0.0f;
// not critting spell
- if ((spellProto->AttributesEx2 & SPELL_ATTR2_CANT_CRIT))
+ if (spellProto->HasAttribute(SPELL_ATTR2_CANT_CRIT))
return 0.0f;
float crit_chance = 0.0f;
@@ -11063,7 +11062,7 @@ bool Unit::IsImmunedToDamage(SpellSchoolMask shoolMask) const
bool Unit::IsImmunedToDamage(SpellInfo const* spellInfo) const
{
- if (spellInfo->Attributes & SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY)
+ if (spellInfo->HasAttribute(SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY))
return false;
uint32 shoolMask = spellInfo->GetSchoolMask();
@@ -11096,7 +11095,7 @@ bool Unit::IsImmunedToSpell(SpellInfo const* spellInfo) const
if (itr->type == spellInfo->Id)
return true;
- if (spellInfo->Attributes & SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY)
+ if (spellInfo->HasAttribute(SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY))
return false;
if (spellInfo->Dispel)
@@ -11154,7 +11153,7 @@ bool Unit::IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index) cons
if (!spellInfo || !spellInfo->Effects[index].IsEffect())
return false;
- if (spellInfo->Attributes & SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY)
+ if (spellInfo->HasAttribute(SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY))
return false;
// If m_immuneToEffect type contain this effect type, IMMUNE effect.
@@ -11177,7 +11176,7 @@ bool Unit::IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index) cons
SpellImmuneList const& list = m_spellImmune[IMMUNITY_STATE];
for (SpellImmuneList::const_iterator itr = list.begin(); itr != list.end(); ++itr)
if (itr->type == aura)
- if (!(spellInfo->AttributesEx3 & SPELL_ATTR3_IGNORE_HIT_RESULT))
+ if (!spellInfo->HasAttribute(SPELL_ATTR3_IGNORE_HIT_RESULT))
return true;
// Check for immune to application of harmful magical effects
@@ -11252,7 +11251,7 @@ uint32 Unit::MeleeDamageBonusDone(Unit* victim, uint32 pdamage, WeaponAttackType
// Some spells don't benefit from pct done mods
if (spellProto)
- if (!(spellProto->AttributesEx6 & SPELL_ATTR6_NO_DONE_PCT_DAMAGE_MODS))
+ if (!spellProto->HasAttribute(SPELL_ATTR6_NO_DONE_PCT_DAMAGE_MODS))
{
AuraEffectList const& mModDamagePercentDone = GetAuraEffectsByType(SPELL_AURA_MOD_DAMAGE_PERCENT_DONE);
for (AuraEffectList::const_iterator i = mModDamagePercentDone.begin(); i != mModDamagePercentDone.end(); ++i)
@@ -11261,7 +11260,7 @@ uint32 Unit::MeleeDamageBonusDone(Unit* victim, uint32 pdamage, WeaponAttackType
{
if ((*i)->GetSpellInfo()->EquippedItemClass == -1)
AddPct(DoneTotalMod, (*i)->GetAmount());
- else if (!((*i)->GetSpellInfo()->AttributesEx5 & SPELL_ATTR5_SPECIAL_ITEM_CLASS_CHECK) && ((*i)->GetSpellInfo()->EquippedItemSubClassMask == 0))
+ else if (!(*i)->GetSpellInfo()->HasAttribute(SPELL_ATTR5_SPECIAL_ITEM_CLASS_CHECK) && ((*i)->GetSpellInfo()->EquippedItemSubClassMask == 0))
AddPct(DoneTotalMod, (*i)->GetAmount());
else if (ToPlayer() && ToPlayer()->HasItemFitToSpellRequirements((*i)->GetSpellInfo()))
AddPct(DoneTotalMod, (*i)->GetAmount());
@@ -11523,7 +11522,7 @@ void Unit::ApplySpellDispelImmunity(const SpellInfo* spellProto, DispelType type
{
ApplySpellImmune(spellProto->Id, IMMUNITY_DISPEL, type, apply);
- if (apply && spellProto->AttributesEx & SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY)
+ if (apply && spellProto->HasAttribute(SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY))
{
// Create dispel mask by dispel type
uint32 dispelMask = SpellInfo::GetDispelMask(type);
@@ -11864,7 +11863,7 @@ bool Unit::_IsValidAttackTarget(Unit const* target, SpellInfo const* bySpell, Wo
return false;
// can't attack invisible (ignore stealth for aoe spells) also if the area being looked at is from a spell use the dynamic object created instead of the casting unit.
- if ((!bySpell || !(bySpell->AttributesEx6 & SPELL_ATTR6_CAN_TARGET_INVISIBLE)) && (obj ? !obj->CanSeeOrDetect(target, bySpell && bySpell->IsAffectingArea()) : !CanSeeOrDetect(target, bySpell && bySpell->IsAffectingArea())))
+ if ((!bySpell || !bySpell->HasAttribute(SPELL_ATTR6_CAN_TARGET_INVISIBLE)) && (obj ? !obj->CanSeeOrDetect(target, bySpell && bySpell->IsAffectingArea()) : !CanSeeOrDetect(target, bySpell && bySpell->IsAffectingArea())))
return false;
// can't attack dead
@@ -11872,7 +11871,7 @@ bool Unit::_IsValidAttackTarget(Unit const* target, SpellInfo const* bySpell, Wo
return false;
// can't attack untargetable
- if ((!bySpell || !(bySpell->AttributesEx6 & SPELL_ATTR6_CAN_TARGET_UNTARGETABLE))
+ if ((!bySpell || !bySpell->HasAttribute(SPELL_ATTR6_CAN_TARGET_UNTARGETABLE))
&& target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE))
return false;
@@ -11981,7 +11980,7 @@ bool Unit::_IsValidAssistTarget(Unit const* target, SpellInfo const* bySpell) co
return false;
// can't assist invisible
- if ((!bySpell || !(bySpell->AttributesEx6 & SPELL_ATTR6_CAN_TARGET_INVISIBLE)) && !CanSeeOrDetect(target, bySpell && bySpell->IsAffectingArea()))
+ if ((!bySpell || !bySpell->HasAttribute(SPELL_ATTR6_CAN_TARGET_INVISIBLE)) && !CanSeeOrDetect(target, bySpell && bySpell->IsAffectingArea()))
return false;
// can't assist dead
@@ -11989,11 +11988,11 @@ bool Unit::_IsValidAssistTarget(Unit const* target, SpellInfo const* bySpell) co
return false;
// can't assist untargetable
- if ((!bySpell || !(bySpell->AttributesEx6 & SPELL_ATTR6_CAN_TARGET_UNTARGETABLE))
+ if ((!bySpell || !bySpell->HasAttribute(SPELL_ATTR6_CAN_TARGET_UNTARGETABLE))
&& target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE))
return false;
- if (!bySpell || !(bySpell->AttributesEx6 & SPELL_ATTR6_ASSIST_IGNORE_IMMUNE_FLAG))
+ if (!bySpell || !bySpell->HasAttribute(SPELL_ATTR6_ASSIST_IGNORE_IMMUNE_FLAG))
{
if (HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE))
{
@@ -12040,7 +12039,7 @@ bool Unit::_IsValidAssistTarget(Unit const* target, SpellInfo const* bySpell) co
// PvC case - player can assist creature only if has specific type flags
// !target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE) &&
else if (HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE)
- && (!bySpell || !(bySpell->AttributesEx6 & SPELL_ATTR6_ASSIST_IGNORE_IMMUNE_FLAG))
+ && (!bySpell || !bySpell->HasAttribute(SPELL_ATTR6_ASSIST_IGNORE_IMMUNE_FLAG))
&& !((target->GetByteValue(UNIT_FIELD_BYTES_2, 1) & UNIT_BYTE2_FLAG_PVP)))
{
if (Creature const* creatureTarget = target->ToCreature())
@@ -12822,7 +12821,7 @@ int32 Unit::ModSpellDuration(SpellInfo const* spellProto, Unit const* target, in
return duration;
// some auras are not affected by duration modifiers
- if (spellProto->AttributesEx7 & SPELL_ATTR7_IGNORE_DURATION_MODS)
+ if (spellProto->HasAttribute(SPELL_ATTR7_IGNORE_DURATION_MODS))
return duration;
// cut duration only of negative effects
@@ -12926,17 +12925,17 @@ void Unit::ModSpellCastTime(SpellInfo const* spellInfo, int32 & castTime, Spell*
if (!spellInfo || castTime < 0)
return;
- if (spellInfo->IsChanneled() && !(spellInfo->AttributesEx5 & SPELL_ATTR5_HASTE_AFFECT_DURATION))
+ if (spellInfo->IsChanneled() && !spellInfo->HasAttribute(SPELL_ATTR5_HASTE_AFFECT_DURATION))
return;
// called from caster
if (Player* modOwner = GetSpellModOwner())
modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_CASTING_TIME, castTime, spell);
- if (!((spellInfo->Attributes & (SPELL_ATTR0_ABILITY | SPELL_ATTR0_TRADESPELL)) || (spellInfo->AttributesEx3 & SPELL_ATTR3_NO_DONE_BONUS)) &&
+ if (!(spellInfo->HasAttribute(SPELL_ATTR0_ABILITY) || spellInfo->HasAttribute(SPELL_ATTR0_TRADESPELL) || spellInfo->HasAttribute(SPELL_ATTR0_TRADESPELL) || spellInfo->HasAttribute(SPELL_ATTR3_NO_DONE_BONUS)) &&
((GetTypeId() == TYPEID_PLAYER && spellInfo->SpellFamilyName) || GetTypeId() == TYPEID_UNIT))
castTime = int32(float(castTime) * GetFloatValue(UNIT_MOD_CAST_SPEED));
- else if (spellInfo->Attributes & SPELL_ATTR0_REQ_AMMO && !(spellInfo->AttributesEx2 & SPELL_ATTR2_AUTOREPEAT_FLAG))
+ else if (spellInfo->HasAttribute(SPELL_ATTR0_REQ_AMMO) && !spellInfo->HasAttribute(SPELL_ATTR2_AUTOREPEAT_FLAG))
castTime = int32(float(castTime) * m_modAttackSpeedPct[RANGED_ATTACK]);
else if (spellInfo->SpellVisual[0] == 3881 && HasAura(67556)) // cooking with Chef Hat.
castTime = 500;
@@ -13711,7 +13710,7 @@ void CharmInfo::InitPossessCreateSpells()
{
uint32 spellId = _unit->ToCreature()->m_spells[i];
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
- if (spellInfo && !(spellInfo->Attributes & SPELL_ATTR0_CASTABLE_WHILE_DEAD))
+ if (spellInfo && !spellInfo->HasAttribute(SPELL_ATTR0_CASTABLE_WHILE_DEAD))
{
if (spellInfo->IsPassive())
_unit->CastSpell(_unit, spellInfo, true);
@@ -13739,7 +13738,7 @@ void CharmInfo::InitCharmCreateSpells()
uint32 spellId = _unit->ToCreature()->m_spells[x];
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
- if (!spellInfo || spellInfo->Attributes & SPELL_ATTR0_CASTABLE_WHILE_DEAD)
+ if (!spellInfo || spellInfo->HasAttribute(SPELL_ATTR0_CASTABLE_WHILE_DEAD))
{
_charmspells[x].SetActionAndType(spellId, ACT_DISABLED);
continue;
@@ -14126,7 +14125,7 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u
continue;
// Triggered spells not triggering additional spells
- bool triggered = !(spellProto->AttributesEx3 & SPELL_ATTR3_CAN_PROC_WITH_TRIGGERED) ?
+ bool triggered = !spellProto->HasAttribute(SPELL_ATTR3_CAN_PROC_WITH_TRIGGERED) ?
(procExtra & PROC_EX_INTERNAL_TRIGGERED && !(procFlag & PROC_FLAG_DONE_TRAP_ACTIVATION)) : false;
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
@@ -14183,7 +14182,7 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u
cooldown = i->spellProcEvent->cooldown;
// Note: must SetCantProc(false) before return
- if (spellInfo->AttributesEx3 & SPELL_ATTR3_DISABLE_PROC)
+ if (spellInfo->HasAttribute(SPELL_ATTR3_DISABLE_PROC))
SetCantProc(true);
bool handled = i->aura->CallScriptProcHandlers(aurApp, eventInfo);
@@ -14378,7 +14377,7 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u
i->aura->CallScriptAfterProcHandlers(aurApp, eventInfo);
- if (spellInfo->AttributesEx3 & SPELL_ATTR3_DISABLE_PROC)
+ if (spellInfo->HasAttribute(SPELL_ATTR3_DISABLE_PROC))
SetCantProc(false);
}
@@ -15053,7 +15052,7 @@ 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->AttributesEx3 & SPELL_ATTR3_CAN_PROC_WITH_TRIGGERED))
+ if (!spellProto->HasAttribute(SPELL_ATTR3_CAN_PROC_WITH_TRIGGERED))
return false;
}
@@ -16213,7 +16212,7 @@ Aura* Unit::AddAura(uint32 spellId, Unit* target)
if (!spellInfo)
return NULL;
- if (!target->IsAlive() && !(spellInfo->Attributes & SPELL_ATTR0_PASSIVE) && !(spellInfo->AttributesEx2 & SPELL_ATTR2_CAN_TARGET_DEAD))
+ if (!target->IsAlive() && !spellInfo->HasAttribute(SPELL_ATTR0_PASSIVE) && !spellInfo->HasAttribute(SPELL_ATTR2_CAN_TARGET_DEAD))
return NULL;
return AddAura(spellInfo, MAX_EFFECT_MASK, target);
@@ -17316,30 +17315,30 @@ void Unit::StopAttackFaction(uint32 faction_id)
void Unit::OutDebugInfo() const
{
TC_LOG_ERROR("entities.unit", "Unit::OutDebugInfo");
- TC_LOG_INFO("entities.unit", "%s name %s", GetGUID().ToString().c_str(), GetName().c_str());
- TC_LOG_INFO("entities.unit", "Owner %s, Minion %s, Charmer %s, Charmed %s", GetOwnerGUID().ToString().c_str(), GetMinionGUID().ToString().c_str(), GetCharmerGUID().ToString().c_str(), GetCharmGUID().ToString().c_str());
- TC_LOG_INFO("entities.unit", "In world %u, unit type mask %u", (uint32)(IsInWorld() ? 1 : 0), m_unitTypeMask);
+ TC_LOG_DEBUG("entities.unit", "%s name %s", GetGUID().ToString().c_str(), GetName().c_str());
+ TC_LOG_DEBUG("entities.unit", "Owner %s, Minion %s, Charmer %s, Charmed %s", GetOwnerGUID().ToString().c_str(), GetMinionGUID().ToString().c_str(), GetCharmerGUID().ToString().c_str(), GetCharmGUID().ToString().c_str());
+ TC_LOG_DEBUG("entities.unit", "In world %u, unit type mask %u", (uint32)(IsInWorld() ? 1 : 0), m_unitTypeMask);
if (IsInWorld())
- TC_LOG_INFO("entities.unit", "Mapid %u", GetMapId());
+ TC_LOG_DEBUG("entities.unit", "Mapid %u", GetMapId());
std::ostringstream o;
o << "Summon Slot: ";
for (uint32 i = 0; i < MAX_SUMMON_SLOT; ++i)
o << m_SummonSlot[i].ToString() << ", ";
- TC_LOG_INFO("entities.unit", "%s", o.str().c_str());
+ TC_LOG_DEBUG("entities.unit", "%s", o.str().c_str());
o.str("");
o << "Controlled List: ";
for (ControlList::const_iterator itr = m_Controlled.begin(); itr != m_Controlled.end(); ++itr)
o << (*itr)->GetGUID().ToString() << ", ";
- TC_LOG_INFO("entities.unit", "%s", o.str().c_str());
+ TC_LOG_DEBUG("entities.unit", "%s", o.str().c_str());
o.str("");
o << "Aura List: ";
for (AuraApplicationMap::const_iterator itr = m_appliedAuras.begin(); itr != m_appliedAuras.end(); ++itr)
o << itr->first << ", ";
- TC_LOG_INFO("entities.unit", "%s", o.str().c_str());
+ TC_LOG_DEBUG("entities.unit", "%s", o.str().c_str());
o.str("");
if (IsVehicle())
@@ -17348,11 +17347,11 @@ void Unit::OutDebugInfo() const
for (SeatMap::iterator itr = GetVehicleKit()->Seats.begin(); itr != GetVehicleKit()->Seats.end(); ++itr)
if (Unit* passenger = ObjectAccessor::GetUnit(*GetVehicleBase(), itr->second.Passenger.Guid))
o << passenger->GetGUID().ToString() << ", ";
- TC_LOG_INFO("entities.unit", "%s", o.str().c_str());
+ TC_LOG_DEBUG("entities.unit", "%s", o.str().c_str());
}
if (GetVehicle())
- TC_LOG_INFO("entities.unit", "On vehicle %u.", GetVehicleBase()->GetEntry());
+ TC_LOG_DEBUG("entities.unit", "On vehicle %u.", GetVehicleBase()->GetEntry());
}
uint32 Unit::GetRemainingPeriodicAmount(ObjectGuid caster, uint32 spellId, AuraType auraType, uint8 effectIndex) const
diff --git a/src/server/game/Entities/Vehicle/Vehicle.cpp b/src/server/game/Entities/Vehicle/Vehicle.cpp
index 9887f303357..b6f9534ac51 100755
--- a/src/server/game/Entities/Vehicle/Vehicle.cpp
+++ b/src/server/game/Entities/Vehicle/Vehicle.cpp
@@ -22,12 +22,8 @@
#include "Vehicle.h"
#include "Unit.h"
#include "Util.h"
-#include "WorldPacket.h"
#include "ScriptMgr.h"
#include "CreatureAI.h"
-#include "ZoneScript.h"
-#include "SpellMgr.h"
-#include "SpellInfo.h"
#include "MoveSplineInit.h"
#include "TemporarySummon.h"
#include "EventProcessor.h"
diff --git a/src/server/game/Events/GameEventMgr.cpp b/src/server/game/Events/GameEventMgr.cpp
index ba82c61e7ff..2264612f89b 100644
--- a/src/server/game/Events/GameEventMgr.cpp
+++ b/src/server/game/Events/GameEventMgr.cpp
@@ -24,7 +24,6 @@
#include "Language.h"
#include "Log.h"
#include "MapManager.h"
-#include "GossipDef.h"
#include "Player.h"
#include "BattlegroundMgr.h"
#include "UnitAI.h"
diff --git a/src/server/game/Globals/ObjectAccessor.cpp b/src/server/game/Globals/ObjectAccessor.cpp
index 88cc201ebf8..859633b16c4 100644
--- a/src/server/game/Globals/ObjectAccessor.cpp
+++ b/src/server/game/Globals/ObjectAccessor.cpp
@@ -20,28 +20,20 @@
#include <boost/thread/locks.hpp>
#include "ObjectAccessor.h"
-#include "CellImpl.h"
#include "Corpse.h"
#include "Creature.h"
#include "DynamicObject.h"
#include "GameObject.h"
#include "GridNotifiers.h"
-#include "GridNotifiersImpl.h"
#include "Item.h"
#include "Map.h"
-#include "MapInstanced.h"
-#include "MapManager.h"
#include "ObjectDefines.h"
#include "ObjectMgr.h"
-#include "Opcodes.h"
#include "Pet.h"
#include "Player.h"
-#include "Vehicle.h"
#include "World.h"
#include "WorldPacket.h"
-#include <cmath>
-
ObjectAccessor::ObjectAccessor() { }
ObjectAccessor::~ObjectAccessor() { }
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp
index f0d7d039dd5..f74201fee60 100644
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -8601,7 +8601,6 @@ void ObjectMgr::LoadBroadcastTexts()
}
_broadcastTextStore.rehash(result->GetRowCount());
- uint32 count = 0;
do
{
@@ -8627,26 +8626,23 @@ void ObjectMgr::LoadBroadcastTexts()
{
if (!sSoundEntriesStore.LookupEntry(bct.SoundId))
{
- TC_LOG_INFO("sql.sql", "BroadcastText (Id: %u) in table `broadcast_text` has SoundId %u but sound does not exist. Skipped.", bct.Id, bct.SoundId);
- // don't load bct of higher expansions
- continue;
+ TC_LOG_DEBUG("broadcasttext", "BroadcastText (Id: %u) in table `broadcast_text` has SoundId %u but sound does not exist.", bct.Id, bct.SoundId);
+ bct.SoundId = 0;
}
}
if (!GetLanguageDescByID(bct.Language))
{
- TC_LOG_INFO("sql.sql", "BroadcastText (Id: %u) in table `broadcast_text` using Language %u but Language does not exist. Skipped.", bct.Id, bct.Language);
- // don't load bct of higher expansions
- continue;
+ TC_LOG_DEBUG("broadcasttext", "BroadcastText (Id: %u) in table `broadcast_text` using Language %u but Language does not exist.", bct.Id, bct.Language);
+ bct.Language = LANG_UNIVERSAL;
}
if (bct.EmoteId0)
{
if (!sEmotesStore.LookupEntry(bct.EmoteId0))
{
- TC_LOG_INFO("sql.sql", "BroadcastText (Id: %u) in table `broadcast_text` has EmoteId0 %u but emote does not exist. Skipped.", bct.Id, bct.EmoteId0);
- // don't load bct of higher expansions
- continue;
+ TC_LOG_DEBUG("broadcasttext", "BroadcastText (Id: %u) in table `broadcast_text` has EmoteId0 %u but emote does not exist.", bct.Id, bct.EmoteId0);
+ bct.EmoteId0 = 0;
}
}
@@ -8654,9 +8650,8 @@ void ObjectMgr::LoadBroadcastTexts()
{
if (!sEmotesStore.LookupEntry(bct.EmoteId1))
{
- TC_LOG_INFO("sql.sql", "BroadcastText (Id: %u) in table `broadcast_text` has EmoteId1 %u but emote does not exist. Skipped.", bct.Id, bct.EmoteId1);
- // don't load bct of higher expansions
- continue;
+ TC_LOG_DEBUG("broadcasttext", "BroadcastText (Id: %u) in table `broadcast_text` has EmoteId1 %u but emote does not exist.", bct.Id, bct.EmoteId1);
+ bct.EmoteId1 = 0;
}
}
@@ -8664,19 +8659,16 @@ void ObjectMgr::LoadBroadcastTexts()
{
if (!sEmotesStore.LookupEntry(bct.EmoteId2))
{
- TC_LOG_INFO("sql.sql", "BroadcastText (Id: %u) in table `broadcast_text` has EmoteId2 %u but emote does not exist. Skipped.", bct.Id, bct.EmoteId2);
- // don't load bct of higher expansions
- continue;
+ TC_LOG_DEBUG("broadcasttext", "BroadcastText (Id: %u) in table `broadcast_text` has EmoteId2 %u but emote does not exist.", bct.Id, bct.EmoteId2);
+ bct.EmoteId2 = 0;
}
}
_broadcastTextStore[bct.Id] = bct;
-
- ++count;
}
while (result->NextRow());
- TC_LOG_INFO("server.loading", ">> Loaded %u broadcast texts in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
+ TC_LOG_INFO("server.loading", ">> Loaded " SZFMTD " broadcast texts in %u ms", _broadcastTextStore.size(), GetMSTimeDiffToNow(oldMSTime));
}
void ObjectMgr::LoadBroadcastTextLocales()
@@ -8702,8 +8694,7 @@ void ObjectMgr::LoadBroadcastTextLocales()
BroadcastTextContainer::iterator bct = _broadcastTextStore.find(id);
if (bct == _broadcastTextStore.end())
{
- TC_LOG_INFO("sql.sql", "BroadcastText (Id: %u) in table `locales_broadcast_text` does not exist or is incompatible. Skipped!", id);
- // don't load bct of higher expansions
+ TC_LOG_ERROR("sql.sql", "BroadcastText (Id: %u) in table `locales_broadcast_text` does not exist. Skipped!", id);
continue;
}
diff --git a/src/server/game/Grids/Notifiers/GridNotifiers.cpp b/src/server/game/Grids/Notifiers/GridNotifiers.cpp
index e14910bdf5e..d52e559c408 100644
--- a/src/server/game/Grids/Notifiers/GridNotifiers.cpp
+++ b/src/server/game/Grids/Notifiers/GridNotifiers.cpp
@@ -21,12 +21,9 @@
#include "WorldPacket.h"
#include "WorldSession.h"
#include "UpdateData.h"
-#include "Item.h"
-#include "Map.h"
#include "Transport.h"
#include "ObjectAccessor.h"
#include "CellImpl.h"
-#include "SpellInfo.h"
using namespace Trinity;
@@ -65,7 +62,7 @@ void VisibleNotifier::SendToSelf()
}
}
- for (GuidSet::const_iterator it = vis_guids.begin(); it != vis_guids.end(); ++it)
+ for (auto it = vis_guids.begin(); it != vis_guids.end(); ++it)
{
i_player.m_clientGUIDs.erase(*it);
i_data.AddOutOfRangeGUID(*it);
diff --git a/src/server/game/Grids/Notifiers/GridNotifiers.h b/src/server/game/Grids/Notifiers/GridNotifiers.h
index 5eb726084b3..ccf9748e67a 100644
--- a/src/server/game/Grids/Notifiers/GridNotifiers.h
+++ b/src/server/game/Grids/Notifiers/GridNotifiers.h
@@ -43,7 +43,7 @@ namespace Trinity
Player &i_player;
UpdateData i_data;
std::set<Unit*> i_visibleNow;
- GuidSet vis_guids;
+ GuidUnorderedSet vis_guids;
VisibleNotifier(Player &player) : i_player(player), vis_guids(player.m_clientGUIDs) { }
template<class T> void Visit(GridRefManager<T> &m);
diff --git a/src/server/game/Grids/ObjectGridLoader.cpp b/src/server/game/Grids/ObjectGridLoader.cpp
index 779688402b6..c7e1056a3ef 100644
--- a/src/server/game/Grids/ObjectGridLoader.cpp
+++ b/src/server/game/Grids/ObjectGridLoader.cpp
@@ -20,7 +20,6 @@
#include "ObjectAccessor.h"
#include "ObjectMgr.h"
#include "Creature.h"
-#include "Vehicle.h"
#include "GameObject.h"
#include "DynamicObject.h"
#include "Corpse.h"
diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp
index 5664cbb6e4b..ae8712510c9 100644
--- a/src/server/game/Groups/Group.cpp
+++ b/src/server/game/Groups/Group.cpp
@@ -31,7 +31,6 @@
#include "BattlegroundMgr.h"
#include "MapManager.h"
#include "InstanceSaveMgr.h"
-#include "MapInstanced.h"
#include "Util.h"
#include "LFGMgr.h"
#include "UpdateFieldFlags.h"
diff --git a/src/server/game/Handlers/AddonHandler.cpp b/src/server/game/Handlers/AddonHandler.cpp
index 8d5e07c4d3b..adb76846379 100644
--- a/src/server/game/Handlers/AddonHandler.cpp
+++ b/src/server/game/Handlers/AddonHandler.cpp
@@ -18,7 +18,6 @@
#include "zlib.h"
#include "AddonHandler.h"
-#include "DatabaseEnv.h"
#include "Opcodes.h"
#include "Log.h"
diff --git a/src/server/game/Handlers/BattlefieldHandler.cpp b/src/server/game/Handlers/BattlefieldHandler.cpp
index c7ffac217c4..69e36e7328d 100644
--- a/src/server/game/Handlers/BattlefieldHandler.cpp
+++ b/src/server/game/Handlers/BattlefieldHandler.cpp
@@ -15,8 +15,6 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "ObjectAccessor.h"
-#include "ObjectMgr.h"
#include "Opcodes.h"
#include "Player.h"
#include "WorldPacket.h"
diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp
index ee8e051ecd9..f103537710f 100644
--- a/src/server/game/Handlers/CharacterHandler.cpp
+++ b/src/server/game/Handlers/CharacterHandler.cpp
@@ -28,7 +28,6 @@
#include "Guild.h"
#include "GuildMgr.h"
#include "Language.h"
-#include "LFGMgr.h"
#include "Log.h"
#include "ObjectAccessor.h"
#include "ObjectMgr.h"
diff --git a/src/server/game/Handlers/ChatHandler.cpp b/src/server/game/Handlers/ChatHandler.cpp
index f5264bde755..2acbaba1f67 100644
--- a/src/server/game/Handlers/ChatHandler.cpp
+++ b/src/server/game/Handlers/ChatHandler.cpp
@@ -34,7 +34,6 @@
#include "Log.h"
#include "Opcodes.h"
#include "Player.h"
-#include "SpellAuras.h"
#include "SpellAuraEffects.h"
#include "Util.h"
#include "ScriptMgr.h"
diff --git a/src/server/game/Handlers/CombatHandler.cpp b/src/server/game/Handlers/CombatHandler.cpp
index ea990c83f46..39ba593c8d9 100644
--- a/src/server/game/Handlers/CombatHandler.cpp
+++ b/src/server/game/Handlers/CombatHandler.cpp
@@ -22,9 +22,7 @@
#include "WorldSession.h"
#include "ObjectAccessor.h"
#include "CreatureAI.h"
-#include "ObjectDefines.h"
#include "Vehicle.h"
-#include "VehicleDefines.h"
#include "Player.h"
#include "Opcodes.h"
diff --git a/src/server/game/Handlers/DuelHandler.cpp b/src/server/game/Handlers/DuelHandler.cpp
index 37d89274909..954fb66a9db 100644
--- a/src/server/game/Handlers/DuelHandler.cpp
+++ b/src/server/game/Handlers/DuelHandler.cpp
@@ -20,8 +20,6 @@
#include "WorldPacket.h"
#include "WorldSession.h"
#include "Log.h"
-#include "Opcodes.h"
-#include "UpdateData.h"
#include "Player.h"
void WorldSession::HandleDuelAcceptedOpcode(WorldPacket& recvPacket)
diff --git a/src/server/game/Handlers/GuildHandler.cpp b/src/server/game/Handlers/GuildHandler.cpp
index 6b770b58827..ca7b4a5f8cf 100644
--- a/src/server/game/Handlers/GuildHandler.cpp
+++ b/src/server/game/Handlers/GuildHandler.cpp
@@ -23,10 +23,7 @@
#include "ObjectMgr.h"
#include "GuildMgr.h"
#include "Log.h"
-#include "Opcodes.h"
#include "Guild.h"
-#include "GossipDef.h"
-#include "SocialMgr.h"
void WorldSession::HandleGuildQueryOpcode(WorldPacket& recvPacket)
{
diff --git a/src/server/game/Handlers/ItemHandler.cpp b/src/server/game/Handlers/ItemHandler.cpp
index a24f247c79d..672e1c69920 100644
--- a/src/server/game/Handlers/ItemHandler.cpp
+++ b/src/server/game/Handlers/ItemHandler.cpp
@@ -24,8 +24,6 @@
#include "ObjectMgr.h"
#include "Player.h"
#include "Item.h"
-#include "UpdateData.h"
-#include "ObjectAccessor.h"
#include "SpellInfo.h"
void WorldSession::HandleSplitItemOpcode(WorldPacket& recvData)
diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp
index e541b9d7625..7b8ce80ccd7 100644
--- a/src/server/game/Handlers/MiscHandler.cpp
+++ b/src/server/game/Handlers/MiscHandler.cpp
@@ -28,9 +28,6 @@
#include "ObjectMgr.h"
#include "GuildMgr.h"
#include "WorldSession.h"
-#include "BigNumber.h"
-#include "SHA1.h"
-#include "UpdateData.h"
#include "LootMgr.h"
#include "Chat.h"
#include "zlib.h"
@@ -38,19 +35,14 @@
#include "Object.h"
#include "Battleground.h"
#include "OutdoorPvP.h"
-#include "Pet.h"
#include "SocialMgr.h"
-#include "CellImpl.h"
#include "AccountMgr.h"
-#include "Vehicle.h"
#include "CreatureAI.h"
#include "DBCEnums.h"
#include "ScriptMgr.h"
#include "MapManager.h"
-#include "InstanceScript.h"
#include "GameObjectAI.h"
#include "Group.h"
-#include "AccountMgr.h"
#include "Spell.h"
#include "BattlegroundMgr.h"
#include "Battlefield.h"
diff --git a/src/server/game/Handlers/MovementHandler.cpp b/src/server/game/Handlers/MovementHandler.cpp
index f537af4b46e..e86fa523f68 100644
--- a/src/server/game/Handlers/MovementHandler.cpp
+++ b/src/server/game/Handlers/MovementHandler.cpp
@@ -23,7 +23,6 @@
#include "Log.h"
#include "Corpse.h"
#include "Player.h"
-#include "SpellAuras.h"
#include "MapManager.h"
#include "Transport.h"
#include "Battleground.h"
diff --git a/src/server/game/Handlers/NPCHandler.cpp b/src/server/game/Handlers/NPCHandler.cpp
index 0300759a6e6..3c4bbd87b3f 100644
--- a/src/server/game/Handlers/NPCHandler.cpp
+++ b/src/server/game/Handlers/NPCHandler.cpp
@@ -27,8 +27,6 @@
#include "SpellMgr.h"
#include "Player.h"
#include "GossipDef.h"
-#include "UpdateMask.h"
-#include "ObjectAccessor.h"
#include "Creature.h"
#include "Pet.h"
#include "ReputationMgr.h"
diff --git a/src/server/game/Handlers/PetHandler.cpp b/src/server/game/Handlers/PetHandler.cpp
index 0fcaa47a5e2..9ff2041ee92 100644
--- a/src/server/game/Handlers/PetHandler.cpp
+++ b/src/server/game/Handlers/PetHandler.cpp
@@ -70,7 +70,7 @@ void WorldSession::HandlePetAction(WorldPacket& recvData)
// used also for charmed creature
Unit* pet = ObjectAccessor::GetUnit(*_player, guid1);
- TC_LOG_INFO("network", "HandlePetAction: %s - flag: %u, spellid: %u, target: %s.", guid1.ToString().c_str(), uint32(flag), spellid, guid2.ToString().c_str());
+ TC_LOG_DEBUG("network", "HandlePetAction: %s - flag: %u, spellid: %u, target: %s.", guid1.ToString().c_str(), uint32(flag), spellid, guid2.ToString().c_str());
if (!pet)
{
@@ -89,7 +89,7 @@ void WorldSession::HandlePetAction(WorldPacket& recvData)
SpellInfo const* spell = (flag == ACT_ENABLED || flag == ACT_PASSIVE) ? sSpellMgr->GetSpellInfo(spellid) : NULL;
if (!spell)
return;
- if (!(spell->Attributes & SPELL_ATTR0_CASTABLE_WHILE_DEAD))
+ if (!spell->HasAttribute(SPELL_ATTR0_CASTABLE_WHILE_DEAD))
return;
}
@@ -398,7 +398,7 @@ void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spe
void WorldSession::HandlePetNameQuery(WorldPacket& recvData)
{
- TC_LOG_INFO("network", "HandlePetNameQuery. CMSG_PET_NAME_QUERY");
+ TC_LOG_DEBUG("network", "WORLD: Received CMSG_PET_NAME_QUERY");
uint32 petnumber;
ObjectGuid petguid;
@@ -465,7 +465,7 @@ bool WorldSession::CheckStableMaster(ObjectGuid guid)
void WorldSession::HandlePetSetAction(WorldPacket& recvData)
{
- TC_LOG_INFO("network", "HandlePetSetAction. CMSG_PET_SET_ACTION");
+ TC_LOG_DEBUG("network", "WORLD: Received CMSG_PET_SET_ACTION");
ObjectGuid petguid;
uint8 count;
@@ -545,7 +545,7 @@ void WorldSession::HandlePetSetAction(WorldPacket& recvData)
uint32 spell_id = UNIT_ACTION_BUTTON_ACTION(data[i]);
uint8 act_state = UNIT_ACTION_BUTTON_TYPE(data[i]);
- TC_LOG_INFO("network", "Player %s has changed pet spell action. Position: %u, Spell: %u, State: 0x%X",
+ TC_LOG_DEBUG("network", "Player %s has changed pet spell action. Position: %u, Spell: %u, State: 0x%X",
_player->GetName().c_str(), position[i], spell_id, uint32(act_state));
//if it's act for spell (en/disable/cast) and there is a spell given (0 = remove spell) which pet doesn't know, don't add
@@ -582,7 +582,7 @@ void WorldSession::HandlePetSetAction(WorldPacket& recvData)
void WorldSession::HandlePetRename(WorldPacket& recvData)
{
- TC_LOG_INFO("network", "HandlePetRename. CMSG_PET_RENAME");
+ TC_LOG_DEBUG("network", "WORLD: Received CMSG_PET_RENAME");
ObjectGuid petguid;
uint8 isdeclined;
@@ -670,7 +670,7 @@ void WorldSession::HandlePetAbandon(WorldPacket& recvData)
{
ObjectGuid guid;
recvData >> guid; //pet guid
- TC_LOG_INFO("network", "HandlePetAbandon. CMSG_PET_ABANDON %s", guid.ToString().c_str());
+ TC_LOG_DEBUG("network", "WORLD: Received CMSG_PET_ABANDON %s", guid.ToString().c_str());
if (!_player->IsInWorld())
return;
@@ -696,7 +696,7 @@ void WorldSession::HandlePetAbandon(WorldPacket& recvData)
void WorldSession::HandlePetSpellAutocastOpcode(WorldPacket& recvPacket)
{
- TC_LOG_INFO("network", "CMSG_PET_SPELL_AUTOCAST");
+ TC_LOG_DEBUG("network", "WORLD: Received CMSG_PET_SPELL_AUTOCAST");
ObjectGuid guid;
uint32 spellid;
uint8 state; //1 for on, 0 for off
@@ -744,7 +744,7 @@ void WorldSession::HandlePetSpellAutocastOpcode(WorldPacket& recvPacket)
void WorldSession::HandlePetCastSpellOpcode(WorldPacket& recvPacket)
{
- TC_LOG_DEBUG("network", "WORLD: CMSG_PET_CAST_SPELL");
+ TC_LOG_DEBUG("network", "WORLD: Received CMSG_PET_CAST_SPELL");
ObjectGuid guid;
uint8 castCount;
@@ -846,7 +846,7 @@ void WorldSession::SendPetNameInvalid(uint32 error, const std::string& name, Dec
void WorldSession::HandlePetLearnTalent(WorldPacket& recvData)
{
- TC_LOG_DEBUG("network", "WORLD: CMSG_PET_LEARN_TALENT");
+ TC_LOG_DEBUG("network", "WORLD: Received CMSG_PET_LEARN_TALENT");
ObjectGuid guid;
uint32 talentId, requestedRank;
@@ -858,7 +858,7 @@ void WorldSession::HandlePetLearnTalent(WorldPacket& recvData)
void WorldSession::HandleLearnPreviewTalentsPet(WorldPacket& recvData)
{
- TC_LOG_DEBUG("network", "CMSG_LEARN_PREVIEW_TALENTS_PET");
+ TC_LOG_DEBUG("network", "WORLD: Received CMSG_LEARN_PREVIEW_TALENTS_PET");
ObjectGuid guid;
recvData >> guid;
diff --git a/src/server/game/Handlers/PetitionsHandler.cpp b/src/server/game/Handlers/PetitionsHandler.cpp
index 1bf081900ee..05e793455da 100644
--- a/src/server/game/Handlers/PetitionsHandler.cpp
+++ b/src/server/game/Handlers/PetitionsHandler.cpp
@@ -28,8 +28,6 @@
#include "Opcodes.h"
#include "Guild.h"
#include "ArenaTeam.h"
-#include "GossipDef.h"
-#include "SocialMgr.h"
#define CHARTER_DISPLAY_ID 16161
diff --git a/src/server/game/Handlers/QueryHandler.cpp b/src/server/game/Handlers/QueryHandler.cpp
index ed41d2ebeed..d15f21f4ad3 100644
--- a/src/server/game/Handlers/QueryHandler.cpp
+++ b/src/server/game/Handlers/QueryHandler.cpp
@@ -17,7 +17,6 @@
*/
#include "Common.h"
-#include "Language.h"
#include "DatabaseEnv.h"
#include "WorldPacket.h"
#include "WorldSession.h"
@@ -28,7 +27,6 @@
#include "Player.h"
#include "UpdateMask.h"
#include "NPCHandler.h"
-#include "Pet.h"
#include "MapManager.h"
void WorldSession::SendNameQueryOpcode(ObjectGuid guid)
diff --git a/src/server/game/Handlers/QuestHandler.cpp b/src/server/game/Handlers/QuestHandler.cpp
index b6157d6eb94..3c6258b2d7c 100644
--- a/src/server/game/Handlers/QuestHandler.cpp
+++ b/src/server/game/Handlers/QuestHandler.cpp
@@ -627,7 +627,7 @@ void WorldSession::HandleQuestgiverStatusMultipleQuery(WorldPacket& /*recvPacket
WorldPacket data(SMSG_QUESTGIVER_STATUS_MULTIPLE, 4);
data << uint32(count); // placeholder
- for (GuidSet::const_iterator itr = _player->m_clientGUIDs.begin(); itr != _player->m_clientGUIDs.end(); ++itr)
+ for (auto itr = _player->m_clientGUIDs.begin(); itr != _player->m_clientGUIDs.end(); ++itr)
{
uint32 questStatus = DIALOG_STATUS_NONE;
diff --git a/src/server/game/Handlers/SkillHandler.cpp b/src/server/game/Handlers/SkillHandler.cpp
index 23ce233a905..6da2efa38a6 100644
--- a/src/server/game/Handlers/SkillHandler.cpp
+++ b/src/server/game/Handlers/SkillHandler.cpp
@@ -17,13 +17,11 @@
*/
#include "Common.h"
-#include "DatabaseEnv.h"
#include "Log.h"
#include "ObjectAccessor.h"
#include "Opcodes.h"
#include "Player.h"
#include "Pet.h"
-#include "UpdateMask.h"
#include "WorldPacket.h"
#include "WorldSession.h"
diff --git a/src/server/game/Handlers/SpellHandler.cpp b/src/server/game/Handlers/SpellHandler.cpp
index c4bd892d3cf..5f641bf713f 100644
--- a/src/server/game/Handlers/SpellHandler.cpp
+++ b/src/server/game/Handlers/SpellHandler.cpp
@@ -26,9 +26,6 @@
#include "Opcodes.h"
#include "Spell.h"
#include "Totem.h"
-#include "TemporarySummon.h"
-#include "SpellAuras.h"
-#include "CreatureAI.h"
#include "ScriptMgr.h"
#include "GameObjectAI.h"
#include "SpellAuraEffects.h"
@@ -417,7 +414,7 @@ void WorldSession::HandleCancelAuraOpcode(WorldPacket& recvPacket)
return;
// not allow remove spells with attr SPELL_ATTR0_CANT_CANCEL
- if (spellInfo->Attributes & SPELL_ATTR0_CANT_CANCEL)
+ if (spellInfo->HasAttribute(SPELL_ATTR0_CANT_CANCEL))
return;
// channeled spell case (it currently cast then)
diff --git a/src/server/game/Handlers/TaxiHandler.cpp b/src/server/game/Handlers/TaxiHandler.cpp
index 02e0345dba8..a9dc7f26b8e 100644
--- a/src/server/game/Handlers/TaxiHandler.cpp
+++ b/src/server/game/Handlers/TaxiHandler.cpp
@@ -24,7 +24,6 @@
#include "Log.h"
#include "ObjectMgr.h"
#include "Player.h"
-#include "UpdateMask.h"
#include "Path.h"
#include "WaypointMovementGenerator.h"
diff --git a/src/server/game/Handlers/VoiceChatHandler.cpp b/src/server/game/Handlers/VoiceChatHandler.cpp
index 7801ed4d9fe..277755c6eb1 100644
--- a/src/server/game/Handlers/VoiceChatHandler.cpp
+++ b/src/server/game/Handlers/VoiceChatHandler.cpp
@@ -19,7 +19,6 @@
#include "Common.h"
#include "WorldPacket.h"
#include "WorldSession.h"
-#include "Opcodes.h"
#include "Log.h"
void WorldSession::HandleVoiceSessionEnableOpcode(WorldPacket& recvData)
diff --git a/src/server/game/Instances/InstanceSaveMgr.cpp b/src/server/game/Instances/InstanceSaveMgr.cpp
index 0a355fb14b7..260c2966a52 100644
--- a/src/server/game/Instances/InstanceSaveMgr.cpp
+++ b/src/server/game/Instances/InstanceSaveMgr.cpp
@@ -21,15 +21,12 @@
#include "GridNotifiers.h"
#include "Log.h"
#include "GridStates.h"
-#include "CellImpl.h"
#include "Map.h"
#include "MapManager.h"
#include "MapInstanced.h"
#include "InstanceSaveMgr.h"
#include "Timer.h"
-#include "GridNotifiersImpl.h"
#include "Config.h"
-#include "Transport.h"
#include "ObjectMgr.h"
#include "World.h"
#include "Group.h"
diff --git a/src/server/game/Instances/InstanceScript.cpp b/src/server/game/Instances/InstanceScript.cpp
index badd151bf4c..42bf61b6e38 100644
--- a/src/server/game/Instances/InstanceScript.cpp
+++ b/src/server/game/Instances/InstanceScript.cpp
@@ -191,6 +191,12 @@ void InstanceScript::UpdateDoorState(GameObject* door)
door->SetGoState(open ? GO_STATE_ACTIVE : GO_STATE_READY);
}
+BossInfo* InstanceScript::GetBossInfo(uint32 id)
+{
+ ASSERT(id < bosses.size());
+ return &bosses[id];
+}
+
void InstanceScript::AddObject(Creature* obj, bool add)
{
ObjectInfoMap::const_iterator j = _creatureInfo.find(obj->GetEntry());
diff --git a/src/server/game/Instances/InstanceScript.h b/src/server/game/Instances/InstanceScript.h
index 3089a4193c9..41a9e9d0be1 100644
--- a/src/server/game/Instances/InstanceScript.h
+++ b/src/server/game/Instances/InstanceScript.h
@@ -254,12 +254,16 @@ class InstanceScript : public ZoneScript
void AddObject(GameObject* obj, bool add);
void AddObject(WorldObject* obj, uint32 type, bool add);
- void AddDoor(GameObject* door, bool add);
+ virtual void AddDoor(GameObject* door, bool add);
void AddMinion(Creature* minion, bool add);
- void UpdateDoorState(GameObject* door);
+ virtual void UpdateDoorState(GameObject* door);
void UpdateMinionState(Creature* minion, EncounterState state);
+ // Exposes private data that should never be modified unless exceptional cases.
+ // Pay very much attention at how the returned BossInfo data is modified to avoid issues.
+ BossInfo* GetBossInfo(uint32 id);
+
// Instance Load and Save
bool ReadSaveDataHeaders(std::istringstream& data);
void ReadSaveDataBossStates(std::istringstream& data);
diff --git a/src/server/game/Loot/LootMgr.cpp b/src/server/game/Loot/LootMgr.cpp
index db6a2c98379..52b866850a6 100644
--- a/src/server/game/Loot/LootMgr.cpp
+++ b/src/server/game/Loot/LootMgr.cpp
@@ -1832,7 +1832,7 @@ void LoadLootTemplates_Spell()
{
// not report about not trainable spells (optionally supported by DB)
// ignore 61756 (Northrend Inscription Research (FAST QA VERSION) for example
- if (!(spellInfo->Attributes & SPELL_ATTR0_NOT_SHAPESHIFT) || (spellInfo->Attributes & SPELL_ATTR0_TRADESPELL))
+ if (!spellInfo->HasAttribute(SPELL_ATTR0_NOT_SHAPESHIFT) || spellInfo->HasAttribute(SPELL_ATTR0_TRADESPELL))
{
LootTemplates_Spell.ReportNonExistingId(spell_id, "Spell", spellInfo->Id);
}
diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp
index 49f7bc86081..dad24de7288 100644
--- a/src/server/game/Maps/Map.cpp
+++ b/src/server/game/Maps/Map.cpp
@@ -28,7 +28,6 @@
#include "Group.h"
#include "InstanceScript.h"
#include "MapInstanced.h"
-#include "MapManager.h"
#include "ObjectAccessor.h"
#include "ObjectMgr.h"
#include "Pet.h"
@@ -80,7 +79,10 @@ bool Map::ExistMap(uint32 mapid, int gx, int gy)
FILE* pf = fopen(fileName, "rb");
if (!pf)
- TC_LOG_ERROR("maps", "Map file '%s': does not exist!", fileName);
+ {
+ TC_LOG_ERROR("maps", "Map file '%s' does not exist!", fileName);
+ TC_LOG_ERROR("maps", "Please place MAP-files (*.map) in the appropriate directory (%s), or correct the DataDir setting in your worldserver.conf file.", (sWorld->GetDataPath()+"maps/").c_str());
+ }
else
{
map_fileheader header;
@@ -109,7 +111,8 @@ bool Map::ExistVMap(uint32 mapid, int gx, int gy)
if (!exists)
{
std::string name = vmgr->getDirFileName(mapid, gx, gy);
- TC_LOG_ERROR("maps", "VMap file '%s' is missing or points to wrong version of vmap file. Redo vmaps with latest version of vmap_assembler.exe.", (sWorld->GetDataPath()+"vmaps/"+name).c_str());
+ TC_LOG_ERROR("maps", "VMap file '%s' does not exist", (sWorld->GetDataPath()+"vmaps/"+name).c_str());
+ TC_LOG_ERROR("maps", "Please place VMAP-files (*.vmtree and *.vmtile) in the vmap-directory (%s), or correct the DataDir setting in your worldserver.conf file.", (sWorld->GetDataPath()+"vmaps/").c_str());
return false;
}
}
@@ -126,9 +129,9 @@ void Map::LoadMMap(int gx, int gy)
bool mmapLoadResult = MMAP::MMapFactory::createOrGetMMapManager()->loadMap((sWorld->GetDataPath() + "mmaps").c_str(), GetId(), gx, gy);
if (mmapLoadResult)
- TC_LOG_INFO("maps", "MMAP loaded name:%s, id:%d, x:%d, y:%d (mmap rep.: x:%d, y:%d)", GetMapName(), GetId(), gx, gy, gx, gy);
+ TC_LOG_DEBUG("maps", "MMAP loaded name:%s, id:%d, x:%d, y:%d (mmap rep.: x:%d, y:%d)", GetMapName(), GetId(), gx, gy, gx, gy);
else
- TC_LOG_INFO("maps", "Could not load MMAP name:%s, id:%d, x:%d, y:%d (mmap rep.: x:%d, y:%d)", GetMapName(), GetId(), gx, gy, gx, gy);
+ TC_LOG_ERROR("maps", "Could not load MMAP name:%s, id:%d, x:%d, y:%d (mmap rep.: x:%d, y:%d)", GetMapName(), GetId(), gx, gy, gx, gy);
}
void Map::LoadVMap(int gx, int gy)
@@ -140,10 +143,10 @@ void Map::LoadVMap(int gx, int gy)
switch (vmapLoadResult)
{
case VMAP::VMAP_LOAD_RESULT_OK:
- TC_LOG_INFO("maps", "VMAP loaded name:%s, id:%d, x:%d, y:%d (vmap rep.: x:%d, y:%d)", GetMapName(), GetId(), gx, gy, gx, gy);
+ TC_LOG_DEBUG("maps", "VMAP loaded name:%s, id:%d, x:%d, y:%d (vmap rep.: x:%d, y:%d)", GetMapName(), GetId(), gx, gy, gx, gy);
break;
case VMAP::VMAP_LOAD_RESULT_ERROR:
- TC_LOG_INFO("maps", "Could not load VMAP name:%s, id:%d, x:%d, y:%d (vmap rep.: x:%d, y:%d)", GetMapName(), GetId(), gx, gy, gx, gy);
+ TC_LOG_ERROR("maps", "Could not load VMAP name:%s, id:%d, x:%d, y:%d (vmap rep.: x:%d, y:%d)", GetMapName(), GetId(), gx, gy, gx, gy);
break;
case VMAP::VMAP_LOAD_RESULT_IGNORED:
TC_LOG_DEBUG("maps", "Ignored VMAP name:%s, id:%d, x:%d, y:%d (vmap rep.: x:%d, y:%d)", GetMapName(), GetId(), gx, gy, gx, gy);
@@ -173,7 +176,7 @@ void Map::LoadMap(int gx, int gy, bool reload)
//map already load, delete it before reloading (Is it necessary? Do we really need the ability the reload maps during runtime?)
if (GridMaps[gx][gy])
{
- TC_LOG_INFO("maps", "Unloading previously loaded map %u before reloading.", GetId());
+ TC_LOG_DEBUG("maps", "Unloading previously loaded map %u before reloading.", GetId());
sScriptMgr->OnUnloadGridMap(this, GridMaps[gx][gy], gx, gy);
delete (GridMaps[gx][gy]);
@@ -185,7 +188,7 @@ void Map::LoadMap(int gx, int gy, bool reload)
int len = sWorld->GetDataPath().length() + strlen("maps/%03u%02u%02u.map") + 1;
tmp = new char[len];
snprintf(tmp, len, (char *)(sWorld->GetDataPath() + "maps/%03u%02u%02u.map").c_str(), GetId(), gx, gy);
- TC_LOG_INFO("maps", "Loading map %s", tmp);
+ TC_LOG_DEBUG("maps", "Loading map %s", tmp);
// loading data
GridMaps[gx][gy] = new GridMap();
if (!GridMaps[gx][gy]->loadData(tmp))
@@ -2497,7 +2500,7 @@ void Map::UpdateObjectsVisibilityFor(Player* player, Cell cell, CellCoord cellpa
void Map::SendInitSelf(Player* player)
{
- TC_LOG_INFO("maps", "Creating player data for himself %u", player->GetGUIDLow());
+ TC_LOG_DEBUG("maps", "Creating player data for himself %u", player->GetGUIDLow());
UpdateData data;
@@ -2849,7 +2852,7 @@ bool InstanceMap::CanEnter(Player* player)
uint32 maxPlayers = GetMaxPlayers();
if (GetPlayersCountExceptGMs() >= maxPlayers)
{
- TC_LOG_INFO("maps", "MAP: Instance '%u' of map '%s' cannot have more than '%u' players. Player '%s' rejected", GetInstanceId(), GetMapName(), maxPlayers, player->GetName().c_str());
+ TC_LOG_WARN("maps", "MAP: Instance '%u' of map '%s' cannot have more than '%u' players. Player '%s' rejected", GetInstanceId(), GetMapName(), maxPlayers, player->GetName().c_str());
player->SendTransferAborted(GetId(), TRANSFER_ABORT_MAX_PLAYERS);
return false;
}
@@ -2918,7 +2921,7 @@ bool InstanceMap::AddPlayerToMap(Player* player)
InstanceSave* mapSave = sInstanceSaveMgr->GetInstanceSave(GetInstanceId());
if (!mapSave)
{
- TC_LOG_INFO("maps", "InstanceMap::Add: creating instance save for map %d spawnmode %d with instance id %d", GetId(), GetSpawnMode(), GetInstanceId());
+ TC_LOG_DEBUG("maps", "InstanceMap::Add: creating instance save for map %d spawnmode %d with instance id %d", GetId(), GetSpawnMode(), GetInstanceId());
mapSave = sInstanceSaveMgr->AddInstanceSave(GetId(), GetInstanceId(), Difficulty(GetSpawnMode()), 0, true);
}
@@ -2994,7 +2997,7 @@ bool InstanceMap::AddPlayerToMap(Player* player)
// first player enters (no players yet)
SetResetSchedule(false);
- TC_LOG_INFO("maps", "MAP: Player '%s' entered instance '%u' of map '%s'", player->GetName().c_str(), GetInstanceId(), GetMapName());
+ TC_LOG_DEBUG("maps", "MAP: Player '%s' entered instance '%u' of map '%s'", player->GetName().c_str(), GetInstanceId(), GetMapName());
// initialize unload state
m_unloadTimer = 0;
m_resetAfterUnload = false;
@@ -3020,7 +3023,7 @@ void InstanceMap::Update(const uint32 t_diff)
void InstanceMap::RemovePlayerFromMap(Player* player, bool remove)
{
- TC_LOG_INFO("maps", "MAP: Removing player '%s' from instance '%u' of map '%s' before relocating to another map", player->GetName().c_str(), GetInstanceId(), GetMapName());
+ TC_LOG_DEBUG("maps", "MAP: Removing player '%s' from instance '%u' of map '%s' before relocating to another map", player->GetName().c_str(), GetInstanceId(), GetMapName());
//if last player set unload timer
if (!m_unloadTimer && m_mapRefManager.getSize() == 1)
m_unloadTimer = m_unloadWhenEmpty ? MIN_UNLOAD_DELAY : std::max(sWorld->getIntConfig(CONFIG_INSTANCE_UNLOAD_DELAY), (uint32)MIN_UNLOAD_DELAY);
@@ -3253,7 +3256,7 @@ bool BattlegroundMap::AddPlayerToMap(Player* player)
void BattlegroundMap::RemovePlayerFromMap(Player* player, bool remove)
{
- TC_LOG_INFO("maps", "MAP: Removing player '%s' from bg '%u' of map '%s' before relocating to another map", player->GetName().c_str(), GetInstanceId(), GetMapName());
+ TC_LOG_DEBUG("maps", "MAP: Removing player '%s' from bg '%u' of map '%s' before relocating to another map", player->GetName().c_str(), GetInstanceId(), GetMapName());
Map::RemovePlayerFromMap(player, remove);
}
diff --git a/src/server/game/Maps/MapManager.cpp b/src/server/game/Maps/MapManager.cpp
index c8dd812ca02..29f4b4ab7c2 100644
--- a/src/server/game/Maps/MapManager.cpp
+++ b/src/server/game/Maps/MapManager.cpp
@@ -27,7 +27,6 @@
#include "InstanceScript.h"
#include "Config.h"
#include "World.h"
-#include "CellImpl.h"
#include "Corpse.h"
#include "ObjectMgr.h"
#include "Language.h"
diff --git a/src/server/game/Miscellaneous/Language.h b/src/server/game/Miscellaneous/Language.h
index 8131984224f..9bae8fbdfae 100644
--- a/src/server/game/Miscellaneous/Language.h
+++ b/src/server/game/Miscellaneous/Language.h
@@ -207,7 +207,8 @@ enum TrinityStrings
LANG_LIQUID_STATUS = 175,
LANG_INVALID_GAMEOBJECT_TYPE = 176,
LANG_GAMEOBJECT_DAMAGED = 177,
- // Room for more level 1 178-199 not used
+ LANG_GRID_POSITION = 178,
+ // Room for more level 1 179-199 not used
// level 2 chat
LANG_NO_SELECTION = 200,
diff --git a/src/server/game/Movement/MotionMaster.cpp b/src/server/game/Movement/MotionMaster.cpp
index 298e534d58e..2b323e196a7 100644
--- a/src/server/game/Movement/MotionMaster.cpp
+++ b/src/server/game/Movement/MotionMaster.cpp
@@ -30,7 +30,6 @@
#include "RandomMovementGenerator.h"
#include "MoveSpline.h"
#include "MoveSplineInit.h"
-#include <cassert>
inline bool isStatic(MovementGenerator *mv)
{
@@ -387,6 +386,43 @@ void MotionMaster::MoveJump(float x, float y, float z, float speedXY, float spee
Mutate(new EffectMovementGenerator(id), MOTION_SLOT_CONTROLLED);
}
+void MotionMaster::MoveCirclePath(float x, float y, float z, float radius, bool clockwise, uint8 stepCount)
+{
+ float step = 2 * float(M_PI) / stepCount * (clockwise ? -1.0f : 1.0f);
+ Position const& pos = { x, y, z, 0.0f };
+ float angle = pos.GetAngle(_owner->GetPositionX(), _owner->GetPositionY());
+
+ Movement::MoveSplineInit init(_owner);
+
+ for (uint8 i = 0; i < stepCount; angle += step, ++i)
+ {
+ G3D::Vector3 point;
+ point.x = x + radius * cosf(angle);
+ point.y = y + radius * sinf(angle);
+
+ if (_owner->IsFlying())
+ point.z = z;
+ else
+ point.z = _owner->GetMap()->GetHeight(_owner->GetPhaseMask(), point.x, point.y, z);
+
+ init.Path().push_back(point);
+ }
+
+ if (_owner->IsFlying())
+ {
+ init.SetFly();
+ init.SetCyclic();
+ init.SetAnimation(Movement::ToFly);
+ }
+ else
+ {
+ init.SetWalk(true);
+ init.SetCyclic();
+ }
+
+ init.Launch();
+}
+
void MotionMaster::MoveFall(uint32 id /*=0*/)
{
// use larger distance for vmap height search than in most other cases
@@ -647,7 +683,7 @@ void MotionMaster::DirectDelete(_Ty curr)
void MotionMaster::DelayedDelete(_Ty curr)
{
- TC_LOG_FATAL("misc", "Unit (Entry %u) is trying to delete its updating MG (Type %u)!", _owner->GetEntry(), curr->GetMovementGeneratorType());
+ TC_LOG_FATAL("misc", "Unit (Entry %u) is trying to delete its updating Movement Generator (Type %u)!", _owner->GetEntry(), curr->GetMovementGeneratorType());
if (isStatic(curr))
return;
if (!_expList)
diff --git a/src/server/game/Movement/MotionMaster.h b/src/server/game/Movement/MotionMaster.h
index 2821cd5a59b..0b547d96e7f 100644
--- a/src/server/game/Movement/MotionMaster.h
+++ b/src/server/game/Movement/MotionMaster.h
@@ -184,6 +184,7 @@ class MotionMaster //: private std::stack<MovementGenerator *>
void MoveJump(Position const& pos, float speedXY, float speedZ, uint32 id = EVENT_JUMP)
{ MoveJump(pos.m_positionX, pos.m_positionY, pos.m_positionZ, speedXY, speedZ, id); };
void MoveJump(float x, float y, float z, float speedXY, float speedZ, uint32 id = EVENT_JUMP);
+ void MoveCirclePath(float x, float y, float z, float radius, bool clockwise, uint8 stepCount);
void MoveFall(uint32 id = 0);
void MoveSeekAssistance(float x, float y, float z);
diff --git a/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp
index cbfc181fe9f..f0c0311280f 100755
--- a/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp
@@ -17,10 +17,8 @@
*/
#include "Creature.h"
-#include "MapManager.h"
#include "ConfusedMovementGenerator.h"
#include "PathGenerator.h"
-#include "VMapFactory.h"
#include "MoveSplineInit.h"
#include "MoveSpline.h"
#include "Player.h"
diff --git a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp
index cea25fefbda..fa17846a1ff 100644
--- a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp
@@ -18,7 +18,6 @@
#include "Creature.h"
#include "CreatureAI.h"
-#include "MapManager.h"
#include "FleeingMovementGenerator.h"
#include "PathGenerator.h"
#include "ObjectAccessor.h"
diff --git a/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp
index ff28f3855a6..4245bffb864 100644
--- a/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp
@@ -19,7 +19,6 @@
#include "HomeMovementGenerator.h"
#include "Creature.h"
#include "CreatureAI.h"
-#include "WorldPacket.h"
#include "MoveSplineInit.h"
#include "MoveSpline.h"
diff --git a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp
index 0341af299be..86f0e6e20eb 100644
--- a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp
@@ -17,9 +17,7 @@
*/
#include "Creature.h"
-#include "MapManager.h"
#include "RandomMovementGenerator.h"
-#include "ObjectAccessor.h"
#include "Map.h"
#include "Util.h"
#include "CreatureGroups.h"
diff --git a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp
index ed1ea7f4b17..a4c3831cf82 100755
--- a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp
@@ -19,7 +19,6 @@
#include "WaypointMovementGenerator.h"
//Extended headers
#include "ObjectMgr.h"
-#include "World.h"
#include "Transport.h"
//Flightmaster grid preloading
#include "MapManager.h"
@@ -379,9 +378,9 @@ void FlightPathMovementGenerator::PreloadEndGrid()
// Load the grid
if (endMap)
{
- TC_LOG_INFO("misc", "Preloading rid (%f, %f) for map %u at node index %u/%u", _endGridX, _endGridY, _endMapId, _preloadTargetNode, (uint32)(i_path->size()-1));
+ TC_LOG_DEBUG("misc", "Preloading rid (%f, %f) for map %u at node index %u/%u", _endGridX, _endGridY, _endMapId, _preloadTargetNode, (uint32)(i_path->size()-1));
endMap->LoadGrid(_endGridX, _endGridY);
}
else
- TC_LOG_INFO("misc", "Unable to determine map to preload flightmaster grid");
+ TC_LOG_DEBUG("misc", "Unable to determine map to preload flightmaster grid");
}
diff --git a/src/server/game/Movement/Spline/MoveSpline.cpp b/src/server/game/Movement/Spline/MoveSpline.cpp
index d3fa03c1238..1beeebbbad3 100644
--- a/src/server/game/Movement/Spline/MoveSpline.cpp
+++ b/src/server/game/Movement/Spline/MoveSpline.cpp
@@ -147,7 +147,7 @@ void MoveSpline::init_spline(const MoveSplineInitArgs& args)
/// @todo what to do in such cases? problem is in input data (all points are at same coords)
if (spline.length() < minimal_duration)
{
- TC_LOG_ERROR("misc", "MoveSpline::init_spline: zero length spline, wrong input data?");
+ TC_LOG_DEBUG("misc", "MoveSpline::init_spline: zero length spline, wrong input data?");
spline.set_length(spline.last(), spline.isCyclic() ? 1000 : 1);
}
point_Idx = spline.first();
diff --git a/src/server/game/Movement/Spline/MoveSplineInit.cpp b/src/server/game/Movement/Spline/MoveSplineInit.cpp
index 9619d478b7f..180ecf23079 100644
--- a/src/server/game/Movement/Spline/MoveSplineInit.cpp
+++ b/src/server/game/Movement/Spline/MoveSplineInit.cpp
@@ -21,7 +21,6 @@
#include "MovementPacketBuilder.h"
#include "Unit.h"
#include "Transport.h"
-#include "Vehicle.h"
#include "WorldPacket.h"
#include "Opcodes.h"
diff --git a/src/server/game/Movement/Spline/MovementUtil.cpp b/src/server/game/Movement/Spline/MovementUtil.cpp
index 7e63f029fd4..4f7e1d6a7a4 100644
--- a/src/server/game/Movement/Spline/MovementUtil.cpp
+++ b/src/server/game/Movement/Spline/MovementUtil.cpp
@@ -18,7 +18,6 @@
#include "MoveSplineFlag.h"
#include <cmath>
-#include <string>
namespace Movement
{
diff --git a/src/server/game/OutdoorPvP/OutdoorPvP.cpp b/src/server/game/OutdoorPvP/OutdoorPvP.cpp
index cf7be3de5ce..7c3f27e2acd 100644
--- a/src/server/game/OutdoorPvP/OutdoorPvP.cpp
+++ b/src/server/game/OutdoorPvP/OutdoorPvP.cpp
@@ -20,7 +20,6 @@
#include "ObjectAccessor.h"
#include "ObjectMgr.h"
#include "Map.h"
-#include "MapManager.h"
#include "Group.h"
#include "WorldPacket.h"
#include "GridNotifiers.h"
diff --git a/src/server/game/Reputation/ReputationMgr.cpp b/src/server/game/Reputation/ReputationMgr.cpp
index b99cb677ba0..a3e458503d6 100644
--- a/src/server/game/Reputation/ReputationMgr.cpp
+++ b/src/server/game/Reputation/ReputationMgr.cpp
@@ -28,6 +28,9 @@
const int32 ReputationMgr::PointsInRank[MAX_REPUTATION_RANK] = {36000, 3000, 3000, 3000, 6000, 12000, 21000, 1000};
+const int32 ReputationMgr::Reputation_Cap = 42999;
+const int32 ReputationMgr::Reputation_Bottom = -42000;
+
ReputationRank ReputationMgr::ReputationToRank(int32 standing)
{
int32 limit = Reputation_Cap + 1;
diff --git a/src/server/game/Reputation/ReputationMgr.h b/src/server/game/Reputation/ReputationMgr.h
index c3a8d4f477c..7d7650b858e 100644
--- a/src/server/game/Reputation/ReputationMgr.h
+++ b/src/server/game/Reputation/ReputationMgr.h
@@ -72,8 +72,8 @@ class ReputationMgr
void LoadFromDB(PreparedQueryResult result);
public: // statics
static const int32 PointsInRank[MAX_REPUTATION_RANK];
- static const int32 Reputation_Cap = 42999;
- static const int32 Reputation_Bottom = -42000;
+ static const int32 Reputation_Cap;
+ static const int32 Reputation_Bottom;
static ReputationRank ReputationToRank(int32 standing);
public: // accessors
diff --git a/src/server/game/Scripting/MapScripts.cpp b/src/server/game/Scripting/MapScripts.cpp
index ab9c2e32cc8..3beaa7daa9b 100644
--- a/src/server/game/Scripting/MapScripts.cpp
+++ b/src/server/game/Scripting/MapScripts.cpp
@@ -21,8 +21,6 @@
#include "GridNotifiersImpl.h"
#include "GossipDef.h"
#include "Map.h"
-#include "MapManager.h"
-#include "MapRefManager.h"
#include "ObjectMgr.h"
#include "Pet.h"
#include "ScriptedCreature.h"
diff --git a/src/server/game/Scripting/ScriptLoader.cpp b/src/server/game/Scripting/ScriptLoader.cpp
index 025184ff6ef..8be5da91c32 100644
--- a/src/server/game/Scripting/ScriptLoader.cpp
+++ b/src/server/game/Scripting/ScriptLoader.cpp
@@ -356,7 +356,6 @@ void AddSC_dustwallow_marsh();
void AddSC_felwood();
void AddSC_feralas();
void AddSC_moonglade();
-void AddSC_mulgore();
void AddSC_orgrimmar();
void AddSC_silithus();
void AddSC_stonetalon_mountains();
@@ -426,7 +425,8 @@ void AddSC_boss_heigan();
void AddSC_boss_gothik();
void AddSC_boss_thaddius();
void AddSC_instance_naxxramas();
-void AddSC_boss_magus_telestra(); //The Nexus Nexus
+void AddSC_boss_nexus_commanders(); // The Nexus Nexus
+void AddSC_boss_magus_telestra();
void AddSC_boss_anomalus();
void AddSC_boss_ormorok();
void AddSC_boss_keristrasza();
@@ -1061,7 +1061,6 @@ void AddKalimdorScripts()
AddSC_felwood();
AddSC_feralas();
AddSC_moonglade();
- AddSC_mulgore();
AddSC_orgrimmar();
AddSC_silithus();
AddSC_stonetalon_mountains();
@@ -1255,7 +1254,8 @@ void AddNorthrendScripts()
AddSC_boss_gothik();
AddSC_boss_thaddius();
AddSC_instance_naxxramas();
- AddSC_boss_magus_telestra(); //The Nexus Nexus
+ AddSC_boss_nexus_commanders(); // The Nexus Nexus
+ AddSC_boss_magus_telestra();
AddSC_boss_anomalus();
AddSC_boss_ormorok();
AddSC_boss_keristrasza();
diff --git a/src/server/game/Scripting/ScriptMgr.cpp b/src/server/game/Scripting/ScriptMgr.cpp
index 628452d120c..aed829a7b57 100644
--- a/src/server/game/Scripting/ScriptMgr.cpp
+++ b/src/server/game/Scripting/ScriptMgr.cpp
@@ -182,9 +182,8 @@ struct TSpellSummary
uint8 Effects; // set of enum SelectEffect
} *SpellSummary;
-ScriptMgr::ScriptMgr() : _scriptCount(0)
+ScriptMgr::ScriptMgr() : _scriptCount(0), _scheduledScripts(0)
{
- _scheduledScripts = 0;
}
ScriptMgr::~ScriptMgr() { }
diff --git a/src/server/game/Scripting/ScriptMgr.h b/src/server/game/Scripting/ScriptMgr.h
index e290b13c635..a226f1b7ed2 100644
--- a/src/server/game/Scripting/ScriptMgr.h
+++ b/src/server/game/Scripting/ScriptMgr.h
@@ -1142,7 +1142,7 @@ class ScriptMgr
uint32 _scriptCount;
//atomic op counter for active scripts amount
- std::atomic_long _scheduledScripts;
+ std::atomic<uint32> _scheduledScripts;
};
#endif
diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp
index b6b1a4992af..1ff82aa7bf7 100644
--- a/src/server/game/Server/WorldSession.cpp
+++ b/src/server/game/Server/WorldSession.cpp
@@ -36,16 +36,12 @@
#include "Group.h"
#include "Guild.h"
#include "World.h"
-#include "ObjectAccessor.h"
#include "BattlegroundMgr.h"
#include "OutdoorPvPMgr.h"
-#include "MapManager.h"
#include "SocialMgr.h"
#include "zlib.h"
#include "ScriptMgr.h"
-#include "Transport.h"
#include "WardenWin.h"
-#include "WardenMac.h"
#include "MoveSpline.h"
namespace {
@@ -218,8 +214,8 @@ void WorldSession::SendPacket(WorldPacket* packet)
{
uint64 minTime = uint64(cur_time - lastTime);
uint64 fullTime = uint64(lastTime - firstTime);
- TC_LOG_INFO("misc", "Send all time packets count: " UI64FMTD " bytes: " UI64FMTD " avr.count/sec: %f avr.bytes/sec: %f time: %u", sendPacketCount, sendPacketBytes, float(sendPacketCount)/fullTime, float(sendPacketBytes)/fullTime, uint32(fullTime));
- TC_LOG_INFO("misc", "Send last min packets count: " UI64FMTD " bytes: " UI64FMTD " avr.count/sec: %f avr.bytes/sec: %f", sendLastPacketCount, sendLastPacketBytes, float(sendLastPacketCount)/minTime, float(sendLastPacketBytes)/minTime);
+ TC_LOG_DEBUG("misc", "Send all time packets count: " UI64FMTD " bytes: " UI64FMTD " avr.count/sec: %f avr.bytes/sec: %f time: %u", sendPacketCount, sendPacketBytes, float(sendPacketCount)/fullTime, float(sendPacketBytes)/fullTime, uint32(fullTime));
+ TC_LOG_DEBUG("misc", "Send last min packets count: " UI64FMTD " bytes: " UI64FMTD " avr.count/sec: %f avr.bytes/sec: %f", sendLastPacketCount, sendLastPacketBytes, float(sendLastPacketCount)/minTime, float(sendLastPacketBytes)/minTime);
lastTime = cur_time;
sendLastPacketCount = 1;
@@ -951,7 +947,7 @@ void WorldSession::ReadAddonsInfo(WorldPacket &data)
if (size > 0xFFFFF)
{
- TC_LOG_ERROR("misc", "WorldSession::ReadAddonsInfo addon info too big, size %u", size);
+ TC_LOG_DEBUG("addon", "WorldSession::ReadAddonsInfo: AddOnInfo too big, size %u", size);
return;
}
@@ -981,7 +977,7 @@ void WorldSession::ReadAddonsInfo(WorldPacket &data)
addonInfo >> enabled >> crc >> unk1;
- TC_LOG_INFO("misc", "ADDON: Name: %s, Enabled: 0x%x, CRC: 0x%x, Unknown2: 0x%x", addonName.c_str(), enabled, crc, unk1);
+ TC_LOG_DEBUG("addon", "AddOn: %s (CRC: 0x%x) - enabled: 0x%x - Unknown2: 0x%x", addonName.c_str(), crc, enabled, unk1);
AddonInfo addon(addonName, enabled, crc, 2, true);
@@ -989,15 +985,14 @@ void WorldSession::ReadAddonsInfo(WorldPacket &data)
if (savedAddon)
{
if (addon.CRC != savedAddon->CRC)
- TC_LOG_INFO("misc", "ADDON: %s was known, but didn't match known CRC (0x%x)!", addon.Name.c_str(), savedAddon->CRC);
+ TC_LOG_WARN("addon", " Addon: %s: modified (CRC: 0x%x) - accountID %d)", addon.Name.c_str(), savedAddon->CRC, GetAccountId());
else
- TC_LOG_INFO("misc", "ADDON: %s was known, CRC is correct (0x%x)", addon.Name.c_str(), savedAddon->CRC);
+ TC_LOG_DEBUG("addon", "Addon: %s: validated (CRC: 0x%x) - accountID %d", addon.Name.c_str(), savedAddon->CRC, GetAccountId());
}
else
{
AddonMgr::SaveAddon(addon);
-
- TC_LOG_INFO("misc", "ADDON: %s (0x%x) was not known, saving...", addon.Name.c_str(), addon.CRC);
+ TC_LOG_WARN("addon", "Addon: %s: unknown (CRC: 0x%x) - accountId %d (storing addon name and checksum to database)", addon.Name.c_str(), addon.CRC, GetAccountId());
}
/// @todo Find out when to not use CRC/pubkey, and other possible states.
@@ -1006,10 +1001,10 @@ void WorldSession::ReadAddonsInfo(WorldPacket &data)
uint32 currentTime;
addonInfo >> currentTime;
- TC_LOG_DEBUG("network", "ADDON: CurrentTime: %u", currentTime);
+ TC_LOG_DEBUG("addon", "AddOn: CurrentTime: %u", currentTime);
}
else
- TC_LOG_ERROR("misc", "Addon packet uncompress error!");
+ TC_LOG_DEBUG("addon", "AddOn: Addon packet uncompress error!");
}
void WorldSession::SendAddonsInfo()
@@ -1048,8 +1043,8 @@ void WorldSession::SendAddonsInfo()
data << uint8(usepk);
if (usepk) // if CRC is wrong, add public key (client need it)
{
- TC_LOG_INFO("misc", "ADDON: CRC (0x%x) for addon %s is wrong (does not match expected 0x%x), sending pubkey",
- itr->CRC, itr->Name.c_str(), STANDARD_ADDON_CRC);
+ TC_LOG_DEBUG("addon", "AddOn: %s: CRC checksum mismatch: got 0x%x - expected 0x%x - sending pubkey to accountID %d",
+ itr->Name.c_str(), itr->CRC, STANDARD_ADDON_CRC, GetAccountId());
data.append(addonPublicKey, sizeof(addonPublicKey));
}
@@ -1262,7 +1257,7 @@ bool WorldSession::DosProtection::EvaluateOpcode(WorldPacket& p, time_t time) co
return true;
case POLICY_KICK:
{
- TC_LOG_INFO("network", "AntiDOS: Player kicked!");
+ TC_LOG_WARN("network", "AntiDOS: Player kicked!");
Session->KickPlayer();
return false;
}
@@ -1278,7 +1273,7 @@ bool WorldSession::DosProtection::EvaluateOpcode(WorldPacket& p, time_t time) co
case BAN_IP: nameOrIp = Session->GetRemoteAddress(); break;
}
sWorld->BanAccount(bm, nameOrIp, duration, "DOS (Packet Flooding/Spoofing", "Server: AutoDOS");
- TC_LOG_INFO("network", "AntiDOS: Player automatically banned for %u seconds.", duration);
+ TC_LOG_WARN("network", "AntiDOS: Player automatically banned for %u seconds.", duration);
Session->KickPlayer();
return false;
}
diff --git a/src/server/game/Server/WorldSocket.cpp b/src/server/game/Server/WorldSocket.cpp
index 5b1d9497953..0bb864de0ed 100644
--- a/src/server/game/Server/WorldSocket.cpp
+++ b/src/server/game/Server/WorldSocket.cpp
@@ -146,14 +146,12 @@ bool WorldSocket::ReadDataHandler()
uint16 opcode = uint16(header->cmd);
- std::string opcodeName = GetOpcodeNameForLogging(opcode);
-
WorldPacket packet(opcode, std::move(_packetBuffer));
if (sPacketLog->CanLogPacket())
sPacketLog->LogPacket(packet, CLIENT_TO_SERVER, GetRemoteIpAddress(), GetRemotePort());
- TC_LOG_TRACE("network.opcode", "C->S: %s %s", (_worldSession ? _worldSession->GetPlayerInfo() : GetRemoteIpAddress().to_string()).c_str(), opcodeName.c_str());
+ TC_LOG_TRACE("network.opcode", "C->S: %s %s", (_worldSession ? _worldSession->GetPlayerInfo() : GetRemoteIpAddress().to_string()).c_str(), GetOpcodeNameForLogging(opcode).c_str());
switch (opcode)
{
@@ -170,7 +168,7 @@ bool WorldSocket::ReadDataHandler()
HandleAuthSession(packet);
break;
case CMSG_KEEP_ALIVE:
- TC_LOG_DEBUG("network", "%s", opcodeName.c_str());
+ TC_LOG_DEBUG("network", "%s", GetOpcodeNameForLogging(opcode).c_str());
sScriptMgr->OnPacketReceive(_worldSession, packet);
break;
default:
@@ -257,7 +255,7 @@ void WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
recvPacket >> unk4;
recvPacket.read(digest, 20);
- TC_LOG_INFO("network", "WorldSocket::HandleAuthSession: client %u, serverId %u, account %s, loginServerType %u, clientseed %u, realmIndex %u",
+ TC_LOG_DEBUG("network", "WorldSocket::HandleAuthSession: client %u, serverId %u, account %s, loginServerType %u, clientseed %u, realmIndex %u",
clientBuild,
serverId,
account.c_str(),
@@ -429,7 +427,7 @@ void WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
if (allowedAccountType > SEC_PLAYER && AccountTypes(security) < allowedAccountType)
{
SendAuthResponseError(AUTH_UNAVAILABLE);
- TC_LOG_INFO("network", "WorldSocket::HandleAuthSession: User tries to login but his security level is not enough");
+ TC_LOG_DEBUG("network", "WorldSocket::HandleAuthSession: User tries to login but his security level is not enough");
sScriptMgr->OnFailedAccountLogin(id);
DelayedCloseSocket();
return;
diff --git a/src/server/game/Server/WorldSocketMgr.cpp b/src/server/game/Server/WorldSocketMgr.cpp
index 947bd62860c..86c09ef6b6b 100644
--- a/src/server/game/Server/WorldSocketMgr.cpp
+++ b/src/server/game/Server/WorldSocketMgr.cpp
@@ -50,7 +50,8 @@ bool WorldSocketMgr::StartNetwork(boost::asio::io_service& service, std::string
{
_tcpNoDelay = sConfigMgr->GetBoolDefault("Network.TcpNodelay", true);
- TC_LOG_DEBUG("misc", "Max allowed socket connections %d", boost::asio::socket_base::max_connections);
+ int const max_connections = boost::asio::socket_base::max_connections;
+ TC_LOG_DEBUG("misc", "Max allowed socket connections %d", max_connections);
// -1 means use default
_socketSendBufferSize = sConfigMgr->GetIntDefault("Network.OutKBuff", -1);
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
index e5b8cd111bc..b1cb7d51b35 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
@@ -32,7 +32,6 @@
#include "OutdoorPvPMgr.h"
#include "Formulas.h"
#include "GridNotifiers.h"
-#include "GridNotifiersImpl.h"
#include "CellImpl.h"
#include "ScriptMgr.h"
#include "Vehicle.h"
@@ -542,11 +541,11 @@ void AuraEffect::CalculatePeriodic(Unit* caster, bool create, bool load)
// Haste modifies periodic time of channeled spells
if (m_spellInfo->IsChanneled())
{
- if (m_spellInfo->AttributesEx5 & SPELL_ATTR5_HASTE_AFFECT_DURATION)
+ if (m_spellInfo->HasAttribute(SPELL_ATTR5_HASTE_AFFECT_DURATION))
caster->ModSpellCastTime(m_spellInfo, m_amplitude);
}
// and periodic time of auras affected by SPELL_AURA_PERIODIC_HASTE
- else if (caster->HasAuraTypeWithAffectMask(SPELL_AURA_PERIODIC_HASTE, m_spellInfo) || m_spellInfo->AttributesEx5 & SPELL_ATTR5_HASTE_AFFECT_DURATION)
+ else if (caster->HasAuraTypeWithAffectMask(SPELL_AURA_PERIODIC_HASTE, m_spellInfo) || m_spellInfo->HasAttribute(SPELL_ATTR5_HASTE_AFFECT_DURATION))
m_amplitude = int32(m_amplitude * caster->GetFloatValue(UNIT_MOD_CAST_SPEED));
}
}
@@ -555,7 +554,7 @@ void AuraEffect::CalculatePeriodic(Unit* caster, bool create, bool load)
{
m_tickNumber = m_amplitude ? GetBase()->GetDuration() / m_amplitude : 0;
m_periodicTimer = m_amplitude ? GetBase()->GetDuration() % m_amplitude : 0;
- if (m_spellInfo->AttributesEx5 & SPELL_ATTR5_START_PERIODIC_AT_APPLY)
+ if (m_spellInfo->HasAttribute(SPELL_ATTR5_START_PERIODIC_AT_APPLY))
++m_tickNumber;
}
else // aura just created or reapplied
@@ -571,7 +570,7 @@ void AuraEffect::CalculatePeriodic(Unit* caster, bool create, bool load)
{
m_periodicTimer = 0;
// Start periodic on next tick or at aura apply
- if (m_amplitude && !(m_spellInfo->AttributesEx5 & SPELL_ATTR5_START_PERIODIC_AT_APPLY))
+ if (m_amplitude && !m_spellInfo->HasAttribute(SPELL_ATTR5_START_PERIODIC_AT_APPLY))
m_periodicTimer += m_amplitude;
}
}
@@ -1133,7 +1132,7 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const
continue;
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(itr->first);
- if (!spellInfo || !(spellInfo->Attributes & (SPELL_ATTR0_PASSIVE | SPELL_ATTR0_HIDDEN_CLIENTSIDE)))
+ if (!spellInfo || !(spellInfo->HasAttribute(SPELL_ATTR0_PASSIVE) || spellInfo->HasAttribute(SPELL_ATTR0_HIDDEN_CLIENTSIDE)))
continue;
if (spellInfo->Stances & (1<<(GetMiscValue()-1)))
@@ -1148,7 +1147,7 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const
if (GlyphPropertiesEntry const* glyph = sGlyphPropertiesStore.LookupEntry(glyphId))
{
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(glyph->SpellId);
- if (!spellInfo || !(spellInfo->Attributes & (SPELL_ATTR0_PASSIVE | SPELL_ATTR0_HIDDEN_CLIENTSIDE)))
+ if (!spellInfo || !(spellInfo->HasAttribute(SPELL_ATTR0_PASSIVE) || spellInfo->HasAttribute(SPELL_ATTR0_HIDDEN_CLIENTSIDE)))
continue;
if (spellInfo->Stances & (1<<(GetMiscValue()-1)))
target->CastSpell(target, glyph->SpellId, true, NULL, this);
@@ -3243,7 +3242,7 @@ void AuraEffect::HandleModStateImmunityMask(AuraApplication const* aurApp, uint8
for (std::list <AuraType>::iterator iter = aura_immunity_list.begin(); iter != aura_immunity_list.end(); ++iter)
target->ApplySpellImmune(GetId(), IMMUNITY_STATE, *iter, apply);
- if (apply && GetSpellInfo()->AttributesEx & SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY)
+ if (apply && GetSpellInfo()->HasAttribute(SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY))
{
target->RemoveAurasWithMechanic(mechanic_immunity_list, AURA_REMOVE_BY_DEFAULT, GetId());
for (std::list <AuraType>::iterator iter = aura_immunity_list.begin(); iter != aura_immunity_list.end(); ++iter)
@@ -3300,7 +3299,7 @@ void AuraEffect::HandleModMechanicImmunity(AuraApplication const* aurApp, uint8
break;
}
- if (apply && GetSpellInfo()->AttributesEx & SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY)
+ if (apply && GetSpellInfo()->HasAttribute(SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY))
target->RemoveAurasWithMechanic(mechanic, AURA_REMOVE_BY_DEFAULT, GetId());
}
@@ -3336,7 +3335,7 @@ void AuraEffect::HandleAuraModStateImmunity(AuraApplication const* aurApp, uint8
target->ApplySpellImmune(GetId(), IMMUNITY_STATE, GetMiscValue(), apply);
- if (apply && GetSpellInfo()->AttributesEx & SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY)
+ if (apply && GetSpellInfo()->HasAttribute(SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY))
target->RemoveAurasByType(AuraType(GetMiscValue()), ObjectGuid::Empty, GetBase());
}
@@ -3372,13 +3371,13 @@ void AuraEffect::HandleAuraModSchoolImmunity(AuraApplication const* aurApp, uint
target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION);
// remove all flag auras (they are positive, but they must be removed when you are immune)
- if (GetSpellInfo()->AttributesEx & SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY
- && GetSpellInfo()->AttributesEx2 & SPELL_ATTR2_DAMAGE_REDUCED_SHIELD)
+ if (GetSpellInfo()->HasAttribute(SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY)
+ && GetSpellInfo()->HasAttribute(SPELL_ATTR2_DAMAGE_REDUCED_SHIELD))
target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION);
/// @todo optimalize this cycle - use RemoveAurasWithInterruptFlags call or something else
if ((apply)
- && GetSpellInfo()->AttributesEx & SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY
+ && GetSpellInfo()->HasAttribute(SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY)
&& GetSpellInfo()->IsPositive()) //Only positive immunity removes auras
{
uint32 school_mask = GetMiscValue();
@@ -3759,7 +3758,7 @@ void AuraEffect::HandleModTotalPercentStat(AuraApplication const* aurApp, uint8
// recalculate current HP/MP after applying aura modifications (only for spells with SPELL_ATTR0_UNK4 0x00000010 flag)
// this check is total bullshit i think
- if (GetMiscValue() == STAT_STAMINA && (m_spellInfo->Attributes & SPELL_ATTR0_ABILITY))
+ if (GetMiscValue() == STAT_STAMINA && m_spellInfo->HasAttribute(SPELL_ATTR0_ABILITY))
target->SetHealth(std::max<uint32>(uint32(healthPct * target->GetMaxHealth() * 0.01f), (alive ? 1 : 0)));
}
@@ -5901,7 +5900,7 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const
else
damage = uint32(target->CountPctFromMaxHealth(damage));
- if (!(m_spellInfo->AttributesEx4 & SPELL_ATTR4_FIXED_DAMAGE))
+ if (!m_spellInfo->HasAttribute(SPELL_ATTR4_FIXED_DAMAGE))
if (m_spellInfo->Effects[m_effIndex].IsTargetingArea() || isAreaAura)
{
damage = int32(float(damage) * target->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_AOE_DAMAGE_AVOIDANCE, m_spellInfo->SchoolMask));
@@ -5918,13 +5917,13 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const
damage = caster->SpellCriticalDamageBonus(m_spellInfo, damage, target);
int32 dmg = damage;
- if (!(GetSpellInfo()->AttributesEx4 & SPELL_ATTR4_FIXED_DAMAGE))
+ if (!GetSpellInfo()->HasAttribute(SPELL_ATTR4_FIXED_DAMAGE))
caster->ApplyResilience(target, NULL, &dmg, crit, CR_CRIT_TAKEN_SPELL);
damage = dmg;
caster->CalcAbsorbResist(target, GetSpellInfo()->GetSchoolMask(), DOT, damage, &absorb, &resist, GetSpellInfo());
- TC_LOG_INFO("spells", "PeriodicTick: %s attacked %s for %u dmg inflicted by %u absorb is %u",
+ TC_LOG_DEBUG("spells.periodic", "PeriodicTick: %s attacked %s for %u dmg inflicted by %u absorb is %u",
GetCasterGUID().ToString().c_str(), target->GetGUID().ToString().c_str(), damage, GetId(), absorb);
caster->DealDamageMods(target, damage, &absorb);
@@ -5979,7 +5978,7 @@ void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) c
damage = caster->SpellDamageBonusDone(target, GetSpellInfo(), damage, DOT, GetBase()->GetStackAmount()) * caster->SpellDamagePctDone(target, m_spellInfo, DOT);
else
damage = std::max(int32(damage * GetDonePct()), 0);
-
+
damage = target->SpellDamageBonusTaken(caster, GetSpellInfo(), damage, DOT, GetBase()->GetStackAmount());
// Calculate armor mitigation
@@ -5990,7 +5989,7 @@ void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) c
damage = damageReductedArmor;
}
- if (!(m_spellInfo->AttributesEx4 & SPELL_ATTR4_FIXED_DAMAGE))
+ if (!m_spellInfo->HasAttribute(SPELL_ATTR4_FIXED_DAMAGE))
if (m_spellInfo->Effects[m_effIndex].IsTargetingArea() || isAreaAura)
{
damage = uint32(float(damage) * target->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_AOE_DAMAGE_AVOIDANCE, m_spellInfo->SchoolMask));
@@ -6007,7 +6006,7 @@ void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) c
damage = caster->SpellCriticalDamageBonus(m_spellInfo, damage, target);
int32 dmg = damage;
- if (!(GetSpellInfo()->AttributesEx4 & SPELL_ATTR4_FIXED_DAMAGE))
+ if (!GetSpellInfo()->HasAttribute(SPELL_ATTR4_FIXED_DAMAGE))
caster->ApplyResilience(target, NULL, &dmg, crit, CR_CRIT_TAKEN_SPELL);
damage = dmg;
@@ -6016,7 +6015,7 @@ void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) c
if (target->GetHealth() < damage)
damage = uint32(target->GetHealth());
- TC_LOG_INFO("spells", "PeriodicTick: %s health leech of %s for %u dmg inflicted by %u abs is %u",
+ TC_LOG_DEBUG("spells.periodic", "PeriodicTick: %s health leech of %s for %u dmg inflicted by %u abs is %u",
GetCasterGUID().ToString().c_str(), target->GetGUID().ToString().c_str(), damage, GetId(), absorb);
caster->SendSpellNonMeleeDamageLog(target, GetId(), damage, GetSpellInfo()->GetSchoolMask(), absorb, resist, false, 0, crit);
@@ -6083,7 +6082,7 @@ void AuraEffect::HandlePeriodicHealAurasTick(Unit* target, Unit* caster) const
}
// heal for caster damage (must be alive)
- if (target != caster && GetSpellInfo()->AttributesEx2 & SPELL_ATTR2_HEALTH_FUNNEL && !caster->IsAlive())
+ if (target != caster && GetSpellInfo()->HasAttribute(SPELL_ATTR2_HEALTH_FUNNEL) && !caster->IsAlive())
return;
// don't regen when permanent aura target has full power
@@ -6160,7 +6159,7 @@ void AuraEffect::HandlePeriodicHealAurasTick(Unit* target, Unit* caster) const
if (crit)
damage = caster->SpellCriticalHealingBonus(m_spellInfo, damage, target);
- TC_LOG_INFO("spells", "PeriodicTick: %s heal of %s for %u health inflicted by %u",
+ TC_LOG_DEBUG("spells.periodic", "PeriodicTick: %s heal of %s for %u health inflicted by %u",
GetCasterGUID().ToString().c_str(), target->GetGUID().ToString().c_str(), damage, GetId());
uint32 absorb = 0;
@@ -6177,7 +6176,7 @@ void AuraEffect::HandlePeriodicHealAurasTick(Unit* target, Unit* caster) const
// Health Funnel
// damage caster for heal amount
- if (target != caster && GetSpellInfo()->AttributesEx2 & SPELL_ATTR2_HEALTH_FUNNEL)
+ if (target != caster && GetSpellInfo()->HasAttribute(SPELL_ATTR2_HEALTH_FUNNEL))
{
uint32 funnelDamage = GetSpellInfo()->ManaPerSecond; // damage is not affected by spell power
@@ -6231,7 +6230,7 @@ void AuraEffect::HandlePeriodicManaLeechAuraTick(Unit* target, Unit* caster) con
drainAmount = maxmana;
}
- TC_LOG_INFO("spells", "PeriodicTick: %s power leech of %s for %u dmg inflicted by %u",
+ TC_LOG_DEBUG("spells.periodic", "PeriodicTick: %s power leech of %s for %u dmg inflicted by %u",
GetCasterGUID().ToString().c_str(), target->GetGUID().ToString().c_str(), drainAmount, GetId());
// resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
@@ -6292,7 +6291,7 @@ void AuraEffect::HandleObsModPowerAuraTick(Unit* target, Unit* caster) const
// ignore negative values (can be result apply spellmods to aura damage
uint32 amount = std::max(m_amount, 0) * target->GetMaxPower(powerType) /100;
- TC_LOG_INFO("spells", "PeriodicTick: %s energize %s for %u dmg inflicted by %u",
+ TC_LOG_DEBUG("spells.periodic", "PeriodicTick: %s energize %s for %u dmg inflicted by %u",
GetCasterGUID().ToString().c_str(), target->GetGUID().ToString().c_str(), amount, GetId());
SpellPeriodicAuraLogInfo pInfo(this, amount, 0, 0, 0, 0.0f, false);
@@ -6308,7 +6307,7 @@ void AuraEffect::HandlePeriodicEnergizeAuraTick(Unit* target, Unit* caster) cons
{
Powers powerType = Powers(GetMiscValue());
- if (target->GetTypeId() == TYPEID_PLAYER && target->getPowerType() != powerType && !(m_spellInfo->AttributesEx7 & SPELL_ATTR7_CAN_RESTORE_SECONDARY_POWER))
+ if (target->GetTypeId() == TYPEID_PLAYER && target->getPowerType() != powerType && !m_spellInfo->HasAttribute(SPELL_ATTR7_CAN_RESTORE_SECONDARY_POWER))
return;
if (!target->IsAlive() || !target->GetMaxPower(powerType))
@@ -6330,7 +6329,7 @@ void AuraEffect::HandlePeriodicEnergizeAuraTick(Unit* target, Unit* caster) cons
SpellPeriodicAuraLogInfo pInfo(this, amount, 0, 0, 0, 0.0f, false);
target->SendPeriodicAuraLog(&pInfo);
- TC_LOG_INFO("spells", "PeriodicTick: %s energize %s for %u dmg inflicted by %u",
+ TC_LOG_DEBUG("spells.periodic", "PeriodicTick: %s energize %s for %u dmg inflicted by %u",
GetCasterGUID().ToString().c_str(), target->GetGUID().ToString().c_str(), amount, GetId());
int32 gain = target->ModifyPower(powerType, amount);
diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp
index 93a4c96b92f..0ba059b1952 100644
--- a/src/server/game/Spells/Auras/SpellAuras.cpp
+++ b/src/server/game/Spells/Auras/SpellAuras.cpp
@@ -191,7 +191,7 @@ void AuraApplication::BuildUpdatePacket(ByteBuffer& data, bool remove) const
Aura const* aura = GetBase();
data << uint32(aura->GetId());
uint32 flags = _flags;
- if (aura->GetMaxDuration() > 0 && !(aura->GetSpellInfo()->AttributesEx5 & SPELL_ATTR5_HIDE_DURATION))
+ if (aura->GetMaxDuration() > 0 && !aura->GetSpellInfo()->HasAttribute(SPELL_ATTR5_HIDE_DURATION))
flags |= AFLAG_DURATION;
data << uint8(flags);
data << uint8(aura->GetCasterLevel());
@@ -749,12 +749,13 @@ void Aura::SetDuration(int32 duration, bool withMods)
void Aura::RefreshDuration(bool withMods)
{
- if (withMods)
+ Unit* caster = GetCaster();
+ if (withMods && caster)
{
int32 duration = m_spellInfo->GetMaxDuration();
// Calculate duration of periodics affected by haste.
- if (GetCaster()->HasAuraTypeWithAffectMask(SPELL_AURA_PERIODIC_HASTE, m_spellInfo) || m_spellInfo->AttributesEx5 & SPELL_ATTR5_HASTE_AFFECT_DURATION)
- duration = int32(duration * GetCaster()->GetFloatValue(UNIT_MOD_CAST_SPEED));
+ if (caster->HasAuraTypeWithAffectMask(SPELL_AURA_PERIODIC_HASTE, m_spellInfo) || m_spellInfo->HasAttribute(SPELL_ATTR5_HASTE_AFFECT_DURATION))
+ duration = int32(duration * caster->GetFloatValue(UNIT_MOD_CAST_SPEED));
SetMaxDuration(duration);
SetDuration(duration);
@@ -1813,7 +1814,7 @@ bool Aura::CanStackWith(Aura const* existingAura) const
if (existingAura->GetSpellInfo()->IsChanneled())
return true;
- if (m_spellInfo->AttributesEx3 & SPELL_ATTR3_STACK_FOR_DIFF_CASTERS)
+ if (m_spellInfo->HasAttribute(SPELL_ATTR3_STACK_FOR_DIFF_CASTERS))
return true;
// check same periodic auras
@@ -1865,7 +1866,7 @@ bool Aura::CanStackWith(Aura const* existingAura) const
if (m_spellInfo->IsMultiSlotAura() && !IsArea())
return true;
if (GetCastItemGUID() && existingAura->GetCastItemGUID())
- if (GetCastItemGUID() != existingAura->GetCastItemGUID() && (m_spellInfo->AttributesCu & SPELL_ATTR0_CU_ENCHANT_PROC))
+ if (GetCastItemGUID() != existingAura->GetCastItemGUID() && m_spellInfo->HasAttribute(SPELL_ATTR0_CU_ENCHANT_PROC))
return true;
// same spell with same caster should not stack
return false;
diff --git a/src/server/game/Spells/Auras/SpellAuras.h b/src/server/game/Spells/Auras/SpellAuras.h
index ac45461b333..6abcd578411 100644
--- a/src/server/game/Spells/Auras/SpellAuras.h
+++ b/src/server/game/Spells/Auras/SpellAuras.h
@@ -161,8 +161,8 @@ class Aura
{
return GetCasterGUID() == target->GetGUID()
&& m_spellInfo->Stances
- && !(m_spellInfo->AttributesEx2 & SPELL_ATTR2_NOT_NEED_SHAPESHIFT)
- && !(m_spellInfo->Attributes & SPELL_ATTR0_NOT_SHAPESHIFT);
+ && !m_spellInfo->HasAttribute(SPELL_ATTR2_NOT_NEED_SHAPESHIFT)
+ && !m_spellInfo->HasAttribute(SPELL_ATTR0_NOT_SHAPESHIFT);
}
bool CanBeSaved() const;
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index 8f8295d57d1..dbe87daa1a1 100644
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -31,12 +31,9 @@
#include "Player.h"
#include "Pet.h"
#include "Unit.h"
-#include "Totem.h"
#include "Spell.h"
#include "DynamicObject.h"
-#include "Group.h"
#include "UpdateData.h"
-#include "MapManager.h"
#include "ObjectAccessor.h"
#include "CellImpl.h"
#include "SharedDefines.h"
@@ -482,23 +479,23 @@ void SpellCastTargets::Update(Unit* caster)
void SpellCastTargets::OutDebug() const
{
if (!m_targetMask)
- TC_LOG_INFO("spells", "No targets");
+ TC_LOG_DEBUG("spells", "No targets");
- TC_LOG_INFO("spells", "target mask: %u", m_targetMask);
+ TC_LOG_DEBUG("spells", "target mask: %u", m_targetMask);
if (m_targetMask & (TARGET_FLAG_UNIT_MASK | TARGET_FLAG_CORPSE_MASK | TARGET_FLAG_GAMEOBJECT_MASK))
- TC_LOG_INFO("spells", "Object target: %s", m_objectTargetGUID.ToString().c_str());
+ TC_LOG_DEBUG("spells", "Object target: %s", m_objectTargetGUID.ToString().c_str());
if (m_targetMask & TARGET_FLAG_ITEM)
- TC_LOG_INFO("spells", "Item target: %s", m_itemTargetGUID.ToString().c_str());
+ TC_LOG_DEBUG("spells", "Item target: %s", m_itemTargetGUID.ToString().c_str());
if (m_targetMask & TARGET_FLAG_TRADE_ITEM)
- TC_LOG_INFO("spells", "Trade item target: %s", m_itemTargetGUID.ToString().c_str());
+ TC_LOG_DEBUG("spells", "Trade item target: %s", m_itemTargetGUID.ToString().c_str());
if (m_targetMask & TARGET_FLAG_SOURCE_LOCATION)
- TC_LOG_INFO("spells", "Source location: transport guid:%s trans offset: %s position: %s", m_src._transportGUID.ToString().c_str(), m_src._transportOffset.ToString().c_str(), m_src._position.ToString().c_str());
+ TC_LOG_DEBUG("spells", "Source location: transport guid:%s trans offset: %s position: %s", m_src._transportGUID.ToString().c_str(), m_src._transportOffset.ToString().c_str(), m_src._position.ToString().c_str());
if (m_targetMask & TARGET_FLAG_DEST_LOCATION)
- TC_LOG_INFO("spells", "Destination location: transport guid:%s trans offset: %s position: %s", m_dst._transportGUID.ToString().c_str(), m_dst._transportOffset.ToString().c_str(), m_dst._position.ToString().c_str());
+ TC_LOG_DEBUG("spells", "Destination location: transport guid:%s trans offset: %s position: %s", m_dst._transportGUID.ToString().c_str(), m_dst._transportOffset.ToString().c_str(), m_dst._position.ToString().c_str());
if (m_targetMask & TARGET_FLAG_STRING)
- TC_LOG_INFO("spells", "String: %s", m_strTarget.c_str());
- TC_LOG_INFO("spells", "speed: %f", m_speed);
- TC_LOG_INFO("spells", "elevation: %f", m_elevation);
+ TC_LOG_DEBUG("spells", "String: %s", m_strTarget.c_str());
+ TC_LOG_DEBUG("spells", "speed: %f", m_speed);
+ TC_LOG_DEBUG("spells", "elevation: %f", m_elevation);
}
SpellValue::SpellValue(SpellInfo const* proto)
@@ -512,7 +509,7 @@ SpellValue::SpellValue(SpellInfo const* proto)
Spell::Spell(Unit* caster, SpellInfo const* info, TriggerCastFlags triggerFlags, ObjectGuid originalCasterGUID, bool skipCheck) :
m_spellInfo(sSpellMgr->GetSpellForDifficultyFromSpell(info, caster)),
-m_caster((info->AttributesEx6 & SPELL_ATTR6_CAST_BY_CHARMER && caster->GetCharmerOrOwner()) ? caster->GetCharmerOrOwner() : caster)
+m_caster((info->HasAttribute(SPELL_ATTR6_CAST_BY_CHARMER) && caster->GetCharmerOrOwner()) ? caster->GetCharmerOrOwner() : caster)
, m_spellValue(new SpellValue(m_spellInfo)), m_preGeneratedPath(PathGenerator(m_caster))
{
m_customError = SPELL_CUSTOM_ERROR_NONE;
@@ -533,7 +530,7 @@ m_caster((info->AttributesEx6 & SPELL_ATTR6_CAST_BY_CHARMER && caster->GetCharme
switch (m_spellInfo->DmgClass)
{
case SPELL_DAMAGE_CLASS_MELEE:
- if (m_spellInfo->AttributesEx3 & SPELL_ATTR3_REQ_OFFHAND)
+ if (m_spellInfo->HasAttribute(SPELL_ATTR3_REQ_OFFHAND))
m_attackType = OFF_ATTACK;
else
m_attackType = BASE_ATTACK;
@@ -543,7 +540,7 @@ m_caster((info->AttributesEx6 & SPELL_ATTR6_CAST_BY_CHARMER && caster->GetCharme
break;
default:
// Wands
- if (m_spellInfo->AttributesEx2 & SPELL_ATTR2_AUTOREPEAT_FLAG)
+ if (m_spellInfo->HasAttribute(SPELL_ATTR2_AUTOREPEAT_FLAG))
m_attackType = RANGED_ATTACK;
else
m_attackType = BASE_ATTACK;
@@ -574,7 +571,7 @@ m_caster((info->AttributesEx6 & SPELL_ATTR6_CAST_BY_CHARMER && caster->GetCharme
m_spellState = SPELL_STATE_NULL;
_triggeredCastFlags = triggerFlags;
- if (info->AttributesEx4 & SPELL_ATTR4_CAN_CAST_WHILE_CASTING)
+ if (info->HasAttribute(SPELL_ATTR4_CAN_CAST_WHILE_CASTING))
_triggeredCastFlags = TriggerCastFlags(uint32(_triggeredCastFlags) | TRIGGERED_IGNORE_CAST_IN_PROGRESS | TRIGGERED_CAST_DIRECTLY);
m_CastItem = NULL;
@@ -615,8 +612,8 @@ m_caster((info->AttributesEx6 & SPELL_ATTR6_CAST_BY_CHARMER && caster->GetCharme
// Determine if spell can be reflected back to the caster
// Patch 1.2 notes: Spell Reflection no longer reflects abilities
- m_canReflect = m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_MAGIC && !(m_spellInfo->Attributes & SPELL_ATTR0_ABILITY)
- && !(m_spellInfo->AttributesEx & SPELL_ATTR1_CANT_BE_REFLECTED) && !(m_spellInfo->Attributes & SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY)
+ m_canReflect = m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_MAGIC && !m_spellInfo->HasAttribute(SPELL_ATTR0_ABILITY)
+ && !m_spellInfo->HasAttribute(SPELL_ATTR1_CANT_BE_REFLECTED) && !m_spellInfo->HasAttribute(SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY)
&& !m_spellInfo->IsPassive() && !m_spellInfo->IsPositive();
CleanupTargetList();
@@ -1749,11 +1746,11 @@ uint32 Spell::GetSearcherTypeMask(SpellTargetObjectTypes objType, ConditionList*
default:
break;
}
- if (!(m_spellInfo->AttributesEx2 & SPELL_ATTR2_CAN_TARGET_DEAD))
+ if (!m_spellInfo->HasAttribute(SPELL_ATTR2_CAN_TARGET_DEAD))
retMask &= ~GRID_MAP_TYPE_MASK_CORPSE;
- if (m_spellInfo->AttributesEx3 & SPELL_ATTR3_ONLY_TARGET_PLAYERS)
+ if (m_spellInfo->HasAttribute(SPELL_ATTR3_ONLY_TARGET_PLAYERS))
retMask &= GRID_MAP_TYPE_MASK_CORPSE | GRID_MAP_TYPE_MASK_PLAYER;
- if (m_spellInfo->AttributesEx3 & SPELL_ATTR3_ONLY_TARGET_GHOSTS)
+ if (m_spellInfo->HasAttribute(SPELL_ATTR3_ONLY_TARGET_GHOSTS))
retMask &= GRID_MAP_TYPE_MASK_PLAYER;
if (condList)
@@ -1843,7 +1840,7 @@ void Spell::SearchChainTargets(std::list<WorldObject*>& targets, uint32 chainTar
}
// chain lightning/heal spells and similar - allow to jump at larger distance and go out of los
- bool isBouncingFar = (m_spellInfo->AttributesEx4 & SPELL_ATTR4_AREA_TARGET_CHAIN
+ bool isBouncingFar = (m_spellInfo->HasAttribute(SPELL_ATTR4_AREA_TARGET_CHAIN)
|| m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_NONE
|| m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_MAGIC);
@@ -1944,7 +1941,7 @@ void Spell::prepareDataForTriggerSystem(AuraEffect const* /*triggeredByAura*/)
break;
case SPELL_DAMAGE_CLASS_RANGED:
// Auto attack
- if (m_spellInfo->AttributesEx2 & SPELL_ATTR2_AUTOREPEAT_FLAG)
+ if (m_spellInfo->HasAttribute(SPELL_ATTR2_AUTOREPEAT_FLAG))
{
m_procAttacker = PROC_FLAG_DONE_RANGED_AUTO_ATTACK;
m_procVictim = PROC_FLAG_TAKEN_RANGED_AUTO_ATTACK;
@@ -1958,7 +1955,7 @@ void Spell::prepareDataForTriggerSystem(AuraEffect const* /*triggeredByAura*/)
default:
if (m_spellInfo->EquippedItemClass == ITEM_CLASS_WEAPON &&
m_spellInfo->EquippedItemSubClassMask & (1<<ITEM_SUBCLASS_WEAPON_WAND)
- && m_spellInfo->AttributesEx2 & SPELL_ATTR2_AUTOREPEAT_FLAG) // Wands auto attack
+ && m_spellInfo->HasAttribute(SPELL_ATTR2_AUTOREPEAT_FLAG)) // Wands auto attack
{
m_procAttacker = PROC_FLAG_DONE_RANGED_AUTO_ATTACK;
m_procVictim = PROC_FLAG_TAKEN_RANGED_AUTO_ATTACK;
@@ -1990,8 +1987,8 @@ void Spell::prepareDataForTriggerSystem(AuraEffect const* /*triggeredByAura*/)
if (!(m_procAttacker & PROC_FLAG_DONE_RANGED_AUTO_ATTACK))
{
if (_triggeredCastFlags & TRIGGERED_DISALLOW_PROC_EVENTS &&
- (m_spellInfo->AttributesEx2 & SPELL_ATTR2_TRIGGERED_CAN_TRIGGER_PROC ||
- m_spellInfo->AttributesEx3 & SPELL_ATTR3_TRIGGERED_CAN_TRIGGER_PROC_2))
+ (m_spellInfo->HasAttribute(SPELL_ATTR2_TRIGGERED_CAN_TRIGGER_PROC) ||
+ m_spellInfo->HasAttribute(SPELL_ATTR3_TRIGGERED_CAN_TRIGGER_PROC_2)))
m_procEx |= PROC_EX_INTERNAL_CANT_PROC;
else if (_triggeredCastFlags & TRIGGERED_DISALLOW_PROC_EVENTS)
m_procEx |= PROC_EX_INTERNAL_TRIGGERED;
@@ -2275,7 +2272,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target)
m_spellAura = NULL; // Set aura to null for every target-make sure that pointer is not used for unit without aura applied
//Spells with this flag cannot trigger if effect is cast on self
- bool canEffectTrigger = !(m_spellInfo->AttributesEx3 & SPELL_ATTR3_CANT_TRIGGER_PROC) && unitTarget->CanProc() && (CanExecuteTriggersOnHit(mask) || missInfo == SPELL_MISS_IMMUNE || missInfo == SPELL_MISS_IMMUNE2);
+ bool canEffectTrigger = !m_spellInfo->HasAttribute(SPELL_ATTR3_CANT_TRIGGER_PROC) && unitTarget->CanProc() && (CanExecuteTriggersOnHit(mask) || missInfo == SPELL_MISS_IMMUNE || missInfo == SPELL_MISS_IMMUNE2);
Unit* spellHitTarget = NULL;
if (missInfo == SPELL_MISS_NONE) // In case spell hit target, do all effect on that target
@@ -2395,7 +2392,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target)
if (canEffectTrigger && missInfo != SPELL_MISS_REFLECT)
{
caster->ProcDamageAndSpell(unitTarget, procAttacker, procVictim, procEx, damageInfo.damage, m_attackType, m_spellInfo, m_triggeredByAuraSpell);
- if (caster->GetTypeId() == TYPEID_PLAYER && (m_spellInfo->Attributes & SPELL_ATTR0_STOP_ATTACK_TARGET) == 0 &&
+ if (caster->GetTypeId() == TYPEID_PLAYER && m_spellInfo->HasAttribute(SPELL_ATTR0_STOP_ATTACK_TARGET) == 0 &&
(m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_MELEE || m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_RANGED))
caster->ToPlayer()->CastItemCombatSpell(unitTarget, m_attackType, procVictim, procEx);
}
@@ -2415,7 +2412,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target)
caster->ProcDamageAndSpell(unit, procAttacker, procVictim, procEx, 0, m_attackType, m_spellInfo, m_triggeredByAuraSpell);
// Failed Pickpocket, reveal rogue
- if (missInfo == SPELL_MISS_RESIST && m_spellInfo->AttributesCu & SPELL_ATTR0_CU_PICKPOCKET && unitTarget->GetTypeId() == TYPEID_UNIT)
+ if (missInfo == SPELL_MISS_RESIST && m_spellInfo->HasAttribute(SPELL_ATTR0_CU_PICKPOCKET) && unitTarget->GetTypeId() == TYPEID_UNIT)
{
m_caster->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TALK);
if (unitTarget->ToCreature()->IsAIEnabled)
@@ -2425,9 +2422,9 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target)
if (missInfo != SPELL_MISS_EVADE && !m_caster->IsFriendlyTo(unit) && (!m_spellInfo->IsPositive() || m_spellInfo->HasEffect(SPELL_EFFECT_DISPEL)))
{
- m_caster->CombatStart(unit, !(m_spellInfo->AttributesEx3 & SPELL_ATTR3_NO_INITIAL_AGGRO));
+ m_caster->CombatStart(unit, !m_spellInfo->HasAttribute(SPELL_ATTR3_NO_INITIAL_AGGRO));
- if (m_spellInfo->AttributesCu & SPELL_ATTR0_CU_AURA_CC)
+ if (m_spellInfo->HasAttribute(SPELL_ATTR0_CU_AURA_CC))
if (!unit->IsStandState())
unit->SetStandState(UNIT_STAND_STATE_STAND);
}
@@ -2514,7 +2511,7 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleA
{
unit->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_HITBYSPELL);
/// @todo This is a hack. But we do not know what types of stealth should be interrupted by CC
- if ((m_spellInfo->AttributesCu & SPELL_ATTR0_CU_AURA_CC) && unit->IsControlledByPlayer())
+ if (m_spellInfo->HasAttribute(SPELL_ATTR0_CU_AURA_CC) && unit->IsControlledByPlayer())
unit->RemoveAurasByType(SPELL_AURA_MOD_STEALTH);
}
else if (m_caster->IsFriendlyTo(unit))
@@ -2532,7 +2529,7 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleA
if (m_caster->GetTypeId() == TYPEID_PLAYER)
m_caster->ToPlayer()->UpdatePvP(true);
}
- if (unit->IsInCombat() && !(m_spellInfo->AttributesEx3 & SPELL_ATTR3_NO_INITIAL_AGGRO))
+ if (unit->IsInCombat() && !m_spellInfo->HasAttribute(SPELL_ATTR3_NO_INITIAL_AGGRO))
{
m_caster->SetInCombatState(unit->GetCombatTimer() > 0, unit);
unit->getHostileRefManager().threatAssist(m_caster, 0.0f);
@@ -2625,7 +2622,7 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleA
if (m_spellInfo->IsChanneled())
m_originalCaster->ModSpellCastTime(aurSpellInfo, duration, this);
// and duration of auras affected by SPELL_AURA_PERIODIC_HASTE
- else if (m_originalCaster->HasAuraTypeWithAffectMask(SPELL_AURA_PERIODIC_HASTE, aurSpellInfo) || m_spellInfo->AttributesEx5 & SPELL_ATTR5_HASTE_AFFECT_DURATION)
+ else if (m_originalCaster->HasAuraTypeWithAffectMask(SPELL_AURA_PERIODIC_HASTE, aurSpellInfo) || m_spellInfo->HasAttribute(SPELL_ATTR5_HASTE_AFFECT_DURATION))
duration = int32(duration * m_originalCaster->GetFloatValue(UNIT_MOD_CAST_SPEED));
if (duration != m_spellAura->GetMaxDuration())
@@ -3192,7 +3189,7 @@ void Spell::cast(bool skipCheck)
SendSpellGo();
// Okay, everything is prepared. Now we need to distinguish between immediate and evented delayed spells
- if ((m_spellInfo->Speed > 0.0f && !m_spellInfo->IsChanneled()) || m_spellInfo->AttributesEx4 & SPELL_ATTR4_UNK4)
+ if ((m_spellInfo->Speed > 0.0f && !m_spellInfo->IsChanneled()) || m_spellInfo->HasAttribute(SPELL_ATTR4_UNK4))
{
// Remove used for cast item if need (it can be already NULL after TakeReagents call
// in case delayed spell remove item at cast delay start
@@ -3592,7 +3589,7 @@ void Spell::finish(bool ok)
break;
}
}
- if (!found && !(m_spellInfo->AttributesEx2 & SPELL_ATTR2_NOT_RESET_AUTO_ACTIONS))
+ if (!found && !m_spellInfo->HasAttribute(SPELL_ATTR2_NOT_RESET_AUTO_ACTIONS))
{
m_caster->resetAttackTimer(BASE_ATTACK);
if (m_caster->haveOffhandWeapon())
@@ -3618,7 +3615,7 @@ void Spell::finish(bool ok)
}
// Stop Attack for some spells
- if (m_spellInfo->Attributes & SPELL_ATTR0_STOP_ATTACK_TARGET)
+ if (m_spellInfo->HasAttribute(SPELL_ATTR0_STOP_ATTACK_TARGET))
m_caster->AttackStop();
}
@@ -3783,7 +3780,7 @@ void Spell::SendSpellStart()
if ((IsTriggered() && !m_spellInfo->IsAutoRepeatRangedSpell()) || m_triggeredByAuraSpell)
castFlags |= CAST_FLAG_PENDING;
- if (m_spellInfo->Attributes & SPELL_ATTR0_REQ_AMMO)
+ if (m_spellInfo->HasAttribute(SPELL_ATTR0_REQ_AMMO))
castFlags |= CAST_FLAG_AMMO;
if ((m_caster->GetTypeId() == TYPEID_PLAYER ||
(m_caster->GetTypeId() == TYPEID_UNIT && m_caster->ToCreature()->IsPet()))
@@ -3836,7 +3833,7 @@ void Spell::SendSpellGo()
if ((IsTriggered() && !m_spellInfo->IsAutoRepeatRangedSpell()) || m_triggeredByAuraSpell)
castFlags |= CAST_FLAG_PENDING;
- if (m_spellInfo->Attributes & SPELL_ATTR0_REQ_AMMO)
+ if (m_spellInfo->HasAttribute(SPELL_ATTR0_REQ_AMMO))
castFlags |= CAST_FLAG_AMMO; // arrows/bullets visual
if ((m_caster->GetTypeId() == TYPEID_PLAYER ||
@@ -4230,7 +4227,7 @@ void Spell::SendResurrectRequest(Player* target)
data << uint8(m_caster->GetTypeId() == TYPEID_PLAYER ? 0 : 1); // "you'll be afflicted with resurrection sickness"
// override delay sent with SMSG_CORPSE_RECLAIM_DELAY, set instant resurrection for spells with this attribute
- if (m_spellInfo->AttributesEx3 & SPELL_ATTR3_IGNORE_RESURRECTION_TIMER)
+ if (m_spellInfo->HasAttribute(SPELL_ATTR3_IGNORE_RESURRECTION_TIMER))
data << uint32(0);
target->GetSession()->SendPacket(&data);
}
@@ -4561,8 +4558,8 @@ void Spell::HandleThreatSpells()
if (m_UniqueTargetInfo.empty())
return;
- if ((m_spellInfo->AttributesEx & SPELL_ATTR1_NO_THREAT) ||
- (m_spellInfo->AttributesEx3 & SPELL_ATTR3_NO_INITIAL_AGGRO))
+ if (m_spellInfo->HasAttribute(SPELL_ATTR1_NO_THREAT) ||
+ m_spellInfo->HasAttribute(SPELL_ATTR3_NO_INITIAL_AGGRO))
return;
float threat = 0.0f;
@@ -4573,7 +4570,7 @@ void Spell::HandleThreatSpells()
threat += threatEntry->flatMod;
}
- else if ((m_spellInfo->AttributesCu & SPELL_ATTR0_CU_NO_INITIAL_THREAT) == 0)
+ else if (m_spellInfo->HasAttribute(SPELL_ATTR0_CU_NO_INITIAL_THREAT) == 0)
threat += m_spellInfo->SpellLevel;
// past this point only multiplicative effects occur
@@ -4634,11 +4631,11 @@ void Spell::HandleEffects(Unit* pUnitTarget, Item* pItemTarget, GameObject* pGOT
SpellCastResult Spell::CheckCast(bool strict)
{
// check death state
- if (!m_caster->IsAlive() && !(m_spellInfo->Attributes & SPELL_ATTR0_PASSIVE) && !((m_spellInfo->Attributes & SPELL_ATTR0_CASTABLE_WHILE_DEAD) || (IsTriggered() && !m_triggeredByAuraSpell)))
+ if (!m_caster->IsAlive() && !m_spellInfo->HasAttribute(SPELL_ATTR0_PASSIVE) && !(m_spellInfo->HasAttribute(SPELL_ATTR0_CASTABLE_WHILE_DEAD) || (IsTriggered() && !m_triggeredByAuraSpell)))
return SPELL_FAILED_CASTER_DEAD;
// check cooldowns to prevent cheating
- if (m_caster->GetTypeId() == TYPEID_PLAYER && !(m_spellInfo->Attributes & SPELL_ATTR0_PASSIVE))
+ if (m_caster->GetTypeId() == TYPEID_PLAYER && !m_spellInfo->HasAttribute(SPELL_ATTR0_PASSIVE))
{
//can cast triggered (by aura only?) spells while have this flag
if (!(_triggeredCastFlags & TRIGGERED_IGNORE_CASTER_AURASTATE) && m_caster->ToPlayer()->HasFlag(PLAYER_FLAGS, PLAYER_ALLOW_ONLY_ABILITY))
@@ -4657,7 +4654,7 @@ SpellCastResult Spell::CheckCast(bool strict)
return SPELL_FAILED_NOT_READY;
}
- if (m_spellInfo->AttributesEx7 & SPELL_ATTR7_IS_CHEAT_SPELL && !m_caster->HasFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_ALLOW_CHEAT_SPELLS))
+ if (m_spellInfo->HasAttribute(SPELL_ATTR7_IS_CHEAT_SPELL) && !m_caster->HasFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_ALLOW_CHEAT_SPELLS))
{
m_customError = SPELL_CUSTOM_ERROR_GM_ONLY;
return SPELL_FAILED_CUSTOM_ERROR;
@@ -4675,11 +4672,11 @@ SpellCastResult Spell::CheckCast(bool strict)
if (m_caster->GetTypeId() == TYPEID_PLAYER && VMAP::VMapFactory::createOrGetVMapManager()->isLineOfSightCalcEnabled())
{
- if (m_spellInfo->Attributes & SPELL_ATTR0_OUTDOORS_ONLY &&
+ if (m_spellInfo->HasAttribute(SPELL_ATTR0_OUTDOORS_ONLY) &&
!m_caster->GetMap()->IsOutdoors(m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ()))
return SPELL_FAILED_ONLY_OUTDOORS;
- if (m_spellInfo->Attributes & SPELL_ATTR0_INDOORS_ONLY &&
+ if (m_spellInfo->HasAttribute(SPELL_ATTR0_INDOORS_ONLY) &&
m_caster->GetMap()->IsOutdoors(m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ()))
return SPELL_FAILED_ONLY_INDOORS;
}
@@ -4705,7 +4702,7 @@ SpellCastResult Spell::CheckCast(bool strict)
if (shapeError != SPELL_CAST_OK)
return shapeError;
- if ((m_spellInfo->Attributes & SPELL_ATTR0_ONLY_STEALTHED) && !(m_caster->HasStealthAura()))
+ if (m_spellInfo->HasAttribute(SPELL_ATTR0_ONLY_STEALTHED) && !(m_caster->HasStealthAura()))
return SPELL_FAILED_ONLY_STEALTHED;
}
}
@@ -4791,7 +4788,7 @@ SpellCastResult Spell::CheckCast(bool strict)
// those spells may have incorrect target entries or not filled at all (for example 15332)
// such spells when learned are not targeting anyone using targeting system, they should apply directly to caster instead
// also, such casts shouldn't be sent to client
- if (!((m_spellInfo->Attributes & SPELL_ATTR0_PASSIVE) && (!m_targets.GetUnitTarget() || m_targets.GetUnitTarget() == m_caster)))
+ if (!(m_spellInfo->HasAttribute(SPELL_ATTR0_PASSIVE) && (!m_targets.GetUnitTarget() || m_targets.GetUnitTarget() == m_caster)))
{
// Check explicit target for m_originalCaster - todo: get rid of such workarounds
SpellCastResult castResult = m_spellInfo->CheckExplicitTarget(m_originalCaster ? m_originalCaster : m_caster, m_targets.GetObjectTarget(), m_targets.GetItemTarget());
@@ -4808,11 +4805,11 @@ SpellCastResult Spell::CheckCast(bool strict)
if (target != m_caster)
{
// Must be behind the target
- if ((m_spellInfo->AttributesCu & SPELL_ATTR0_CU_REQ_CASTER_BEHIND_TARGET) && target->HasInArc(static_cast<float>(M_PI), m_caster))
+ if (m_spellInfo->HasAttribute(SPELL_ATTR0_CU_REQ_CASTER_BEHIND_TARGET) && target->HasInArc(static_cast<float>(M_PI), m_caster))
return SPELL_FAILED_NOT_BEHIND;
// Target must be facing you
- if ((m_spellInfo->AttributesCu & SPELL_ATTR0_CU_REQ_TARGET_FACING_CASTER) && !target->HasInArc(static_cast<float>(M_PI), m_caster))
+ if (m_spellInfo->HasAttribute(SPELL_ATTR0_CU_REQ_TARGET_FACING_CASTER) && !target->HasInArc(static_cast<float>(M_PI), m_caster))
return SPELL_FAILED_NOT_INFRONT;
if (m_caster->GetEntry() != WORLD_TRIGGER) // Ignore LOS for gameobjects casts (wrongly cast by a trigger)
@@ -4822,7 +4819,7 @@ SpellCastResult Spell::CheckCast(bool strict)
if (DynamicObject* dynObj = m_caster->GetDynObject(m_triggeredByAuraSpell->Id))
losTarget = dynObj;
- if (!(m_spellInfo->AttributesEx2 & SPELL_ATTR2_CAN_TARGET_NOT_IN_LOS) && !DisableMgr::IsDisabledFor(DISABLE_TYPE_SPELL, m_spellInfo->Id, NULL, SPELL_DISABLE_LOS) && !target->IsWithinLOSInMap(losTarget))
+ if (!m_spellInfo->HasAttribute(SPELL_ATTR2_CAN_TARGET_NOT_IN_LOS) && !DisableMgr::IsDisabledFor(DISABLE_TYPE_SPELL, m_spellInfo->Id, NULL, SPELL_DISABLE_LOS) && !target->IsWithinLOSInMap(losTarget))
return SPELL_FAILED_LINE_OF_SIGHT;
}
}
@@ -4834,7 +4831,7 @@ SpellCastResult Spell::CheckCast(bool strict)
float x, y, z;
m_targets.GetDstPos()->GetPosition(x, y, z);
- if (!(m_spellInfo->AttributesEx2 & SPELL_ATTR2_CAN_TARGET_NOT_IN_LOS) && !DisableMgr::IsDisabledFor(DISABLE_TYPE_SPELL, m_spellInfo->Id, NULL, SPELL_DISABLE_LOS) && !m_caster->IsWithinLOS(x, y, z))
+ if (!m_spellInfo->HasAttribute(SPELL_ATTR2_CAN_TARGET_NOT_IN_LOS) && !DisableMgr::IsDisabledFor(DISABLE_TYPE_SPELL, m_spellInfo->Id, NULL, SPELL_DISABLE_LOS) && !m_caster->IsWithinLOS(x, y, z))
return SPELL_FAILED_LINE_OF_SIGHT;
}
@@ -4855,15 +4852,15 @@ SpellCastResult Spell::CheckCast(bool strict)
}
// Spell cast only in battleground
- if ((m_spellInfo->AttributesEx3 & SPELL_ATTR3_BATTLEGROUND) && m_caster->GetTypeId() == TYPEID_PLAYER)
+ if (m_spellInfo->HasAttribute(SPELL_ATTR3_BATTLEGROUND) && m_caster->GetTypeId() == TYPEID_PLAYER)
if (!m_caster->ToPlayer()->InBattleground())
return SPELL_FAILED_ONLY_BATTLEGROUNDS;
// do not allow spells to be cast in arenas
// - with greater than 10 min CD without SPELL_ATTR4_USABLE_IN_ARENA flag
// - with SPELL_ATTR4_NOT_USABLE_IN_ARENA flag
- if ((m_spellInfo->AttributesEx4 & SPELL_ATTR4_NOT_USABLE_IN_ARENA) ||
- (m_spellInfo->GetRecoveryTime() > 10 * MINUTE * IN_MILLISECONDS && !(m_spellInfo->AttributesEx4 & SPELL_ATTR4_USABLE_IN_ARENA)))
+ if (m_spellInfo->HasAttribute(SPELL_ATTR4_NOT_USABLE_IN_ARENA) ||
+ (m_spellInfo->GetRecoveryTime() > 10 * MINUTE * IN_MILLISECONDS && !m_spellInfo->HasAttribute(SPELL_ATTR4_USABLE_IN_ARENA)))
if (MapEntry const* mapEntry = sMapStore.LookupEntry(m_caster->GetMapId()))
if (mapEntry->IsBattleArena())
return SPELL_FAILED_NOT_IN_ARENA;
@@ -4881,7 +4878,7 @@ SpellCastResult Spell::CheckCast(bool strict)
// not let players cast spells at mount (and let do it to creatures)
if (m_caster->IsMounted() && m_caster->GetTypeId() == TYPEID_PLAYER && !(_triggeredCastFlags & TRIGGERED_IGNORE_CASTER_MOUNTED_OR_ON_VEHICLE) &&
- !m_spellInfo->IsPassive() && !(m_spellInfo->Attributes & SPELL_ATTR0_CASTABLE_WHILE_MOUNTED))
+ !m_spellInfo->IsPassive() && !m_spellInfo->HasAttribute(SPELL_ATTR0_CASTABLE_WHILE_MOUNTED))
{
if (m_caster->IsInFlight())
return SPELL_FAILED_NOT_ON_TAXI;
@@ -4938,7 +4935,7 @@ SpellCastResult Spell::CheckCast(bool strict)
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
if (m_spellInfo->Effects[i].Effect == SPELL_EFFECT_DISPEL)
{
- if (m_spellInfo->Effects[i].IsTargetingArea() || m_spellInfo->AttributesEx & SPELL_ATTR1_MELEE_COMBAT_START)
+ if (m_spellInfo->Effects[i].IsTargetingArea() || m_spellInfo->HasAttribute(SPELL_ATTR1_MELEE_COMBAT_START))
{
hasDispellableAura = true;
break;
@@ -5522,7 +5519,7 @@ SpellCastResult Spell::CheckPetCast(Unit* target)
SpellCastResult Spell::CheckCasterAuras() const
{
// spells totally immuned to caster auras (wsg flag drop, give marks etc)
- if (m_spellInfo->AttributesEx6 & SPELL_ATTR6_IGNORE_CASTER_AURAS)
+ if (m_spellInfo->HasAttribute(SPELL_ATTR6_IGNORE_CASTER_AURAS))
return SPELL_CAST_OK;
uint8 school_immune = 0;
@@ -5531,7 +5528,7 @@ SpellCastResult Spell::CheckCasterAuras() const
// Check if the spell grants school or mechanic immunity.
// We use bitmasks so the loop is done only once and not on every aura check below.
- if (m_spellInfo->AttributesEx & SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY)
+ if (m_spellInfo->HasAttribute(SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY))
{
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
{
@@ -5547,7 +5544,7 @@ SpellCastResult Spell::CheckCasterAuras() const
mechanic_immune = IMMUNE_TO_MOVEMENT_IMPAIRMENT_AND_LOSS_CONTROL_MASK;
}
- bool usableInStun = (m_spellInfo->AttributesEx5 & SPELL_ATTR5_USABLE_WHILE_STUNNED) != 0;
+ bool usableInStun = m_spellInfo->HasAttribute(SPELL_ATTR5_USABLE_WHILE_STUNNED);
// Glyph of Pain Suppression
// there is no other way to handle it
@@ -5579,9 +5576,9 @@ SpellCastResult Spell::CheckCasterAuras() const
else
prevented_reason = SPELL_FAILED_STUNNED;
}
- else if (unitflag & UNIT_FLAG_CONFUSED && !(m_spellInfo->AttributesEx5 & SPELL_ATTR5_USABLE_WHILE_CONFUSED))
+ else if (unitflag & UNIT_FLAG_CONFUSED && !m_spellInfo->HasAttribute(SPELL_ATTR5_USABLE_WHILE_CONFUSED))
prevented_reason = SPELL_FAILED_CONFUSED;
- else if (unitflag & UNIT_FLAG_FLEEING && !(m_spellInfo->AttributesEx5 & SPELL_ATTR5_USABLE_WHILE_FEARED))
+ else if (unitflag & UNIT_FLAG_FLEEING && !m_spellInfo->HasAttribute(SPELL_ATTR5_USABLE_WHILE_FEARED))
prevented_reason = SPELL_FAILED_FLEEING;
else if (unitflag & UNIT_FLAG_SILENCED && m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE)
prevented_reason = SPELL_FAILED_SILENCED;
@@ -5601,7 +5598,7 @@ SpellCastResult Spell::CheckCasterAuras() const
SpellInfo const* auraInfo = aura->GetSpellInfo();
if (auraInfo->GetAllEffectsMechanicMask() & mechanic_immune)
continue;
- if (auraInfo->GetSchoolMask() & school_immune && !(auraInfo->AttributesEx & SPELL_ATTR1_UNAFFECTED_BY_SCHOOL_IMMUNE))
+ if (auraInfo->GetSchoolMask() & school_immune && !auraInfo->HasAttribute(SPELL_ATTR1_UNAFFECTED_BY_SCHOOL_IMMUNE))
continue;
if (auraInfo->GetDispelMask() & dispel_immune)
continue;
@@ -5619,11 +5616,11 @@ SpellCastResult Spell::CheckCasterAuras() const
return SPELL_FAILED_STUNNED;
break;
case SPELL_AURA_MOD_CONFUSE:
- if (!(m_spellInfo->AttributesEx5 & SPELL_ATTR5_USABLE_WHILE_CONFUSED))
+ if (!m_spellInfo->HasAttribute(SPELL_ATTR5_USABLE_WHILE_CONFUSED))
return SPELL_FAILED_CONFUSED;
break;
case SPELL_AURA_MOD_FEAR:
- if (!(m_spellInfo->AttributesEx5 & SPELL_ATTR5_USABLE_WHILE_FEARED))
+ if (!m_spellInfo->HasAttribute(SPELL_ATTR5_USABLE_WHILE_FEARED))
return SPELL_FAILED_FLEEING;
break;
case SPELL_AURA_MOD_SILENCE:
@@ -6260,7 +6257,7 @@ SpellCastResult Spell::CheckItems()
if (!(_triggeredCastFlags & TRIGGERED_IGNORE_EQUIPPED_ITEM_REQUIREMENT) && m_spellInfo->EquippedItemClass >=0)
{
// main hand weapon required
- if (m_spellInfo->AttributesEx3 & SPELL_ATTR3_MAIN_HAND)
+ if (m_spellInfo->HasAttribute(SPELL_ATTR3_MAIN_HAND))
{
Item* item = m_caster->ToPlayer()->GetWeaponForAttack(BASE_ATTACK);
@@ -6274,7 +6271,7 @@ SpellCastResult Spell::CheckItems()
}
// offhand hand weapon required
- if (m_spellInfo->AttributesEx3 & SPELL_ATTR3_REQ_OFFHAND)
+ if (m_spellInfo->HasAttribute(SPELL_ATTR3_REQ_OFFHAND))
{
Item* item = m_caster->ToPlayer()->GetWeaponForAttack(OFF_ATTACK);
@@ -6324,7 +6321,7 @@ void Spell::Delayed() // only called in DealDamage()
else
m_timer += delaytime;
- TC_LOG_INFO("spells", "Spell %u partially interrupted for (%d) ms at damage", m_spellInfo->Id, delaytime);
+ TC_LOG_DEBUG("spells", "Spell %u partially interrupted for (%d) ms at damage", m_spellInfo->Id, delaytime);
WorldPacket data(SMSG_SPELL_DELAYED, 8+4);
data << m_caster->GetPackGUID();
@@ -6463,11 +6460,11 @@ bool Spell::CheckEffectTarget(Unit const* target, uint32 eff, Position const* lo
}
// check for ignore LOS on the effect itself
- if (m_spellInfo->AttributesEx2 & SPELL_ATTR2_CAN_TARGET_NOT_IN_LOS || DisableMgr::IsDisabledFor(DISABLE_TYPE_SPELL, m_spellInfo->Id, NULL, SPELL_DISABLE_LOS))
+ if (m_spellInfo->HasAttribute(SPELL_ATTR2_CAN_TARGET_NOT_IN_LOS) || DisableMgr::IsDisabledFor(DISABLE_TYPE_SPELL, m_spellInfo->Id, NULL, SPELL_DISABLE_LOS))
return true;
// if spell is triggered, need to check for LOS disable on the aura triggering it and inherit that behaviour
- if (IsTriggered() && m_triggeredByAuraSpell && (m_triggeredByAuraSpell->AttributesEx2 & SPELL_ATTR2_CAN_TARGET_NOT_IN_LOS || DisableMgr::IsDisabledFor(DISABLE_TYPE_SPELL, m_triggeredByAuraSpell->Id, NULL, SPELL_DISABLE_LOS)))
+ if (IsTriggered() && m_triggeredByAuraSpell && (m_triggeredByAuraSpell->HasAttribute(SPELL_ATTR2_CAN_TARGET_NOT_IN_LOS) || DisableMgr::IsDisabledFor(DISABLE_TYPE_SPELL, m_triggeredByAuraSpell->Id, NULL, SPELL_DISABLE_LOS)))
return true;
/// @todo shit below shouldn't be here, but it's temporary
@@ -6518,7 +6515,7 @@ bool Spell::CheckEffectTarget(Unit const* target, uint32 eff, Position const* lo
bool Spell::IsNextMeleeSwingSpell() const
{
- return (m_spellInfo->Attributes & SPELL_ATTR0_ON_NEXT_SWING) != 0;
+ return m_spellInfo->HasAttribute(SPELL_ATTR0_ON_NEXT_SWING);
}
bool Spell::IsAutoActionResetSpell() const
@@ -6697,7 +6694,7 @@ void Spell::HandleLaunchPhase()
if (m_applyMultiplierMask & (1 << i))
multiplier[i] = m_spellInfo->Effects[i].CalcDamageMultiplier(m_originalCaster, this);
- bool usesAmmo = (m_spellInfo->AttributesCu & SPELL_ATTR0_CU_DIRECT_DAMAGE) != 0;
+ bool usesAmmo = m_spellInfo->HasAttribute(SPELL_ATTR0_CU_DIRECT_DAMAGE);
Unit::AuraEffectList const& Auras = m_caster->GetAuraEffectsByType(SPELL_AURA_ABILITY_CONSUME_NO_AMMO);
for (Unit::AuraEffectList::const_iterator j = Auras.begin(); j != Auras.end(); ++j)
{
@@ -7140,7 +7137,7 @@ void Spell::CallScriptDestinationTargetSelectHandlers(SpellDestination& target,
bool Spell::CheckScriptEffectImplicitTargets(uint32 effIndex, uint32 effIndexToCheck)
{
// Skip if there are not any script
- if (!m_loadedScripts.size())
+ if (m_loadedScripts.empty())
return true;
for (std::list<SpellScript*>::iterator itr = m_loadedScripts.begin(); itr != m_loadedScripts.end(); ++itr)
@@ -7162,7 +7159,7 @@ bool Spell::CheckScriptEffectImplicitTargets(uint32 effIndex, uint32 effIndexToC
bool Spell::CanExecuteTriggersOnHit(uint8 effMask, SpellInfo const* triggeredByAura) const
{
- bool only_on_caster = (triggeredByAura && (triggeredByAura->AttributesEx4 & SPELL_ATTR4_PROC_ONLY_ON_CASTER));
+ bool only_on_caster = (triggeredByAura && triggeredByAura->HasAttribute(SPELL_ATTR4_PROC_ONLY_ON_CASTER));
// If triggeredByAura has SPELL_ATTR4_PROC_ONLY_ON_CASTER then it can only proc on a cast spell with TARGET_UNIT_CASTER
for (uint8 i = 0;i < MAX_SPELL_EFFECTS; ++i)
{
@@ -7401,12 +7398,12 @@ WorldObjectSpellConeTargetCheck::WorldObjectSpellConeTargetCheck(float coneAngle
bool WorldObjectSpellConeTargetCheck::operator()(WorldObject* target)
{
- if (_spellInfo->AttributesCu & SPELL_ATTR0_CU_CONE_BACK)
+ if (_spellInfo->HasAttribute(SPELL_ATTR0_CU_CONE_BACK))
{
if (!_caster->isInBack(target, _coneAngle))
return false;
}
- else if (_spellInfo->AttributesCu & SPELL_ATTR0_CU_CONE_LINE)
+ else if (_spellInfo->HasAttribute(SPELL_ATTR0_CU_CONE_LINE))
{
if (!_caster->HasInLine(target, _caster->GetObjectSize()))
return false;
diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp
index 651f28d3590..cb518ee6099 100644
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -32,10 +32,6 @@
#include "DynamicObject.h"
#include "SpellAuras.h"
#include "SpellAuraEffects.h"
-#include "Group.h"
-#include "UpdateData.h"
-#include "MapManager.h"
-#include "ObjectAccessor.h"
#include "SharedDefines.h"
#include "Pet.h"
#include "GameObject.h"
@@ -43,20 +39,14 @@
#include "Creature.h"
#include "Totem.h"
#include "CreatureAI.h"
-#include "BattlegroundMgr.h"
#include "Battleground.h"
#include "OutdoorPvPMgr.h"
#include "Language.h"
#include "SocialMgr.h"
#include "Util.h"
-#include "VMapFactory.h"
#include "TemporarySummon.h"
-#include "CellImpl.h"
#include "GridNotifiers.h"
-#include "GridNotifiersImpl.h"
-#include "SkillDiscovery.h"
#include "Formulas.h"
-#include "Vehicle.h"
#include "ScriptMgr.h"
#include "GameObjectAI.h"
#include "AccountMgr.h"
@@ -324,7 +314,7 @@ void Spell::EffectSchoolDMG(SpellEffIndex effIndex)
case SPELLFAMILY_GENERIC:
{
// Meteor like spells (divided damage to targets)
- if (m_spellInfo->AttributesCu & SPELL_ATTR0_CU_SHARE_DAMAGE)
+ if (m_spellInfo->HasAttribute(SPELL_ATTR0_CU_SHARE_DAMAGE))
{
uint32 count = 0;
for (std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
@@ -1755,7 +1745,7 @@ void Spell::EffectEnergize(SpellEffIndex effIndex)
Powers power = Powers(m_spellInfo->Effects[effIndex].MiscValue);
- if (unitTarget->GetTypeId() == TYPEID_PLAYER && unitTarget->getPowerType() != power && !(m_spellInfo->AttributesEx7 & SPELL_ATTR7_CAN_RESTORE_SECONDARY_POWER))
+ if (unitTarget->GetTypeId() == TYPEID_PLAYER && unitTarget->getPowerType() != power && !m_spellInfo->HasAttribute(SPELL_ATTR7_CAN_RESTORE_SECONDARY_POWER))
return;
if (unitTarget->GetMaxPower(power) == 0)
@@ -1870,7 +1860,7 @@ void Spell::EffectEnergizePct(SpellEffIndex effIndex)
Powers power = Powers(m_spellInfo->Effects[effIndex].MiscValue);
- if (unitTarget->GetTypeId() == TYPEID_PLAYER && unitTarget->getPowerType() != power && !(m_spellInfo->AttributesEx7 & SPELL_ATTR7_CAN_RESTORE_SECONDARY_POWER))
+ if (unitTarget->GetTypeId() == TYPEID_PLAYER && unitTarget->getPowerType() != power && !m_spellInfo->HasAttribute(SPELL_ATTR7_CAN_RESTORE_SECONDARY_POWER))
return;
uint32 maxPower = unitTarget->GetMaxPower(power);
@@ -4226,7 +4216,7 @@ void Spell::EffectStuck(SpellEffIndex /*effIndex*/)
return;
TC_LOG_DEBUG("spells", "Spell Effect: Stuck");
- TC_LOG_INFO("spells", "Player %s (guid %u) used auto-unstuck future at map %u (%f, %f, %f)", player->GetName().c_str(), player->GetGUIDLow(), player->GetMapId(), player->GetPositionX(), player->GetPositionY(), player->GetPositionZ());
+ TC_LOG_DEBUG("spells", "Player %s (guid %u) used auto-unstuck future at map %u (%f, %f, %f)", player->GetName().c_str(), player->GetGUIDLow(), player->GetMapId(), player->GetPositionX(), player->GetPositionY(), player->GetPositionZ());
if (player->IsInFlight())
return;
@@ -4819,8 +4809,8 @@ void Spell::EffectLeapBack(SpellEffIndex effIndex)
if (!unitTarget)
return;
- float speedxy = float(m_spellInfo->Effects[effIndex].MiscValue)/10;
- float speedz = float(damage/10);
+ float speedxy = m_spellInfo->Effects[effIndex].MiscValue / 10.f;
+ float speedz = damage/ 10.f;
//1891: Disengage
m_caster->JumpTo(speedxy, speedz, m_spellInfo->SpellIconID != 1891);
}
@@ -5344,13 +5334,13 @@ void Spell::EffectStealBeneficialBuff(SpellEffIndex effIndex)
if ((aura->GetSpellInfo()->GetDispelMask()) & dispelMask)
{
// Need check for passive? this
- if (!aurApp->IsPositive() || aura->IsPassive() || aura->GetSpellInfo()->AttributesEx4 & SPELL_ATTR4_NOT_STEALABLE)
+ if (!aurApp->IsPositive() || aura->IsPassive() || aura->GetSpellInfo()->HasAttribute(SPELL_ATTR4_NOT_STEALABLE))
continue;
// The charges / stack amounts don't count towards the total number of auras that can be dispelled.
// Ie: A dispel on a target with 5 stacks of Winters Chill and a Polymorph has 1 / (1 + 1) -> 50% chance to dispell
// Polymorph instead of 1 / (5 + 1) -> 16%.
- bool dispel_charges = (aura->GetSpellInfo()->AttributesEx7 & SPELL_ATTR7_DISPEL_CHARGES) != 0;
+ bool dispel_charges = aura->GetSpellInfo()->HasAttribute(SPELL_ATTR7_DISPEL_CHARGES);
uint8 charges = dispel_charges ? aura->GetCharges() : aura->GetStackAmount();
if (charges > 0)
steal_list.push_back(std::make_pair(aura, charges));
@@ -5852,7 +5842,7 @@ void Spell::EffectCastButtons(SpellEffIndex effIndex)
if (!p_caster->HasSpell(spell_id) || p_caster->HasSpellCooldown(spell_id))
continue;
- if (!(spellInfo->AttributesEx7 & SPELL_ATTR7_SUMMON_PLAYER_TOTEM))
+ if (!spellInfo->HasAttribute(SPELL_ATTR7_SUMMON_PLAYER_TOTEM))
continue;
uint32 cost = spellInfo->CalcPowerCost(m_caster, spellInfo->GetSchoolMask());
diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp
index 6215f8cfa0a..862521a068c 100644
--- a/src/server/game/Spells/SpellInfo.cpp
+++ b/src/server/game/Spells/SpellInfo.cpp
@@ -453,7 +453,7 @@ int32 SpellEffectInfo::CalcValue(Unit const* caster, int32 const* bp, Unit const
// amount multiplication based on caster's level
if (!caster->IsControlledByPlayer() &&
_spellInfo->SpellLevel && _spellInfo->SpellLevel != caster->getLevel() &&
- !basePointsPerLevel && (_spellInfo->Attributes & SPELL_ATTR0_LEVEL_DAMAGE_CALCULATION))
+ !basePointsPerLevel && _spellInfo->HasAttribute(SPELL_ATTR0_LEVEL_DAMAGE_CALCULATION))
{
bool canEffectScale = false;
switch (Effect)
@@ -1049,14 +1049,14 @@ bool SpellInfo::NeedsToBeTriggeredByCaster(SpellInfo const* triggeringSpell) con
bool SpellInfo::IsPassive() const
{
- return (Attributes & SPELL_ATTR0_PASSIVE) != 0;
+ return HasAttribute(SPELL_ATTR0_PASSIVE);
}
bool SpellInfo::IsAutocastable() const
{
- if (Attributes & SPELL_ATTR0_PASSIVE)
+ if (HasAttribute(SPELL_ATTR0_PASSIVE))
return false;
- if (AttributesEx & SPELL_ATTR1_UNAUTOCASTABLE_BY_PET)
+ if (HasAttribute(SPELL_ATTR1_UNAUTOCASTABLE_BY_PET))
return false;
return true;
}
@@ -1107,37 +1107,37 @@ bool SpellInfo::IsMultiSlotAura() const
bool SpellInfo::IsStackableOnOneSlotWithDifferentCasters() const
{
/// TODO: Re-verify meaning of SPELL_ATTR3_STACK_FOR_DIFF_CASTERS and update conditions here
- return StackAmount > 1 && !IsChanneled() && !(AttributesEx3 & SPELL_ATTR3_STACK_FOR_DIFF_CASTERS);
+ return StackAmount > 1 && !IsChanneled() && !HasAttribute(SPELL_ATTR3_STACK_FOR_DIFF_CASTERS);
}
bool SpellInfo::IsCooldownStartedOnEvent() const
{
- return Attributes & SPELL_ATTR0_DISABLED_WHILE_ACTIVE || (CategoryEntry && CategoryEntry->Flags & SPELL_CATEGORY_FLAG_COOLDOWN_STARTS_ON_EVENT);
+ return HasAttribute(SPELL_ATTR0_DISABLED_WHILE_ACTIVE) || (CategoryEntry && CategoryEntry->Flags & SPELL_CATEGORY_FLAG_COOLDOWN_STARTS_ON_EVENT);
}
bool SpellInfo::IsDeathPersistent() const
{
- return (AttributesEx3 & SPELL_ATTR3_DEATH_PERSISTENT) != 0;
+ return HasAttribute(SPELL_ATTR3_DEATH_PERSISTENT);
}
bool SpellInfo::IsRequiringDeadTarget() const
{
- return (AttributesEx3 & SPELL_ATTR3_ONLY_TARGET_GHOSTS) != 0;
+ return HasAttribute(SPELL_ATTR3_ONLY_TARGET_GHOSTS);
}
bool SpellInfo::IsAllowingDeadTarget() const
{
- return AttributesEx2 & SPELL_ATTR2_CAN_TARGET_DEAD || Targets & (TARGET_FLAG_CORPSE_ALLY | TARGET_FLAG_CORPSE_ENEMY | TARGET_FLAG_UNIT_DEAD);
+ return HasAttribute(SPELL_ATTR2_CAN_TARGET_DEAD) || Targets & (TARGET_FLAG_CORPSE_ALLY | TARGET_FLAG_CORPSE_ENEMY | TARGET_FLAG_UNIT_DEAD);
}
bool SpellInfo::CanBeUsedInCombat() const
{
- return !(Attributes & SPELL_ATTR0_CANT_USED_IN_COMBAT);
+ return !HasAttribute(SPELL_ATTR0_CANT_USED_IN_COMBAT);
}
bool SpellInfo::IsPositive() const
{
- return !(AttributesCu & SPELL_ATTR0_CU_NEGATIVE);
+ return !HasAttribute(SPELL_ATTR0_CU_NEGATIVE);
}
bool SpellInfo::IsPositiveEffect(uint8 effIndex) const
@@ -1146,27 +1146,27 @@ bool SpellInfo::IsPositiveEffect(uint8 effIndex) const
{
default:
case 0:
- return !(AttributesCu & SPELL_ATTR0_CU_NEGATIVE_EFF0);
+ return !HasAttribute(SPELL_ATTR0_CU_NEGATIVE_EFF0);
case 1:
- return !(AttributesCu & SPELL_ATTR0_CU_NEGATIVE_EFF1);
+ return !HasAttribute(SPELL_ATTR0_CU_NEGATIVE_EFF1);
case 2:
- return !(AttributesCu & SPELL_ATTR0_CU_NEGATIVE_EFF2);
+ return !HasAttribute(SPELL_ATTR0_CU_NEGATIVE_EFF2);
}
}
bool SpellInfo::IsChanneled() const
{
- return (AttributesEx & (SPELL_ATTR1_CHANNELED_1 | SPELL_ATTR1_CHANNELED_2)) != 0;
+ return HasAttribute(SPELL_ATTR1_CHANNELED_1) || HasAttribute(SPELL_ATTR1_CHANNELED_2);
}
bool SpellInfo::NeedsComboPoints() const
{
- return (AttributesEx & (SPELL_ATTR1_REQ_COMBO_POINTS1 | SPELL_ATTR1_REQ_COMBO_POINTS2)) != 0;
+ return HasAttribute(SPELL_ATTR1_REQ_COMBO_POINTS1) || HasAttribute(SPELL_ATTR1_REQ_COMBO_POINTS2);
}
bool SpellInfo::IsBreakingStealth() const
{
- return !(AttributesEx & SPELL_ATTR1_NOT_BREAK_STEALTH);
+ return !HasAttribute(SPELL_ATTR1_NOT_BREAK_STEALTH);
}
bool SpellInfo::IsRangedWeaponSpell() const
@@ -1177,12 +1177,12 @@ bool SpellInfo::IsRangedWeaponSpell() const
bool SpellInfo::IsAutoRepeatRangedSpell() const
{
- return (AttributesEx2 & SPELL_ATTR2_AUTOREPEAT_FLAG) != 0;
+ return HasAttribute(SPELL_ATTR2_AUTOREPEAT_FLAG);
}
bool SpellInfo::IsAffectedBySpellMods() const
{
- return !(AttributesEx3 & SPELL_ATTR3_NO_DONE_BONUS);
+ return !HasAttribute(SPELL_ATTR3_NO_DONE_BONUS);
}
bool SpellInfo::IsAffectedBySpellMod(SpellModifier const* mod) const
@@ -1205,11 +1205,11 @@ bool SpellInfo::IsAffectedBySpellMod(SpellModifier const* mod) const
bool SpellInfo::CanPierceImmuneAura(SpellInfo const* aura) const
{
// these spells pierce all avalible spells (Resurrection Sickness for example)
- if (Attributes & SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY)
+ if (HasAttribute(SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY))
return true;
// these spells (Cyclone for example) can pierce all... // ...but not these (Divine shield, Ice block, Cyclone and Banish for example)
- if ((AttributesEx & SPELL_ATTR1_UNAFFECTED_BY_SCHOOL_IMMUNE) && !(aura && (aura->Mechanic == MECHANIC_IMMUNE_SHIELD || aura->Mechanic == MECHANIC_INVULNERABILITY || aura->Mechanic == MECHANIC_BANISH)))
+ if ((HasAttribute(SPELL_ATTR1_UNAFFECTED_BY_SCHOOL_IMMUNE)) && !(aura && (aura->Mechanic == MECHANIC_IMMUNE_SHIELD || aura->Mechanic == MECHANIC_INVULNERABILITY || aura->Mechanic == MECHANIC_BANISH)))
return true;
return false;
@@ -1218,15 +1218,15 @@ bool SpellInfo::CanPierceImmuneAura(SpellInfo const* aura) const
bool SpellInfo::CanDispelAura(SpellInfo const* aura) const
{
// These spells (like Mass Dispel) can dispell all auras, except death persistent ones (like Dungeon and Battleground Deserter)
- if (Attributes & SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY && !aura->IsDeathPersistent())
+ if (HasAttribute(SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY) && !aura->IsDeathPersistent())
return true;
// These auras (like Divine Shield) can't be dispelled
- if (aura->Attributes & SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY)
+ if (aura->HasAttribute(SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY))
return false;
// These auras (Cyclone for example) are not dispelable
- if (aura->AttributesEx & SPELL_ATTR1_UNAFFECTED_BY_SCHOOL_IMMUNE)
+ if (aura->HasAttribute(SPELL_ATTR1_UNAFFECTED_BY_SCHOOL_IMMUNE))
return false;
return true;
@@ -1235,7 +1235,7 @@ bool SpellInfo::CanDispelAura(SpellInfo const* aura) const
bool SpellInfo::IsSingleTarget() const
{
// all other single target spells have if it has AttributesEx5
- if (AttributesEx5 & SPELL_ATTR5_SINGLE_TARGET_SPELL)
+ if (HasAttribute(SPELL_ATTR5_SINGLE_TARGET_SPELL))
return true;
switch (GetSpellSpecific())
@@ -1332,7 +1332,7 @@ SpellCastResult SpellInfo::CheckShapeshift(uint32 form) const
if (actAsShifted)
{
- if (Attributes & SPELL_ATTR0_NOT_SHAPESHIFT) // not while shapeshifted
+ if (HasAttribute(SPELL_ATTR0_NOT_SHAPESHIFT)) // not while shapeshifted
return SPELL_FAILED_NOT_SHAPESHIFT;
else if (Stances != 0) // needs other shapeshift
return SPELL_FAILED_ONLY_SHAPESHIFT;
@@ -1340,7 +1340,7 @@ SpellCastResult SpellInfo::CheckShapeshift(uint32 form) const
else
{
// needs shapeshift
- if (!(AttributesEx2 & SPELL_ATTR2_NOT_NEED_SHAPESHIFT) && Stances != 0)
+ if (!HasAttribute(SPELL_ATTR2_NOT_NEED_SHAPESHIFT) && Stances != 0)
return SPELL_FAILED_ONLY_SHAPESHIFT;
}
@@ -1379,7 +1379,7 @@ SpellCastResult SpellInfo::CheckLocation(uint32 map_id, uint32 zone_id, uint32 a
}
// continent limitation (virtual continent)
- if (AttributesEx4 & SPELL_ATTR4_CAST_ONLY_IN_OUTLAND)
+ if (HasAttribute(SPELL_ATTR4_CAST_ONLY_IN_OUTLAND))
{
uint32 v_map = GetVirtualMapForMapAndZone(map_id, zone_id);
MapEntry const* mapEntry = sMapStore.LookupEntry(v_map);
@@ -1388,7 +1388,7 @@ SpellCastResult SpellInfo::CheckLocation(uint32 map_id, uint32 zone_id, uint32 a
}
// raid instance limitation
- if (AttributesEx6 & SPELL_ATTR6_NOT_IN_RAID_INSTANCE)
+ if (HasAttribute(SPELL_ATTR6_NOT_IN_RAID_INSTANCE))
{
MapEntry const* mapEntry = sMapStore.LookupEntry(map_id);
if (!mapEntry || mapEntry->IsRaid())
@@ -1493,11 +1493,11 @@ SpellCastResult SpellInfo::CheckLocation(uint32 map_id, uint32 zone_id, uint32 a
SpellCastResult SpellInfo::CheckTarget(Unit const* caster, WorldObject const* target, bool implicit) const
{
- if (AttributesEx & SPELL_ATTR1_CANT_TARGET_SELF && caster == target)
+ if (HasAttribute(SPELL_ATTR1_CANT_TARGET_SELF) && caster == target)
return SPELL_FAILED_BAD_TARGETS;
// check visibility - ignore stealth for implicit (area) targets
- if (!(AttributesEx6 & SPELL_ATTR6_CAN_TARGET_INVISIBLE) && !caster->CanSeeOrDetect(target, implicit))
+ if (!HasAttribute(SPELL_ATTR6_CAN_TARGET_INVISIBLE) && !caster->CanSeeOrDetect(target, implicit))
return SPELL_FAILED_BAD_TARGETS;
Unit const* unitTarget = target->ToUnit();
@@ -1505,7 +1505,7 @@ SpellCastResult SpellInfo::CheckTarget(Unit const* caster, WorldObject const* ta
// creature/player specific target checks
if (unitTarget)
{
- if (AttributesEx & SPELL_ATTR1_CANT_TARGET_IN_COMBAT)
+ if (HasAttribute(SPELL_ATTR1_CANT_TARGET_IN_COMBAT))
{
if (unitTarget->IsInCombat())
return SPELL_FAILED_TARGET_AFFECTING_COMBAT;
@@ -1517,9 +1517,9 @@ SpellCastResult SpellInfo::CheckTarget(Unit const* caster, WorldObject const* ta
}
// only spells with SPELL_ATTR3_ONLY_TARGET_GHOSTS can target ghosts
- if (((AttributesEx3 & SPELL_ATTR3_ONLY_TARGET_GHOSTS) != 0) != unitTarget->HasAuraType(SPELL_AURA_GHOST))
+ if (HasAttribute(SPELL_ATTR3_ONLY_TARGET_GHOSTS) != unitTarget->HasAuraType(SPELL_AURA_GHOST))
{
- if (AttributesEx3 & SPELL_ATTR3_ONLY_TARGET_GHOSTS)
+ if (HasAttribute(SPELL_ATTR3_ONLY_TARGET_GHOSTS))
return SPELL_FAILED_TARGET_NOT_GHOST;
else
return SPELL_FAILED_BAD_TARGETS;
@@ -1530,12 +1530,12 @@ SpellCastResult SpellInfo::CheckTarget(Unit const* caster, WorldObject const* ta
if (caster->GetTypeId() == TYPEID_PLAYER)
{
// Do not allow these spells to target creatures not tapped by us (Banish, Polymorph, many quest spells)
- if (AttributesEx2 & SPELL_ATTR2_CANT_TARGET_TAPPED)
+ if (HasAttribute(SPELL_ATTR2_CANT_TARGET_TAPPED))
if (Creature const* targetCreature = unitTarget->ToCreature())
if (targetCreature->hasLootRecipient() && !targetCreature->isTappedBy(caster->ToPlayer()))
return SPELL_FAILED_CANT_CAST_ON_TAPPED;
- if (AttributesCu & SPELL_ATTR0_CU_PICKPOCKET)
+ if (HasAttribute(SPELL_ATTR0_CU_PICKPOCKET))
{
if (unitTarget->GetTypeId() == TYPEID_PLAYER)
return SPELL_FAILED_BAD_TARGETS;
@@ -1575,21 +1575,21 @@ SpellCastResult SpellInfo::CheckTarget(Unit const* caster, WorldObject const* ta
else return SPELL_CAST_OK;
// corpseOwner and unit specific target checks
- if (AttributesEx3 & SPELL_ATTR3_ONLY_TARGET_PLAYERS && !unitTarget->ToPlayer())
+ if (HasAttribute(SPELL_ATTR3_ONLY_TARGET_PLAYERS) && !unitTarget->ToPlayer())
return SPELL_FAILED_TARGET_NOT_PLAYER;
if (!IsAllowingDeadTarget() && !unitTarget->IsAlive())
return SPELL_FAILED_TARGETS_DEAD;
// check this flag only for implicit targets (chain and area), allow to explicitly target units for spells like Shield of Righteousness
- if (implicit && AttributesEx6 & SPELL_ATTR6_CANT_TARGET_CROWD_CONTROLLED && !unitTarget->CanFreeMove())
+ if (implicit && HasAttribute(SPELL_ATTR6_CANT_TARGET_CROWD_CONTROLLED) && !unitTarget->CanFreeMove())
return SPELL_FAILED_BAD_TARGETS;
// checked in Unit::IsValidAttack/AssistTarget, shouldn't be checked for ENTRY targets
- //if (!(AttributesEx6 & SPELL_ATTR6_CAN_TARGET_UNTARGETABLE) && target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE))
+ //if (!HasAttribute(SPELL_ATTR6_CAN_TARGET_UNTARGETABLE) && target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE))
// return SPELL_FAILED_BAD_TARGETS;
- //if (!(AttributesEx6 & SPELL_ATTR6_CAN_TARGET_POSSESSED_FRIENDS)
+ //if (!HasAttribute(SPELL_ATTR6_CAN_TARGET_POSSESSED_FRIENDS)
if (!CheckTargetCreatureType(unitTarget))
{
@@ -1705,7 +1705,7 @@ SpellCastResult SpellInfo::CheckVehicle(Unit const* caster) const
checkMask = VEHICLE_SEAT_FLAG_CAN_ATTACK;
VehicleSeatEntry const* vehicleSeat = vehicle->GetSeatForPassenger(caster);
- if (!(AttributesEx6 & SPELL_ATTR6_CASTABLE_WHILE_ON_VEHICLE) && !(Attributes & SPELL_ATTR0_CASTABLE_WHILE_MOUNTED)
+ if (!HasAttribute(SPELL_ATTR6_CASTABLE_WHILE_ON_VEHICLE) && !HasAttribute(SPELL_ATTR0_CASTABLE_WHILE_MOUNTED)
&& (vehicleSeat->m_flags & checkMask) != checkMask)
return SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW;
@@ -2106,7 +2106,7 @@ uint32 SpellInfo::CalcCastTime(Spell* spell /*= NULL*/) const
if (spell)
spell->GetCaster()->ModSpellCastTime(this, castTime, spell);
- if (Attributes & SPELL_ATTR0_REQ_AMMO && (!IsAutoRepeatRangedSpell()))
+ if (HasAttribute(SPELL_ATTR0_REQ_AMMO) && (!IsAutoRepeatRangedSpell()))
castTime += 500;
return (castTime > 0) ? uint32(castTime) : 0;
@@ -2147,7 +2147,7 @@ uint32 SpellInfo::GetRecoveryTime() const
int32 SpellInfo::CalcPowerCost(Unit const* caster, SpellSchoolMask schoolMask) const
{
// Spell drain all exist power on cast (Only paladin lay of Hands)
- if (AttributesEx & SPELL_ATTR1_DRAIN_ALL_POWER)
+ if (HasAttribute(SPELL_ATTR1_DRAIN_ALL_POWER))
{
// If power type - health drain all
if (PowerType == POWER_HEALTH)
@@ -2193,7 +2193,7 @@ int32 SpellInfo::CalcPowerCost(Unit const* caster, SpellSchoolMask schoolMask) c
powerCost += caster->GetInt32Value(UNIT_FIELD_POWER_COST_MODIFIER + school);
// Shiv - costs 20 + weaponSpeed*10 energy (apply only to non-triggered spell with energy cost)
- if (AttributesEx4 & SPELL_ATTR4_SPELL_VS_EXTEND_COST)
+ if (HasAttribute(SPELL_ATTR4_SPELL_VS_EXTEND_COST))
{
uint32 speed = 0;
if (SpellShapeshiftEntry const* ss = sSpellShapeshiftStore.LookupEntry(caster->GetShapeshiftForm()))
@@ -2201,7 +2201,7 @@ int32 SpellInfo::CalcPowerCost(Unit const* caster, SpellSchoolMask schoolMask) c
else
{
WeaponAttackType slot = BASE_ATTACK;
- if (AttributesEx3 & SPELL_ATTR3_REQ_OFFHAND)
+ if (HasAttribute(SPELL_ATTR3_REQ_OFFHAND))
slot = OFF_ATTACK;
speed = caster->GetAttackTime(slot);
@@ -2216,7 +2216,7 @@ int32 SpellInfo::CalcPowerCost(Unit const* caster, SpellSchoolMask schoolMask) c
if (!caster->IsControlledByPlayer())
{
- if (Attributes & SPELL_ATTR0_LEVEL_DAMAGE_CALCULATION)
+ if (HasAttribute(SPELL_ATTR0_LEVEL_DAMAGE_CALCULATION))
{
GtNPCManaCostScalerEntry const* spellScaler = sGtNPCManaCostScalerStore.LookupEntry(SpellLevel - 1);
GtNPCManaCostScalerEntry const* casterScaler = sGtNPCManaCostScalerStore.LookupEntry(caster->getLevel() - 1);
@@ -2361,7 +2361,7 @@ void SpellInfo::_InitializeExplicitTargetMask()
bool SpellInfo::_IsPositiveEffect(uint8 effIndex, bool deep) const
{
// not found a single positive spell with this attribute
- if (Attributes & SPELL_ATTR0_NEGATIVE_1)
+ if (HasAttribute(SPELL_ATTR0_NEGATIVE_1))
return false;
switch (SpellFamilyName)
@@ -2542,7 +2542,7 @@ bool SpellInfo::_IsPositiveEffect(uint8 effIndex, bool deep) const
if (Effects[effIndex].TargetA.GetTarget() != TARGET_UNIT_CASTER)
return false;
// but not this if this first effect (didn't find better check)
- if (Attributes & SPELL_ATTR0_NEGATIVE_1 && effIndex == 0)
+ if (HasAttribute(SPELL_ATTR0_NEGATIVE_1) && effIndex == 0)
return false;
break;
case SPELL_AURA_MECHANIC_IMMUNITY:
diff --git a/src/server/game/Spells/SpellInfo.h b/src/server/game/Spells/SpellInfo.h
index d9c062e77fd..f2808a089e1 100644
--- a/src/server/game/Spells/SpellInfo.h
+++ b/src/server/game/Spells/SpellInfo.h
@@ -376,6 +376,16 @@ public:
bool HasAura(AuraType aura) const;
bool HasAreaAuraEffect() const;
+ inline bool HasAttribute(SpellAttr0 attribute) const { return !!(Attributes & attribute); }
+ inline bool HasAttribute(SpellAttr1 attribute) const { return !!(AttributesEx & attribute); }
+ inline bool HasAttribute(SpellAttr2 attribute) const { return !!(AttributesEx2 & attribute); }
+ inline bool HasAttribute(SpellAttr3 attribute) const { return !!(AttributesEx3 & attribute); }
+ inline bool HasAttribute(SpellAttr4 attribute) const { return !!(AttributesEx4 & attribute); }
+ inline bool HasAttribute(SpellAttr5 attribute) const { return !!(AttributesEx5 & attribute); }
+ inline bool HasAttribute(SpellAttr6 attribute) const { return !!(AttributesEx6 & attribute); }
+ inline bool HasAttribute(SpellAttr7 attribute) const { return !!(AttributesEx7 & attribute); }
+ inline bool HasAttribute(SpellCustomAttributes customAttribute) const { return !!(AttributesCu & customAttribute); }
+
bool IsExplicitDiscovery() const;
bool IsLootCrafting() const;
bool IsQuestTame() const;
diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp
index 82052a6b443..be1384588fb 100644
--- a/src/server/game/Spells/SpellMgr.cpp
+++ b/src/server/game/Spells/SpellMgr.cpp
@@ -19,15 +19,11 @@
#include "SpellMgr.h"
#include "SpellInfo.h"
#include "ObjectMgr.h"
-#include "SpellAuras.h"
#include "SpellAuraDefines.h"
#include "SharedDefines.h"
#include "DBCStores.h"
-#include "World.h"
#include "Chat.h"
-#include "Spell.h"
#include "BattlegroundMgr.h"
-#include "MapManager.h"
#include "BattlefieldWG.h"
#include "BattlefieldMgr.h"
#include "Player.h"
@@ -2238,7 +2234,7 @@ void SpellMgr::LoadEnchantCustomAttr()
continue;
/// @todo find a better check
- if (!(spellInfo->AttributesEx2 & SPELL_ATTR2_PRESERVE_ENCHANT_IN_ARENA) || !(spellInfo->Attributes & SPELL_ATTR0_NOT_SHAPESHIFT))
+ if (!spellInfo->HasAttribute(SPELL_ATTR2_PRESERVE_ENCHANT_IN_ARENA) || !spellInfo->HasAttribute(SPELL_ATTR0_NOT_SHAPESHIFT))
continue;
for (uint32 j = 0; j < MAX_SPELL_EFFECTS; ++j)
@@ -3752,7 +3748,7 @@ void SpellMgr::LoadSpellInfoCorrections()
{
case SPELLFAMILY_PALADIN:
// Seals of the Pure should affect Seal of Righteousness
- if (spellInfo->SpellIconID == 25 && spellInfo->Attributes & SPELL_ATTR0_PASSIVE)
+ if (spellInfo->SpellIconID == 25 && spellInfo->HasAttribute(SPELL_ATTR0_PASSIVE))
spellInfo->Effects[EFFECT_0].SpellClassMask[1] |= 0x20000000;
break;
case SPELLFAMILY_DEATHKNIGHT:
diff --git a/src/server/game/Spells/SpellScript.cpp b/src/server/game/Spells/SpellScript.cpp
index 96977804f70..b347a982132 100644
--- a/src/server/game/Spells/SpellScript.cpp
+++ b/src/server/game/Spells/SpellScript.cpp
@@ -19,7 +19,6 @@
#include "Spell.h"
#include "SpellAuras.h"
#include "SpellScript.h"
-#include "SpellMgr.h"
bool _SpellScript::_Validate(SpellInfo const* entry)
{
diff --git a/src/server/game/Warden/Warden.cpp b/src/server/game/Warden/Warden.cpp
index aed2d73c422..ecf7697db0d 100644
--- a/src/server/game/Warden/Warden.cpp
+++ b/src/server/game/Warden/Warden.cpp
@@ -22,10 +22,8 @@
#include "Log.h"
#include "Opcodes.h"
#include "ByteBuffer.h"
-#include <openssl/md5.h>
#include <openssl/sha.h>
#include "World.h"
-#include "Player.h"
#include "Util.h"
#include "Warden.h"
#include "AccountMgr.h"
diff --git a/src/server/game/Warden/WardenCheckMgr.cpp b/src/server/game/Warden/WardenCheckMgr.cpp
index c2d095e6530..df9cd4786ad 100644
--- a/src/server/game/Warden/WardenCheckMgr.cpp
+++ b/src/server/game/Warden/WardenCheckMgr.cpp
@@ -21,7 +21,6 @@
#include "WorldSession.h"
#include "Log.h"
#include "Database/DatabaseEnv.h"
-#include "Util.h"
#include "WardenCheckMgr.h"
#include "Warden.h"
diff --git a/src/server/game/Warden/WardenWin.cpp b/src/server/game/Warden/WardenWin.cpp
index 5a9d2d174b4..7db5e8f39e5 100644
--- a/src/server/game/Warden/WardenWin.cpp
+++ b/src/server/game/Warden/WardenWin.cpp
@@ -32,7 +32,6 @@
#include "WardenWin.h"
#include "WardenModuleWin.h"
#include "WardenCheckMgr.h"
-#include "AccountMgr.h"
WardenWin::WardenWin() : Warden(), _serverTicks(0) {}
diff --git a/src/server/game/Weather/Weather.cpp b/src/server/game/Weather/Weather.cpp
index edcbe90498d..2a94cd26183 100644
--- a/src/server/game/Weather/Weather.cpp
+++ b/src/server/game/Weather/Weather.cpp
@@ -25,7 +25,6 @@
#include "Player.h"
#include "World.h"
#include "Log.h"
-#include "ObjectMgr.h"
#include "Util.h"
#include "ScriptMgr.h"
#include "WorldSession.h"
@@ -193,8 +192,10 @@ bool Weather::ReGenerate()
void Weather::SendWeatherUpdateToPlayer(Player* player)
{
- WorldPacket data(SMSG_WEATHER, (4+4+4));
- data << uint32(GetWeatherState()) << (float)m_grade << uint8(0);
+ WorldPacket data(SMSG_WEATHER, (4 + 4 + 1));
+ data << uint32(GetWeatherState());
+ data << (float)m_grade;
+ data << uint8(0);
player->GetSession()->SendPacket(&data);
}
@@ -209,7 +210,7 @@ bool Weather::UpdateWeather()
WeatherState state = GetWeatherState();
- WorldPacket data(SMSG_WEATHER, (4+4+4));
+ WorldPacket data(SMSG_WEATHER, (4 + 4 + 1));
data << uint32(state);
data << (float)m_grade;
data << uint8(0);
diff --git a/src/server/game/Weather/WeatherMgr.cpp b/src/server/game/Weather/WeatherMgr.cpp
index d1a614f494d..9100dd464b9 100644
--- a/src/server/game/Weather/WeatherMgr.cpp
+++ b/src/server/game/Weather/WeatherMgr.cpp
@@ -143,8 +143,10 @@ void LoadWeatherData()
void SendFineWeatherUpdateToPlayer(Player* player)
{
- WorldPacket data(SMSG_WEATHER, (4+4+4));
- data << (uint32)WEATHER_STATE_FINE << (float)0.0f << uint8(0);
+ WorldPacket data(SMSG_WEATHER, (4 + 4 + 1));
+ data << (uint32)WEATHER_STATE_FINE;
+ data << (float)0.0f;
+ data << uint8(0);
player->GetSession()->SendPacket(&data);
}
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index 555f89aad8f..9a84fa1670d 100644
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -940,6 +940,12 @@ void World::LoadConfigSettings(bool reload)
}
m_bool_configs[CONFIG_SAVE_RESPAWN_TIME_IMMEDIATELY] = sConfigMgr->GetBoolDefault("SaveRespawnTimeImmediately", true);
+ if (!m_bool_configs[CONFIG_SAVE_RESPAWN_TIME_IMMEDIATELY])
+ {
+ TC_LOG_WARN("server.loading", "SaveRespawnTimeImmediately triggers assertions when disabled, overridden to Enabled");
+ m_bool_configs[CONFIG_SAVE_RESPAWN_TIME_IMMEDIATELY] = true;
+ }
+
m_bool_configs[CONFIG_WEATHER] = sConfigMgr->GetBoolDefault("ActivateWeather", true);
m_int_configs[CONFIG_DISABLE_BREATHING] = sConfigMgr->GetIntDefault("DisableWaterBreath", SEC_CONSOLE);
@@ -1334,7 +1340,7 @@ void World::SetInitialWorldSettings()
!MapManager::ExistMapAndVMap(530, 10349.6f, -6357.29f) ||
!MapManager::ExistMapAndVMap(530, -3961.64f, -13931.2f))))
{
- TC_LOG_ERROR("server.loading", "Correct *.map files not found in path '%smaps' or *.vmtree/*.vmtile files in '%svmaps'. Please place *.map/*.vmtree/*.vmtile files in appropriate directories or correct the DataDir value in the worldserver.conf file.", m_dataPath.c_str(), m_dataPath.c_str());
+ TC_LOG_FATAL("server.loading", "Unable to load critical files - server shutting down !!!");
exit(1);
}
@@ -1908,28 +1914,24 @@ void World::DetectDBCLang()
TC_LOG_INFO("server.loading", "Using %s DBC Locale as default. All available DBC locales: %s", localeNames[m_defaultDbcLocale], availableLocalsStr.empty() ? "<none>" : availableLocalsStr.c_str());
}
-void World::RecordTimeDiff(const char *text, ...)
+void World::ResetTimeDiffRecord()
{
if (m_updateTimeCount != 1)
return;
- if (!text)
- {
- m_currentTime = getMSTime();
+
+ m_currentTime = getMSTime();
+}
+
+void World::RecordTimeDiff(std::string const& text)
+{
+ if (m_updateTimeCount != 1)
return;
- }
uint32 thisTime = getMSTime();
uint32 diff = getMSTimeDiff(m_currentTime, thisTime);
if (diff > m_int_configs[CONFIG_MIN_LOG_UPDATE])
- {
- va_list ap;
- char str[256];
- va_start(ap, text);
- vsnprintf(str, 256, text, ap);
- va_end(ap);
- TC_LOG_INFO("misc", "Difftime %s: %u.", str, diff);
- }
+ TC_LOG_INFO("misc", "Difftime %s: %u.", text.c_str(), diff);
m_currentTime = thisTime;
}
@@ -2046,7 +2048,7 @@ void World::Update(uint32 diff)
}
/// <li> Handle session updates when the timer has passed
- RecordTimeDiff(NULL);
+ ResetTimeDiffRecord();
UpdateSessions(diff);
RecordTimeDiff("UpdateSessions");
@@ -2093,7 +2095,7 @@ void World::Update(uint32 diff)
/// <li> Handle all other objects
///- Update objects when the timer has passed (maps, transport, creatures, ...)
- RecordTimeDiff(NULL);
+ ResetTimeDiffRecord();
sMapMgr->Update(diff);
RecordTimeDiff("UpdateMapMgr");
@@ -3018,7 +3020,7 @@ void World::ResetRandomBG()
{
TC_LOG_INFO("misc", "Random BG status reset for all characters.");
- PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_BATTLEGROUND_RANDOM);
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_BATTLEGROUND_RANDOM_ALL);
CharacterDatabase.Execute(stmt);
for (SessionMap::const_iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h
index 95c737936bc..af89adcb04e 100644
--- a/src/server/game/World/World.h
+++ b/src/server/game/World/World.h
@@ -741,7 +741,8 @@ class World
void LoadDBVersion();
char const* GetDBVersion() const { return m_DBVersion.c_str(); }
- void RecordTimeDiff(const char * text, ...);
+ void ResetTimeDiffRecord();
+ void RecordTimeDiff(std::string const& text);
void LoadAutobroadcasts();
diff --git a/src/server/scripts/CMakeLists.txt b/src/server/scripts/CMakeLists.txt
index e7d08d69805..20b970b6ac1 100644
--- a/src/server/scripts/CMakeLists.txt
+++ b/src/server/scripts/CMakeLists.txt
@@ -50,6 +50,7 @@ include_directories(
${CMAKE_SOURCE_DIR}/dep/recastnavigation/Recast/Include
${CMAKE_SOURCE_DIR}/dep/g3dlite/include
${CMAKE_SOURCE_DIR}/dep/SFMT
+ ${CMAKE_SOURCE_DIR}/dep/cppformat
${CMAKE_SOURCE_DIR}/dep/zlib
${CMAKE_SOURCE_DIR}/src/server/shared
${CMAKE_SOURCE_DIR}/src/server/shared/Configuration
@@ -62,6 +63,7 @@ include_directories(
${CMAKE_SOURCE_DIR}/src/server/shared/Logging
${CMAKE_SOURCE_DIR}/src/server/shared/Packets
${CMAKE_SOURCE_DIR}/src/server/shared/Threading
+ ${CMAKE_SOURCE_DIR}/src/server/shared/Updater
${CMAKE_SOURCE_DIR}/src/server/shared/Utilities
${CMAKE_SOURCE_DIR}/src/server/collision
${CMAKE_SOURCE_DIR}/src/server/collision/Management
@@ -144,6 +146,8 @@ include_directories(
${VALGRIND_INCLUDE_DIR}
)
+GroupSources(${CMAKE_CURRENT_SOURCE_DIR})
+
add_library(scripts STATIC
${scripts_STAT_SRCS}
${scripts_STAT_PCH_SRC}
diff --git a/src/server/scripts/Commands/cs_lfg.cpp b/src/server/scripts/Commands/cs_lfg.cpp
index 308a841df2a..747d84de9c5 100644
--- a/src/server/scripts/Commands/cs_lfg.cpp
+++ b/src/server/scripts/Commands/cs_lfg.cpp
@@ -47,15 +47,15 @@ public:
{
{ "player", rbac::RBAC_PERM_COMMAND_LFG_PLAYER, false, &HandleLfgPlayerInfoCommand, "", NULL },
{ "group", rbac::RBAC_PERM_COMMAND_LFG_GROUP, false, &HandleLfgGroupInfoCommand, "", NULL },
- { "queue", rbac::RBAC_PERM_COMMAND_LFG_QUEUE, false, &HandleLfgQueueInfoCommand, "", NULL },
- { "clean", rbac::RBAC_PERM_COMMAND_LFG_CLEAN, false, &HandleLfgCleanCommand, "", NULL },
- { "options", rbac::RBAC_PERM_COMMAND_LFG_OPTIONS, false, &HandleLfgOptionsCommand, "", NULL },
+ { "queue", rbac::RBAC_PERM_COMMAND_LFG_QUEUE, true, &HandleLfgQueueInfoCommand, "", NULL },
+ { "clean", rbac::RBAC_PERM_COMMAND_LFG_CLEAN, true, &HandleLfgCleanCommand, "", NULL },
+ { "options", rbac::RBAC_PERM_COMMAND_LFG_OPTIONS, true, &HandleLfgOptionsCommand, "", NULL },
{ NULL, 0, false, NULL, "", NULL }
};
static ChatCommand commandTable[] =
{
- { "lfg", rbac::RBAC_PERM_COMMAND_LFG, false, NULL, "", lfgCommandTable },
+ { "lfg", rbac::RBAC_PERM_COMMAND_LFG, true, NULL, "", lfgCommandTable },
{ NULL, 0, false, NULL, "", NULL }
};
return commandTable;
@@ -118,7 +118,7 @@ public:
static bool HandleLfgQueueInfoCommand(ChatHandler* handler, char const* args)
{
- handler->SendSysMessage(sLFGMgr->DumpQueueInfo(atoi(args) != 0).c_str());
+ handler->SendSysMessage(sLFGMgr->DumpQueueInfo(*args != '\0').c_str());
return true;
}
diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp
index 0e86823aa7c..52cc20b9d3b 100644
--- a/src/server/scripts/Commands/cs_misc.cpp
+++ b/src/server/scripts/Commands/cs_misc.cpp
@@ -25,7 +25,6 @@
#include "InstanceSaveMgr.h"
#include "Language.h"
#include "MovementGenerator.h"
-#include "ObjectAccessor.h"
#include "Opcodes.h"
#include "SpellAuras.h"
#include "TargetedMovementGenerator.h"
@@ -237,7 +236,8 @@ public:
zoneId, (zoneEntry ? zoneEntry->area_name[handler->GetSessionDbcLocale()] : unknown),
areaId, (areaEntry ? areaEntry->area_name[handler->GetSessionDbcLocale()] : unknown),
object->GetPhaseMask(),
- object->GetPositionX(), object->GetPositionY(), object->GetPositionZ(), object->GetOrientation(),
+ object->GetPositionX(), object->GetPositionY(), object->GetPositionZ(), object->GetOrientation());
+ handler->PSendSysMessage(LANG_GRID_POSITION,
cell.GridX(), cell.GridY(), cell.CellX(), cell.CellY(), object->GetInstanceId(),
zoneX, zoneY, groundZ, floorZ, haveMap, haveVMap, haveMMap);
diff --git a/src/server/scripts/EasternKingdoms/Karazhan/karazhan.cpp b/src/server/scripts/EasternKingdoms/Karazhan/karazhan.cpp
index 59f2ce1a2c9..92c3f83034d 100644
--- a/src/server/scripts/EasternKingdoms/Karazhan/karazhan.cpp
+++ b/src/server/scripts/EasternKingdoms/Karazhan/karazhan.cpp
@@ -360,17 +360,17 @@ public:
case GOSSIP_ACTION_INFO_DEF+3:
player->CLOSE_GOSSIP_MENU();
pBarnesAI->m_uiEventId = EVENT_OZ;
- TC_LOG_INFO("scripts", "player (%s) manually set Opera event to EVENT_OZ", player->GetGUID().ToString().c_str());
+ TC_LOG_DEBUG("scripts", "player (%s) manually set Opera event to EVENT_OZ", player->GetGUID().ToString().c_str());
break;
case GOSSIP_ACTION_INFO_DEF+4:
player->CLOSE_GOSSIP_MENU();
pBarnesAI->m_uiEventId = EVENT_HOOD;
- TC_LOG_INFO("scripts", "player (%s) manually set Opera event to EVENT_HOOD", player->GetGUID().ToString().c_str());
+ TC_LOG_DEBUG("scripts", "player (%s) manually set Opera event to EVENT_HOOD", player->GetGUID().ToString().c_str());
break;
case GOSSIP_ACTION_INFO_DEF+5:
player->CLOSE_GOSSIP_MENU();
pBarnesAI->m_uiEventId = EVENT_RAJ;
- TC_LOG_INFO("scripts", "player (%s) manually set Opera event to EVENT_RAJ", player->GetGUID().ToString().c_str());
+ TC_LOG_DEBUG("scripts", "player (%s) manually set Opera event to EVENT_RAJ", player->GetGUID().ToString().c_str());
break;
}
diff --git a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp
index 3db0e1092fd..326360428d2 100644
--- a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp
+++ b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp
@@ -174,7 +174,7 @@ public:
anchor->GetContactPoint(me, anchorX, anchorY, z, 1.0f);
playerGUID = target->GetGUID();
- Talk(SAY_EVENT_START);
+ Talk(SAY_EVENT_START, target);
}
void UpdateAI(uint32 diff) override
diff --git a/src/server/scripts/EasternKingdoms/SunkenTemple/sunken_temple.cpp b/src/server/scripts/EasternKingdoms/SunkenTemple/sunken_temple.cpp
index 3ced85f09a2..97be139cefe 100644
--- a/src/server/scripts/EasternKingdoms/SunkenTemple/sunken_temple.cpp
+++ b/src/server/scripts/EasternKingdoms/SunkenTemple/sunken_temple.cpp
@@ -36,19 +36,27 @@ EndContentData */
# at_malfurion_Stormrage_trigger
#####*/
-class at_malfurion_stormrage : public AreaTriggerScript
+enum MalfurionMisc
{
-public:
- at_malfurion_stormrage() : AreaTriggerScript("at_malfurion_stormrage") { }
+ NPC_MALFURION_STORMRAGE = 15362,
+ QUEST_ERANIKUS_TYRANT_OF_DREAMS = 8733,
+ QUEST_THE_CHARGE_OF_DRAGONFLIGHTS = 8555,
+};
- bool OnTrigger(Player* player, const AreaTriggerEntry* /*at*/) override
- {
- if (player->GetInstanceScript() && !player->FindNearestCreature(15362, 15))
- player->SummonCreature(15362, player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), -1.52f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 100000);
- return false;
- }
+class at_malfurion_stormrage : public AreaTriggerScript
+{
+ public:
+ at_malfurion_stormrage() : AreaTriggerScript("at_malfurion_stormrage") { }
+ bool OnTrigger(Player* player, const AreaTriggerEntry* /*at*/) override
+ {
+ if (player->GetInstanceScript() && !player->FindNearestCreature(NPC_MALFURION_STORMRAGE, 15.0f) &&
+ player->GetQuestStatus(QUEST_THE_CHARGE_OF_DRAGONFLIGHTS) == QUEST_STATUS_REWARDED && player->GetQuestStatus(QUEST_ERANIKUS_TYRANT_OF_DREAMS) != QUEST_STATUS_REWARDED)
+ player->SummonCreature(NPC_MALFURION_STORMRAGE, player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), -1.52f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 100000);
+ return false;
+ }
};
+
/*#####
# go_atalai_statue
#####*/
diff --git a/src/server/scripts/EasternKingdoms/ZulAman/boss_hexlord.cpp b/src/server/scripts/EasternKingdoms/ZulAman/boss_hexlord.cpp
index 01ac3920082..1a98c081570 100644
--- a/src/server/scripts/EasternKingdoms/ZulAman/boss_hexlord.cpp
+++ b/src/server/scripts/EasternKingdoms/ZulAman/boss_hexlord.cpp
@@ -689,54 +689,57 @@ class boss_alyson_antille : public CreatureScript
}
};
-struct boss_gazakrothAI : public boss_hexlord_addAI
+class boss_gazakroth : public CreatureScript
{
- boss_gazakrothAI(Creature* creature) : boss_hexlord_addAI(creature)
- {
- Initialize();
- }
-
- void Initialize()
- {
- firebolt_timer = 2000;
- }
+ public:
- uint32 firebolt_timer;
+ boss_gazakroth() : CreatureScript("boss_gazakroth") { }
+
+ struct boss_gazakrothAI : public boss_hexlord_addAI
+ {
+ boss_gazakrothAI(Creature* creature) : boss_hexlord_addAI(creature)
+ {
+ Initialize();
+ }
- void Reset() override
- {
- Initialize();
- boss_hexlord_addAI::Reset();
- }
+ void Initialize()
+ {
+ firebolt_timer = 2 * IN_MILLISECONDS;
+ }
+
+ void Reset() override
+ {
+ Initialize();
+ boss_hexlord_addAI::Reset();
+ }
- void AttackStart(Unit* who) override
- {
- if (!who)
- return;
+ void AttackStart(Unit* who) override
+ {
+ AttackStartCaster(who, 20.0f);
+ }
- if (who->isTargetableForAttack())
- {
- if (me->Attack(who, false))
+ void UpdateAI(uint32 diff) override
{
- me->GetMotionMaster()->MoveChase(who, 20);
- me->AddThreat(who, 0.0f);
+ if (!UpdateVictim())
+ return;
+
+ if (firebolt_timer <= diff)
+ {
+ DoCastVictim(SPELL_FIREBOLT, false);
+ firebolt_timer = 0.7 * IN_MILLISECONDS;
+ } else firebolt_timer -= diff;
+
+ boss_hexlord_addAI::UpdateAI(diff);
}
- }
- }
- void UpdateAI(uint32 diff) override
- {
- if (!UpdateVictim())
- return;
+ private:
+ uint32 firebolt_timer;
+ };
- if (firebolt_timer <= diff)
+ CreatureAI* GetAI(Creature* creature) const override
{
- DoCastVictim(SPELL_FIREBOLT, false);
- firebolt_timer = 700;
- } else firebolt_timer -= diff;
-
- boss_hexlord_addAI::UpdateAI(diff);
- }
+ return GetInstanceAI<boss_gazakrothAI>(creature);
+ }
};
class boss_lord_raadan : public CreatureScript
@@ -1062,7 +1065,7 @@ void AddSC_boss_hex_lord_malacrass()
{
new boss_hexlord_malacrass();
new boss_thurg();
- // new boss_gazakroth();
+ new boss_gazakroth();
new boss_lord_raadan();
new boss_darkheart();
new boss_slither();
diff --git a/src/server/scripts/EasternKingdoms/zone_redridge_mountains.cpp b/src/server/scripts/EasternKingdoms/zone_redridge_mountains.cpp
index 898e3f9a2cb..ecfd705cf4d 100644
--- a/src/server/scripts/EasternKingdoms/zone_redridge_mountains.cpp
+++ b/src/server/scripts/EasternKingdoms/zone_redridge_mountains.cpp
@@ -92,7 +92,7 @@ public:
me->SetWalk(false);
break;
case 115:
- player->AreaExploredOrEventHappens(QUEST_MISSING_IN_ACTION);
+ player->GroupEventHappens(QUEST_MISSING_IN_ACTION, me);
timer = 2000;
phase = 4;
break;
diff --git a/src/server/scripts/EasternKingdoms/zone_undercity.cpp b/src/server/scripts/EasternKingdoms/zone_undercity.cpp
index 9ce694fb76c..ca281bab60a 100644
--- a/src/server/scripts/EasternKingdoms/zone_undercity.cpp
+++ b/src/server/scripts/EasternKingdoms/zone_undercity.cpp
@@ -40,25 +40,44 @@ EndContentData */
enum Sylvanas
{
- QUEST_JOURNEY_TO_UNDERCITY = 9180,
- EMOTE_LAMENT_END = 0,
- SAY_LAMENT_END = 1,
+ QUEST_JOURNEY_TO_UNDERCITY = 9180,
- SOUND_CREDIT = 10896,
- ENTRY_HIGHBORNE_LAMENTER = 21628,
- ENTRY_HIGHBORNE_BUNNY = 21641,
+ EMOTE_LAMENT_END = 0,
+ SAY_LAMENT_END = 1,
+ EMOTE_LAMENT = 2,
- SPELL_HIGHBORNE_AURA = 37090,
- SPELL_SYLVANAS_CAST = 36568,
- SPELL_RIBBON_OF_SOULS = 34432, // the real one to use might be 37099
+ // Ambassador Sunsorrow
+ SAY_SUNSORROW_WHISPER = 0,
+
+ SOUND_CREDIT = 10896,
+
+ NPC_HIGHBORNE_LAMENTER = 21628,
+ NPC_HIGHBORNE_BUNNY = 21641,
+ NPC_AMBASSADOR_SUNSORROW = 16287,
+
+ SPELL_HIGHBORNE_AURA = 37090,
+ SPELL_SYLVANAS_CAST = 36568,
+ //SPELL_RIBBON_OF_SOULS = 34432, the real one to use might be 37099
+ SPELL_RIBBON_OF_SOULS = 37099,
// Combat spells
- SPELL_BLACK_ARROW = 59712,
- SPELL_FADE = 20672,
- SPELL_FADE_BLINK = 29211,
- SPELL_MULTI_SHOT = 59713,
- SPELL_SHOT = 59710,
- SPELL_SUMMON_SKELETON = 59711
+ SPELL_BLACK_ARROW = 59712,
+ SPELL_FADE = 20672,
+ SPELL_FADE_BLINK = 29211,
+ SPELL_MULTI_SHOT = 59713,
+ SPELL_SHOT = 59710,
+ SPELL_SUMMON_SKELETON = 59711,
+
+ // Events
+ EVENT_FADE = 1,
+ EVENT_SUMMON_SKELETON = 2,
+ EVENT_BLACK_ARROW = 3,
+ EVENT_SHOOT = 4,
+ EVENT_MULTI_SHOT = 5,
+ EVENT_LAMENT_OF_THE_HIGHBORN = 6,
+ EVENT_SUNSORROW_WHISPER = 7,
+
+ GUID_EVENT_INVOKER = 1,
};
float HighborneLoc[4][3]=
@@ -77,26 +96,14 @@ class npc_lady_sylvanas_windrunner : public CreatureScript
public:
npc_lady_sylvanas_windrunner() : CreatureScript("npc_lady_sylvanas_windrunner") { }
- bool OnQuestReward(Player* /*player*/, Creature* creature, const Quest *_Quest, uint32 /*slot*/) override
+ bool OnQuestReward(Player* player, Creature* creature, const Quest *_Quest, uint32 /*slot*/) override
{
if (_Quest->GetQuestId() == QUEST_JOURNEY_TO_UNDERCITY)
- {
- ENSURE_AI(npc_lady_sylvanas_windrunner::npc_lady_sylvanas_windrunnerAI, creature->AI())->LamentEvent = true;
- ENSURE_AI(npc_lady_sylvanas_windrunner::npc_lady_sylvanas_windrunnerAI, creature->AI())->DoPlaySoundToSet(creature, SOUND_CREDIT);
- creature->CastSpell(creature, SPELL_SYLVANAS_CAST, false);
-
- for (uint8 i = 0; i < 4; ++i)
- creature->SummonCreature(ENTRY_HIGHBORNE_LAMENTER, HighborneLoc[i][0], HighborneLoc[i][1], HIGHBORNE_LOC_Y, HighborneLoc[i][2], TEMPSUMMON_TIMED_DESPAWN, 160000);
- }
+ creature->AI()->SetGUID(player->GetGUID(), GUID_EVENT_INVOKER);
return true;
}
- CreatureAI* GetAI(Creature* creature) const override
- {
- return new npc_lady_sylvanas_windrunnerAI(creature);
- }
-
struct npc_lady_sylvanas_windrunnerAI : public ScriptedAI
{
npc_lady_sylvanas_windrunnerAI(Creature* creature) : ScriptedAI(creature)
@@ -106,41 +113,51 @@ public:
void Initialize()
{
- LamentEventTimer = 5000;
LamentEvent = false;
targetGUID.Clear();
-
- FadeTimer = 30000;
- SummonSkeletonTimer = 20000;
- BlackArrowTimer = 15000;
- ShotTimer = 8000;
- MultiShotTimer = 10000;
+ playerGUID.Clear();
}
- uint32 LamentEventTimer;
- bool LamentEvent;
- ObjectGuid targetGUID;
-
- uint32 FadeTimer;
- uint32 SummonSkeletonTimer;
- uint32 BlackArrowTimer;
- uint32 ShotTimer;
- uint32 MultiShotTimer;
-
void Reset() override
{
Initialize();
+ _events.Reset();
}
- void EnterCombat(Unit* /*who*/) override { }
+ void EnterCombat(Unit* /*who*/) override
+ {
+ _events.ScheduleEvent(EVENT_FADE, 30000);
+ _events.ScheduleEvent(EVENT_SUMMON_SKELETON, 20000);
+ _events.ScheduleEvent(EVENT_BLACK_ARROW, 15000);
+ _events.ScheduleEvent(EVENT_SHOOT, 8000);
+ _events.ScheduleEvent(EVENT_MULTI_SHOT, 10000);
+ }
+
+ void SetGUID(ObjectGuid guid, int32 type) override
+ {
+ if (type == GUID_EVENT_INVOKER)
+ {
+ Talk(EMOTE_LAMENT);
+ DoPlaySoundToSet(me, SOUND_CREDIT);
+ DoCast(me, SPELL_SYLVANAS_CAST, false);
+ playerGUID = guid;
+ LamentEvent = true;
+
+ for (uint8 i = 0; i < 4; ++i)
+ me->SummonCreature(NPC_HIGHBORNE_LAMENTER, HighborneLoc[i][0], HighborneLoc[i][1], HIGHBORNE_LOC_Y, HighborneLoc[i][2], TEMPSUMMON_TIMED_DESPAWN, 160000);
+
+ _events.ScheduleEvent(EVENT_LAMENT_OF_THE_HIGHBORN, 2000);
+ _events.ScheduleEvent(EVENT_SUNSORROW_WHISPER, 10000);
+ }
+ }
void JustSummoned(Creature* summoned) override
{
- if (summoned->GetEntry() == ENTRY_HIGHBORNE_BUNNY)
+ if (summoned->GetEntry() == NPC_HIGHBORNE_BUNNY)
{
if (Creature* target = ObjectAccessor::GetCreature(*summoned, targetGUID))
{
- target->MonsterMoveWithSpeed(target->GetPositionX(), target->GetPositionY(), me->GetPositionZ()+15.0f, 0);
+ target->GetMotionMaster()->MoveJump(target->GetPositionX(), target->GetPositionY(), me->GetPositionZ() + 15.0f, 0);
target->SetPosition(target->GetPositionX(), target->GetPositionY(), me->GetPositionZ()+15.0f, 0.0f);
summoned->CastSpell(target, SPELL_RIBBON_OF_SOULS, false);
}
@@ -152,75 +169,86 @@ public:
void UpdateAI(uint32 diff) override
{
- if (LamentEvent)
- {
- if (LamentEventTimer <= diff)
- {
- DoSummon(ENTRY_HIGHBORNE_BUNNY, me, 10.0f, 3000, TEMPSUMMON_TIMED_DESPAWN);
-
- LamentEventTimer = 2000;
- if (!me->HasAura(SPELL_SYLVANAS_CAST))
- {
- Talk(SAY_LAMENT_END);
- Talk(EMOTE_LAMENT_END);
- LamentEvent = false;
- }
- } else LamentEventTimer -= diff;
- }
-
- if (!UpdateVictim())
+ if (!UpdateVictim() && !LamentEvent)
return;
- // Combat spells
-
- if (FadeTimer <= diff)
- {
- DoCast(me, SPELL_FADE);
- // add a blink to simulate a stealthed movement and reappearing elsewhere
- DoCast(me, SPELL_FADE_BLINK);
- FadeTimer = 30000 + rand32() % 5000;
- // if the victim is out of melee range she cast multi shot
- if (Unit* victim = me->GetVictim())
- if (me->GetDistance(victim) > 10.0f)
- DoCast(victim, SPELL_MULTI_SHOT);
- } else FadeTimer -= diff;
-
- if (SummonSkeletonTimer <= diff)
- {
- DoCast(me, SPELL_SUMMON_SKELETON);
- SummonSkeletonTimer = 20000 + rand32() % 10000;
- } else SummonSkeletonTimer -= diff;
-
- if (BlackArrowTimer <= diff)
- {
- if (Unit* victim = me->GetVictim())
- {
- DoCast(victim, SPELL_BLACK_ARROW);
- BlackArrowTimer = 15000 + rand32() % 5000;
- }
- } else BlackArrowTimer -= diff;
+ _events.Update(diff);
- if (ShotTimer <= diff)
- {
- if (Unit* victim = me->GetVictim())
- {
- DoCast(victim, SPELL_SHOT);
- ShotTimer = 8000 + rand32() % 2000;
- }
- } else ShotTimer -= diff;
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
- if (MultiShotTimer <= diff)
+ while (uint32 eventId = _events.ExecuteEvent())
{
- if (Unit* victim = me->GetVictim())
+ switch (eventId)
{
- DoCast(victim, SPELL_MULTI_SHOT);
- MultiShotTimer = 10000 + rand32() % 3000;
+ case EVENT_FADE:
+ DoCast(me, SPELL_FADE);
+ // add a blink to simulate a stealthed movement and reappearing elsewhere
+ DoCast(me, SPELL_FADE_BLINK);
+ // if the victim is out of melee range she cast multi shot
+ if (Unit* victim = me->GetVictim())
+ if (me->GetDistance(victim) > 10.0f)
+ DoCast(victim, SPELL_MULTI_SHOT);
+ _events.ScheduleEvent(EVENT_FADE, urand(30000, 35000));
+ break;
+ case EVENT_SUMMON_SKELETON:
+ DoCast(me, SPELL_SUMMON_SKELETON);
+ _events.ScheduleEvent(EVENT_SUMMON_SKELETON, urand(20000, 30000));
+ break;
+ case EVENT_BLACK_ARROW:
+ if (Unit* victim = me->GetVictim())
+ DoCast(victim, SPELL_BLACK_ARROW);
+ _events.ScheduleEvent(EVENT_BLACK_ARROW, urand(15000, 20000));
+ break;
+ case EVENT_SHOOT:
+ if (Unit* victim = me->GetVictim())
+ DoCast(victim, SPELL_SHOT);
+ _events.ScheduleEvent(EVENT_SHOOT, urand(8000, 10000));
+ break;
+ case EVENT_MULTI_SHOT:
+ if (Unit* victim = me->GetVictim())
+ DoCast(victim, SPELL_MULTI_SHOT);
+ _events.ScheduleEvent(EVENT_MULTI_SHOT, urand(10000, 13000));
+ break;
+ case EVENT_LAMENT_OF_THE_HIGHBORN:
+ if (!me->HasAura(SPELL_SYLVANAS_CAST))
+ {
+ Talk(SAY_LAMENT_END);
+ Talk(EMOTE_LAMENT_END);
+ LamentEvent = false;
+ me->HandleEmoteCommand(EMOTE_ONESHOT_KNEEL);
+ Reset();
+ }
+ else
+ {
+ DoSummon(NPC_HIGHBORNE_BUNNY, me, 10.0f, 3000, TEMPSUMMON_TIMED_DESPAWN);
+ _events.ScheduleEvent(EVENT_LAMENT_OF_THE_HIGHBORN, 2000);
+ }
+ break;
+ case EVENT_SUNSORROW_WHISPER:
+ if (Creature* ambassador = me->FindNearestCreature(NPC_AMBASSADOR_SUNSORROW, 20.0f))
+ if (Player* player = ObjectAccessor::GetPlayer(*me, playerGUID))
+ ambassador->AI()->Talk(SAY_SUNSORROW_WHISPER, player);
+ break;
+ default:
+ break;
}
- } else MultiShotTimer -= diff;
+ }
DoMeleeAttackIfReady();
}
+
+ private:
+ EventMap _events;
+ bool LamentEvent;
+ ObjectGuid targetGUID;
+ ObjectGuid playerGUID;
};
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return new npc_lady_sylvanas_windrunnerAI(creature);
+ }
};
/*######
diff --git a/src/server/scripts/Kalimdor/CMakeLists.txt b/src/server/scripts/Kalimdor/CMakeLists.txt
index 9a68973b8d1..ce8d0cfbcfd 100644
--- a/src/server/scripts/Kalimdor/CMakeLists.txt
+++ b/src/server/scripts/Kalimdor/CMakeLists.txt
@@ -92,7 +92,6 @@ set(scripts_STAT_SRCS
Kalimdor/RuinsOfAhnQiraj/boss_moam.cpp
Kalimdor/RuinsOfAhnQiraj/ruins_of_ahnqiraj.h
Kalimdor/RuinsOfAhnQiraj/boss_kurinnaxx.cpp
- Kalimdor/zone_mulgore.cpp
Kalimdor/zone_bloodmyst_isle.cpp
Kalimdor/zone_thunder_bluff.cpp
Kalimdor/zone_azshara.cpp
diff --git a/src/server/scripts/Kalimdor/RazorfenKraul/razorfen_kraul.cpp b/src/server/scripts/Kalimdor/RazorfenKraul/razorfen_kraul.cpp
index a7c17a9df3e..f4a7e1f4185 100644
--- a/src/server/scripts/Kalimdor/RazorfenKraul/razorfen_kraul.cpp
+++ b/src/server/scripts/Kalimdor/RazorfenKraul/razorfen_kraul.cpp
@@ -136,131 +136,7 @@ public:
}
};
-enum SnufflenoseGopher
-{
- NPC_SNUFFLENOSE_GOPHER = 4781,
- GO_BLUELEAF_TUBBER = 20920,
- ACTION_FIND_NEW_TUBBER = 0,
- POINT_TUBBER = 0
-};
-
-struct npc_snufflenose_gopher : public CreatureScript
-{
-public:
- npc_snufflenose_gopher() : CreatureScript("npc_snufflenose_gopher") { }
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return new npc_snufflenose_gopherAI(creature);
- }
-
- struct npc_snufflenose_gopherAI : public PetAI
- {
- npc_snufflenose_gopherAI(Creature* creature) : PetAI(creature)
- {
- IsMovementActive = false;
- }
-
- void Reset() override
- {
- IsMovementActive = false;
- TargetTubberGUID.Clear();
- }
-
- void MovementInform(uint32 type, uint32 id) override
- {
- if (type == POINT_MOTION_TYPE && id == POINT_TUBBER)
- {
- if (GameObject* go = me->GetMap()->GetGameObject(TargetTubberGUID))
- {
- go->SetRespawnTime(5 * MINUTE);
- go->Refresh();
- go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_INTERACT_COND);
- }
-
- IsMovementActive = false;
- }
- else
- PetAI::MovementInform(type, id);
- }
-
- void DoFindNewTubber()
- {
- std::list<GameObject*> tubbersInRange;
- GetGameObjectListWithEntryInGrid(tubbersInRange, me, GO_BLUELEAF_TUBBER, 40.0f);
-
- if (tubbersInRange.empty())
- return;
-
- tubbersInRange.remove_if([](GameObject* go)
- {
- return go->isSpawned() || !go->HasFlag(GAMEOBJECT_FLAGS, GO_FLAG_INTERACT_COND);
- });
-
- tubbersInRange.sort(Trinity::ObjectDistanceOrderPred(me));
-
- GameObject* nearestTubber = tubbersInRange.front();
- if (!nearestTubber)
- return;
-
- TargetTubberGUID = nearestTubber->GetGUID();
-
- // XFurry was wrong...
- me->GetMotionMaster()->MovePoint(POINT_TUBBER, nearestTubber->GetPositionX(),
- nearestTubber->GetPositionY(),
- nearestTubber->GetPositionZ());
- IsMovementActive = true;
- }
-
- void UpdateAI(uint32 diff) override
- {
- if (!IsMovementActive)
- PetAI::UpdateAI(diff);
- }
-
- void DoAction(int32 action) override
- {
- if (action == ACTION_FIND_NEW_TUBBER)
- DoFindNewTubber();
- }
-
-
- bool IsMovementActive;
- ObjectGuid TargetTubberGUID;
- };
-};
-
-class spell_snufflenose_command : public SpellScriptLoader
-{
- public:
- spell_snufflenose_command() : SpellScriptLoader("spell_snufflenose_command") { }
-
- class spell_snufflenose_commandSpellScript : public SpellScript
- {
- PrepareSpellScript(spell_snufflenose_commandSpellScript);
-
- void HandleEffect(SpellEffIndex /*effIndex*/)
- {
- if (Creature* target = GetHitCreature())
- if (target->GetEntry() == NPC_SNUFFLENOSE_GOPHER)
- target->AI()->DoAction(ACTION_FIND_NEW_TUBBER);
- }
-
- void Register() override
- {
- OnEffectHitTarget += SpellEffectFn(spell_snufflenose_commandSpellScript::HandleEffect, EFFECT_0, SPELL_EFFECT_DUMMY);
- }
- };
-
- SpellScript* GetSpellScript() const override
- {
- return new spell_snufflenose_commandSpellScript();
- }
-};
-
void AddSC_razorfen_kraul()
{
- new npc_snufflenose_gopher();
new npc_willix();
- new spell_snufflenose_command();
}
diff --git a/src/server/scripts/Kalimdor/zone_bloodmyst_isle.cpp b/src/server/scripts/Kalimdor/zone_bloodmyst_isle.cpp
index ca5e4697c35..99342b5a628 100644
--- a/src/server/scripts/Kalimdor/zone_bloodmyst_isle.cpp
+++ b/src/server/scripts/Kalimdor/zone_bloodmyst_isle.cpp
@@ -27,10 +27,14 @@ EndScriptData */
npc_webbed_creature
EndContentData */
+#include "Player.h"
+#include "Group.h"
+#include "GridNotifiersImpl.h"
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
+#include "ScriptedEscortAI.h"
#include "PassiveAI.h"
-#include "Player.h"
+#include "CellImpl.h"
/*######
## npc_webbed_creature
@@ -88,7 +92,723 @@ public:
}
};
+/*######
+## Quest 9759: Ending Their World
+######*/
+
+enum EndingTheirWorldMisc
+{
+ SAY_SIRONAS_1 = 0,
+
+ SAY_LEGOSO_1 = 0,
+ SAY_LEGOSO_2 = 1,
+ SAY_LEGOSO_3 = 2,
+ SAY_LEGOSO_4 = 3,
+ SAY_LEGOSO_5 = 4,
+ SAY_LEGOSO_6 = 5,
+ SAY_LEGOSO_7 = 6,
+ SAY_LEGOSO_8 = 7,
+ SAY_LEGOSO_9 = 8,
+ SAY_LEGOSO_10 = 9,
+ SAY_LEGOSO_11 = 10,
+ SAY_LEGOSO_12 = 11,
+ SAY_LEGOSO_13 = 12,
+ SAY_LEGOSO_14 = 13,
+ SAY_LEGOSO_15 = 14,
+ SAY_LEGOSO_16 = 15,
+ SAY_LEGOSO_17 = 16,
+ SAY_LEGOSO_18 = 17,
+ SAY_LEGOSO_19 = 18,
+ SAY_LEGOSO_20 = 19,
+ SAY_LEGOSO_21 = 20,
+
+ SPELL_BLOODMYST_TESLA = 31611,
+ SPELL_SIRONAS_CHANNELING = 31612,
+
+ SPELL_UPPERCUT = 10966,
+ SPELL_IMMOLATE = 12742,
+ SPELL_CURSE_OF_BLOOD = 8282,
+
+ SPELL_FROST_SHOCK = 8056,
+ SPELL_HEALING_SURGE = 8004,
+ SPELL_SEARING_TOTEM = 38116,
+ SPELL_STRENGTH_OF_EARTH_TOTEM = 31633,
+
+ NPC_SIRONAS = 17678,
+ NPC_BLOODMYST_TESLA_COIL = 17979,
+ NPC_LEGOSO = 17982,
+
+ GO_DRAENEI_EXPLOSIVES_1 = 182088,
+ GO_DRAENEI_EXPLOSIVES_2 = 182091,
+ GO_FIRE_EXPLOSION = 182071,
+
+ ACTION_SIRONAS_CHANNEL_START = 1,
+ ACTION_SIRONAS_CHANNEL_STOP = 2,
+
+ ACTION_LEGOSO_SIRONAS_KILLED = 1,
+
+ EVENT_UPPERCUT = 1,
+ EVENT_IMMOLATE = 2,
+ EVENT_CURSE_OF_BLOOD = 3,
+
+ EVENT_FROST_SHOCK = 1,
+ EVENT_HEALING_SURGE = 2,
+ EVENT_SEARING_TOTEM = 3,
+ EVENT_STRENGTH_OF_EARTH_TOTEM = 4,
+
+ WP_START = 1,
+ WP_EXPLOSIVES_FIRST_POINT = 21,
+ WP_EXPLOSIVES_FIRST_PLANT = 22,
+ WP_EXPLOSIVES_FIRST_RUNOFF = 23,
+ WP_EXPLOSIVES_FIRST_DETONATE = 24,
+ WP_DEBUG_1 = 25,
+ WP_DEBUG_2 = 26,
+ WP_SIRONAS_HILL = 33,
+ WP_EXPLOSIVES_SECOND_BATTLEROAR = 35,
+ WP_EXPLOSIVES_SECOND_PLANT = 39,
+ WP_EXPLOSIVES_SECOND_DETONATE = 40,
+
+ PHASE_NONE = 0,
+ PHASE_CONTINUE = -1,
+ PHASE_WP_26 = 1,
+ PHASE_WP_22 = 2,
+ PHASE_PLANT_FIRST_KNEEL = 3,
+ PHASE_PLANT_FIRST_STAND = 4,
+ PHASE_PLANT_FIRST_WORK = 5,
+ PHASE_PLANT_FIRST_FINISH = 6,
+ PHASE_PLANT_FIRST_TIMER_1 = 7,
+ PHASE_PLANT_FIRST_TIMER_2 = 8,
+ PHASE_PLANT_FIRST_TIMER_3 = 9,
+ PHASE_PLANT_FIRST_DETONATE = 10,
+ PHASE_PLANT_FIRST_SPEECH = 11,
+ PHASE_PLANT_FIRST_ROTATE = 12,
+ PHASE_PLANT_FIRST_POINT = 13,
+ PHASE_FEEL_SIRONAS_1 = 14,
+ PHASE_FEEL_SIRONAS_2 = 15,
+ PHASE_MEET_SIRONAS_ROAR = 16,
+ PHASE_MEET_SIRONAS_TURN = 17,
+ PHASE_MEET_SIRONAS_SPEECH = 18,
+ PHASE_PLANT_SECOND_KNEEL = 19,
+ PHASE_PLANT_SECOND_SPEECH = 20,
+ PHASE_PLANT_SECOND_STAND = 21,
+ PHASE_PLANT_SECOND_FINISH = 22,
+ PHASE_PLANT_SECOND_WAIT = 23,
+ PHASE_PLANT_SECOND_TIMER_1 = 24,
+ PHASE_PLANT_SECOND_TIMER_2 = 25,
+ PHASE_PLANT_SECOND_TIMER_3 = 26,
+ PHASE_PLANT_SECOND_DETONATE = 27,
+ PHASE_FIGHT_SIRONAS_STOP = 28,
+ PHASE_FIGHT_SIRONAS_SPEECH_1 = 29,
+ PHASE_FIGHT_SIRONAS_SPEECH_2 = 30,
+ PHASE_FIGHT_SIRONAS_START = 31,
+ PHASE_SIRONAS_SLAIN_SPEECH_1 = 32,
+ PHASE_SIRONAS_SLAIN_EMOTE_1 = 33,
+ PHASE_SIRONAS_SLAIN_EMOTE_2 = 34,
+ PHASE_SIRONAS_SLAIN_SPEECH_2 = 35,
+
+ DATA_EVENT_STARTER_GUID = 0,
+
+ MAX_EXPLOSIVES = 5,
+
+ QUEST_ENDING_THEIR_WORLD = 9759
+};
+
+Position const ExplosivesPos[2][MAX_EXPLOSIVES] =
+{
+ {
+ { -1954.946f, -10654.714f, 110.448f },
+ { -1956.331f, -10654.494f, 110.869f },
+ { -1955.906f, -10656.221f, 110.791f },
+ { -1957.294f, -10656.000f, 111.219f },
+ { -1954.462f, -10656.451f, 110.404f }
+ },
+ {
+ { -1915.137f, -10583.651f, 178.365f },
+ { -1914.006f, -10582.964f, 178.471f },
+ { -1912.717f, -10582.398f, 178.658f },
+ { -1915.056f, -10582.251f, 178.162f },
+ { -1913.883f, -10581.778f, 178.346f }
+ }
+};
+
+/*######
+## npc_sironas
+######*/
+
+class npc_sironas : public CreatureScript
+{
+public:
+ npc_sironas() : CreatureScript("npc_sironas") { }
+
+ CreatureAI* GetAI(Creature* creature) const
+ {
+ return new npc_sironasAI(creature);
+ }
+
+ struct npc_sironasAI : public ScriptedAI
+ {
+ npc_sironasAI(Creature* creature) : ScriptedAI(creature) { }
+
+ void Reset() override
+ {
+ _events.Reset();
+ me->SetDisplayId(me->GetCreatureTemplate()->Modelid2);
+ }
+
+ void EnterCombat(Unit* /*who*/) override
+ {
+ _events.ScheduleEvent(EVENT_UPPERCUT, 15 * IN_MILLISECONDS);
+ _events.ScheduleEvent(EVENT_IMMOLATE, 10 * IN_MILLISECONDS);
+ _events.ScheduleEvent(EVENT_CURSE_OF_BLOOD, 5 * IN_MILLISECONDS);
+ }
+
+ void JustDied(Unit* killer) override
+ {
+ me->SetObjectScale(1.0f);
+ _events.Reset();
+ if (Creature* legoso = me->FindNearestCreature(NPC_LEGOSO, SIZE_OF_GRIDS))
+ {
+ Group* group = me->GetLootRecipientGroup();
+
+ if (killer->GetGUID() == legoso->GetGUID() ||
+ (group && group->IsMember(killer->GetGUID())) ||
+ killer->GetGUIDLow() == legoso->AI()->GetData(DATA_EVENT_STARTER_GUID))
+ legoso->AI()->DoAction(ACTION_LEGOSO_SIRONAS_KILLED);
+ }
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
+
+ _events.Update(diff);
+
+ while (uint32 eventId = _events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_UPPERCUT:
+ DoCastVictim(SPELL_UPPERCUT);
+ _events.ScheduleEvent(EVENT_UPPERCUT, urand(10, 12) * IN_MILLISECONDS);
+ break;
+ case EVENT_IMMOLATE:
+ DoCastVictim(SPELL_IMMOLATE);
+ _events.ScheduleEvent(EVENT_IMMOLATE, urand(15, 20) * IN_MILLISECONDS);
+ break;
+ case EVENT_CURSE_OF_BLOOD:
+ DoCastVictim(SPELL_CURSE_OF_BLOOD);
+ _events.ScheduleEvent(EVENT_CURSE_OF_BLOOD, urand(20, 25) * IN_MILLISECONDS);
+ break;
+ default:
+ break;
+ }
+ }
+
+ DoMeleeAttackIfReady();
+ }
+
+ void DoAction(int32 param) override
+ {
+ switch (param)
+ {
+ case ACTION_SIRONAS_CHANNEL_START:
+ {
+ DoCast(me, SPELL_SIRONAS_CHANNELING);
+ std::list<Creature*> BeamList;
+ _beamGuidList.clear();
+ me->GetCreatureListWithEntryInGrid(BeamList, NPC_BLOODMYST_TESLA_COIL, SIZE_OF_GRIDS);
+ for (std::list<Creature*>::iterator itr = BeamList.begin(); itr != BeamList.end(); ++itr)
+ {
+ _beamGuidList.push_back((*itr)->GetGUID());
+ (*itr)->CastSpell(*itr, SPELL_BLOODMYST_TESLA);
+ }
+ break;
+ }
+ case ACTION_SIRONAS_CHANNEL_STOP:
+ {
+ me->InterruptNonMeleeSpells(true, SPELL_SIRONAS_CHANNELING);
+ std::list<Creature*> creatureList;
+ GetCreatureListWithEntryInGrid(creatureList, me, NPC_BLOODMYST_TESLA_COIL, 500.0f);
+ if (!creatureList.empty())
+ for (std::list<Creature*>::iterator itr = creatureList.begin(); itr != creatureList.end(); ++itr)
+ (*itr)->InterruptNonMeleeSpells(true, SPELL_BLOODMYST_TESLA);
+ }
+ default:
+ break;
+ }
+ }
+
+ private:
+ GuidList _beamGuidList;
+ EventMap _events;
+ };
+};
+
+/*######
+## npc_demolitionist_legoso
+######*/
+
+class npc_demolitionist_legoso : public CreatureScript
+{
+public:
+ npc_demolitionist_legoso() : CreatureScript("npc_demolitionist_legoso") { }
+
+ CreatureAI* GetAI(Creature* creature) const
+ {
+ return new npc_demolitionist_legosoAI(creature);
+ }
+
+ struct npc_demolitionist_legosoAI : public npc_escortAI
+ {
+ npc_demolitionist_legosoAI(Creature* creature) : npc_escortAI(creature) { }
+
+ void sQuestAccept(Player* player, Quest const* quest) override
+ {
+ if (quest->GetQuestId() == QUEST_ENDING_THEIR_WORLD)
+ {
+ SetData(DATA_EVENT_STARTER_GUID, player->GetGUIDLow());
+ Start(true, true, player->GetGUID(), quest);
+ }
+ }
+
+ uint32 GetData(uint32 id) const override
+ {
+ switch (id)
+ {
+ case DATA_EVENT_STARTER_GUID:
+ return _eventStarterGuidLow;
+ default:
+ return 0;
+ }
+ }
+
+ void SetData(uint32 data, uint32 value) override
+ {
+ switch (data)
+ {
+ case DATA_EVENT_STARTER_GUID:
+ _eventStarterGuidLow = value;
+ break;
+ default:
+ break;
+ }
+ }
+
+ void Reset() override
+ {
+ _phase = PHASE_NONE;
+ _moveTimer = 0;
+ _eventStarterGuidLow = 0;
+ me->SetCanDualWield(true);
+
+ _events.Reset();
+ _events.ScheduleEvent(EVENT_FROST_SHOCK, 1 * IN_MILLISECONDS);
+ _events.ScheduleEvent(EVENT_HEALING_SURGE, 5 * IN_MILLISECONDS);
+ _events.ScheduleEvent(EVENT_SEARING_TOTEM, 15 * IN_MILLISECONDS);
+ _events.ScheduleEvent(EVENT_STRENGTH_OF_EARTH_TOTEM, 20 * IN_MILLISECONDS);
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ _events.Update(diff);
+
+ if (UpdateVictim())
+ {
+ while (uint32 eventId = _events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_FROST_SHOCK:
+ DoCastVictim(SPELL_FROST_SHOCK);
+ _events.DelayEvents(1 * IN_MILLISECONDS);
+ _events.ScheduleEvent(EVENT_FROST_SHOCK, urand(10, 15) * IN_MILLISECONDS);
+ break;
+ case EVENT_SEARING_TOTEM:
+ DoCast(me, SPELL_SEARING_TOTEM);
+ _events.DelayEvents(1 * IN_MILLISECONDS);
+ _events.ScheduleEvent(EVENT_SEARING_TOTEM, urand(110, 130) * IN_MILLISECONDS);
+ break;
+ case EVENT_STRENGTH_OF_EARTH_TOTEM:
+ DoCast(me, SPELL_STRENGTH_OF_EARTH_TOTEM);
+ _events.DelayEvents(1 * IN_MILLISECONDS);
+ _events.ScheduleEvent(EVENT_STRENGTH_OF_EARTH_TOTEM, urand(110, 130) * IN_MILLISECONDS);
+ break;
+ case EVENT_HEALING_SURGE:
+ {
+ Unit* target = NULL;
+ if (me->GetHealthPct() < 85)
+ target = me;
+ else if (Player* player = GetPlayerForEscort())
+ if (player->GetHealthPct() < 85)
+ target = player;
+ if (target)
+ {
+ DoCast(target, SPELL_HEALING_SURGE);
+ _events.ScheduleEvent(EVENT_HEALING_SURGE, 10 * IN_MILLISECONDS);
+ }
+ else
+ _events.ScheduleEvent(EVENT_HEALING_SURGE, 2 * IN_MILLISECONDS);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ DoMeleeAttackIfReady();
+ }
+
+ if (HasEscortState(STATE_ESCORT_NONE))
+ return;
+
+ npc_escortAI::UpdateAI(diff);
+
+ if (_phase)
+ {
+ if (_moveTimer <= diff)
+ {
+ switch (_phase)
+ {
+ case PHASE_WP_26: //debug skip path to point 26, buggy path calculation
+ me->GetMotionMaster()->MovePoint(WP_DEBUG_2, -2021.77f, -10648.8f, 129.903f, false);
+ _moveTimer = 2 * IN_MILLISECONDS;
+ _phase = PHASE_CONTINUE;
+ break;
+ case PHASE_CONTINUE: // continue escort
+ SetEscortPaused(false);
+ _moveTimer = 0 * IN_MILLISECONDS;
+ _phase = PHASE_NONE;
+ break;
+ case PHASE_WP_22: //debug skip path to point 22, buggy path calculation
+ me->GetMotionMaster()->MovePoint(WP_EXPLOSIVES_FIRST_PLANT, -1958.026f, -10660.465f, 111.547f, false);
+ Talk(SAY_LEGOSO_3);
+ _moveTimer = 2 * IN_MILLISECONDS;
+ _phase = PHASE_PLANT_FIRST_KNEEL;
+ break;
+ case PHASE_PLANT_FIRST_KNEEL: // plant first explosives stage 1 kneel
+ me->SetStandState(UNIT_STAND_STATE_KNEEL);
+ _moveTimer = 10 * IN_MILLISECONDS;
+ _phase = PHASE_PLANT_FIRST_STAND;
+ break;
+ case PHASE_PLANT_FIRST_STAND: // plant first explosives stage 1 stand
+ me->SetStandState(UNIT_STAND_STATE_STAND);
+ _moveTimer = 0.5* IN_MILLISECONDS;
+ _phase = PHASE_PLANT_FIRST_WORK;
+ break;
+ case PHASE_PLANT_FIRST_WORK: // plant first explosives stage 2 work
+ Talk(SAY_LEGOSO_4);
+ _moveTimer = 17.5 * IN_MILLISECONDS;
+ _phase = PHASE_PLANT_FIRST_FINISH;
+ break;
+ case PHASE_PLANT_FIRST_FINISH: // plant first explosives finish
+ _explosivesGuids.clear();
+ for (uint8 i = 0; i != MAX_EXPLOSIVES; ++i)
+ {
+ if (GameObject* explosive = me->SummonGameObject(GO_DRAENEI_EXPLOSIVES_1, ExplosivesPos[0][i].m_positionX, ExplosivesPos[0][i].m_positionY, ExplosivesPos[0][i].m_positionZ, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0))
+ _explosivesGuids.push_back(explosive->GetGUID());
+ }
+ me->HandleEmoteCommand(EMOTE_ONESHOT_NONE); // reset anim state
+ // force runoff movement so he will not screw up next waypoint
+ me->GetMotionMaster()->MovePoint(WP_EXPLOSIVES_FIRST_RUNOFF, -1955.6f, -10669.8f, 110.65f, false);
+ Talk(SAY_LEGOSO_5);
+ _moveTimer = 1.5 * IN_MILLISECONDS;
+ _phase = PHASE_CONTINUE;
+ break;
+ case PHASE_PLANT_FIRST_TIMER_1: // first explosives detonate timer 1
+ Talk(SAY_LEGOSO_6);
+ _moveTimer = 1 * IN_MILLISECONDS;
+ _phase = PHASE_PLANT_FIRST_TIMER_2;
+ break;
+ case PHASE_PLANT_FIRST_TIMER_2: // first explosives detonate timer 2
+ Talk(SAY_LEGOSO_7);
+ _moveTimer = 1 * IN_MILLISECONDS;
+ _phase = PHASE_PLANT_FIRST_TIMER_3;
+ break;
+ case PHASE_PLANT_FIRST_TIMER_3: // first explosives detonate timer 3
+ Talk(SAY_LEGOSO_8);
+ _moveTimer = 1 * IN_MILLISECONDS;
+ _phase = PHASE_PLANT_FIRST_DETONATE;
+ break;
+ case PHASE_PLANT_FIRST_DETONATE: // first explosives detonate finish
+ for (GuidList::iterator itr = _explosivesGuids.begin(); itr != _explosivesGuids.end(); ++itr)
+ {
+ if (GameObject* explosive = sObjectAccessor->GetGameObject(*me, *itr))
+ me->RemoveGameObject(explosive, true);
+ }
+ _explosivesGuids.clear();
+ me->HandleEmoteCommand(EMOTE_ONESHOT_CHEER);
+ _moveTimer = 2 * IN_MILLISECONDS;
+ _phase = PHASE_PLANT_FIRST_SPEECH;
+ break;
+ case PHASE_PLANT_FIRST_SPEECH: // after detonation 1 speech
+ Talk(SAY_LEGOSO_9);
+ _moveTimer = 4 * IN_MILLISECONDS;
+ _phase = PHASE_PLANT_FIRST_ROTATE;
+ break;
+ case PHASE_PLANT_FIRST_ROTATE: // after detonation 1 rotate to next point
+ me->SetFacingTo(2.272f);
+ _moveTimer = 1 * IN_MILLISECONDS;
+ _phase = PHASE_PLANT_FIRST_POINT;
+ break;
+ case PHASE_PLANT_FIRST_POINT: // after detonation 1 send point anim and go on to next point
+ me->HandleEmoteCommand(EMOTE_ONESHOT_POINT);
+ _moveTimer = 2 * IN_MILLISECONDS;
+ _phase = PHASE_CONTINUE;
+ break;
+ case PHASE_FEEL_SIRONAS_1: // legoso exclamation before sironas 1.1
+ Talk(SAY_LEGOSO_10);
+ _moveTimer = 4 * IN_MILLISECONDS;
+ _phase = PHASE_FEEL_SIRONAS_2;
+ break;
+ case PHASE_FEEL_SIRONAS_2: // legoso exclamation before sironas 1.2
+ Talk(SAY_LEGOSO_11);
+ _moveTimer = 4 * IN_MILLISECONDS;
+ _phase = PHASE_CONTINUE;
+ break;
+ case PHASE_MEET_SIRONAS_ROAR: // legoso exclamation before sironas 2.1
+ Talk(SAY_LEGOSO_12);
+ _moveTimer = 4 * IN_MILLISECONDS;
+ _phase = PHASE_MEET_SIRONAS_TURN;
+ break;
+ case PHASE_MEET_SIRONAS_TURN: // legoso exclamation before sironas 2.2
+ if (Player* player = GetPlayerForEscort())
+ me->SetFacingToObject(player);
+ _moveTimer = 1 * IN_MILLISECONDS;
+ _phase = PHASE_MEET_SIRONAS_SPEECH;
+ break;
+ case PHASE_MEET_SIRONAS_SPEECH: // legoso exclamation before sironas 2.3
+ Talk(SAY_LEGOSO_13);
+ _moveTimer = 7 * IN_MILLISECONDS;
+ _phase = PHASE_CONTINUE;
+ break;
+ case PHASE_PLANT_SECOND_KNEEL: // plant second explosives stage 1 kneel
+ me->SetStandState(UNIT_STAND_STATE_KNEEL);
+ _moveTimer = 11 * IN_MILLISECONDS;
+ _phase = PHASE_PLANT_SECOND_SPEECH;
+ break;
+ case PHASE_PLANT_SECOND_SPEECH: // plant second explosives stage 2 kneel
+ Talk(SAY_LEGOSO_14);
+ _moveTimer = 13 * IN_MILLISECONDS;
+ _phase = PHASE_PLANT_SECOND_STAND;
+ break;
+ case PHASE_PLANT_SECOND_STAND: // plant second explosives finish
+ me->SetStandState(UNIT_STAND_STATE_STAND);
+ _moveTimer = 1 * IN_MILLISECONDS;
+ _phase = PHASE_PLANT_SECOND_FINISH;
+ break;
+ case PHASE_PLANT_SECOND_FINISH: // plant second explosives finish - create explosives
+ _explosivesGuids.clear();
+ for (uint8 i = 0; i != MAX_EXPLOSIVES; ++i)
+ {
+ if (GameObject* explosive = me->SummonGameObject(GO_DRAENEI_EXPLOSIVES_2, ExplosivesPos[1][i].m_positionX, ExplosivesPos[1][i].m_positionY, ExplosivesPos[1][i].m_positionZ, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0))
+ _explosivesGuids.push_back(explosive->GetGUID());
+ }
+ Talk(SAY_LEGOSO_15);
+ _moveTimer = 1 * IN_MILLISECONDS;
+ _phase = PHASE_PLANT_SECOND_WAIT;
+ break;
+ case PHASE_PLANT_SECOND_WAIT: // plant second explosives finish - proceed to next point
+ _moveTimer = 1 * IN_MILLISECONDS;
+ _phase = PHASE_CONTINUE;
+ break;
+ case PHASE_PLANT_SECOND_TIMER_1: // second explosives detonate timer 1
+ Talk(SAY_LEGOSO_16);
+ _moveTimer = 1 * IN_MILLISECONDS;
+ _phase = PHASE_PLANT_SECOND_TIMER_2;
+ break;
+ case PHASE_PLANT_SECOND_TIMER_2: // second explosives detonate timer 2
+ Talk(SAY_LEGOSO_17);
+ _moveTimer = 1 * IN_MILLISECONDS;
+ _phase = PHASE_PLANT_SECOND_TIMER_3;
+ break;
+ case PHASE_PLANT_SECOND_TIMER_3: // second explosives detonate timer 3
+ Talk(SAY_LEGOSO_18);
+ _moveTimer = 1 * IN_MILLISECONDS;
+ _phase = PHASE_PLANT_SECOND_DETONATE;
+ break;
+ case PHASE_PLANT_SECOND_DETONATE: // second explosives detonate finish
+ for (GuidList::iterator itr = _explosivesGuids.begin(); itr != _explosivesGuids.end(); ++itr)
+ {
+ if (GameObject* explosive = sObjectAccessor->GetGameObject(*me, *itr))
+ me->RemoveGameObject(explosive, true);
+ }
+ _explosivesGuids.clear();
+ if (Creature* sironas = me->FindNearestCreature(NPC_SIRONAS, SIZE_OF_GRIDS))
+ {
+ sironas->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC);
+ me->SetFacingToObject(sironas);
+ }
+ _moveTimer = 1 * IN_MILLISECONDS;
+ _phase = PHASE_FIGHT_SIRONAS_STOP;
+ break;
+ case PHASE_FIGHT_SIRONAS_STOP: // sironas channel stop
+ if (Creature* sironas = me->FindNearestCreature(NPC_SIRONAS, SIZE_OF_GRIDS))
+ sironas->AI()->DoAction(ACTION_SIRONAS_CHANNEL_STOP);
+ _moveTimer = 1 * IN_MILLISECONDS;
+ _phase = PHASE_FIGHT_SIRONAS_SPEECH_1;
+ break;
+ case PHASE_FIGHT_SIRONAS_SPEECH_1: // sironas exclamation before aggro
+ if (Creature* sironas = me->FindNearestCreature(NPC_SIRONAS, SIZE_OF_GRIDS))
+ sironas->AI()->Talk(SAY_SIRONAS_1);
+ _moveTimer = 1 * IN_MILLISECONDS;
+ _phase = PHASE_FIGHT_SIRONAS_SPEECH_2;
+ break;
+ case PHASE_FIGHT_SIRONAS_SPEECH_2: // legoso exclamation before aggro
+ if (Creature* sironas = me->FindNearestCreature(NPC_SIRONAS, SIZE_OF_GRIDS))
+ sironas->SetObjectScale(3.0f);
+ Talk(SAY_LEGOSO_19);
+ _moveTimer = 1 * IN_MILLISECONDS;
+ _phase = PHASE_FIGHT_SIRONAS_START;
+ break;
+ case PHASE_FIGHT_SIRONAS_START: // legoso exclamation at aggro
+ if (Creature* sironas = me->FindNearestCreature(NPC_SIRONAS, SIZE_OF_GRIDS))
+ {
+ Unit* target = GetPlayerForEscort();
+ if (!target)
+ target = me;
+
+ target->AddThreat(sironas, 0.001f);
+ sironas->Attack(target, true);
+ sironas->GetMotionMaster()->MoveChase(target);
+ }
+ _moveTimer = 10 * IN_MILLISECONDS;
+ _phase = PHASE_CONTINUE;
+ break;
+ case PHASE_SIRONAS_SLAIN_SPEECH_1: // legoso exclamation after battle - stage 1.1
+ Talk(SAY_LEGOSO_20);
+ _moveTimer = 2 * IN_MILLISECONDS;
+ _phase = PHASE_SIRONAS_SLAIN_EMOTE_1;
+ break;
+ case PHASE_SIRONAS_SLAIN_EMOTE_1: // legoso exclamation after battle - stage 1.2
+ me->HandleEmoteCommand(EMOTE_ONESHOT_EXCLAMATION);
+ _moveTimer = 2 * IN_MILLISECONDS;
+ _phase = PHASE_SIRONAS_SLAIN_EMOTE_2;
+ break;
+ case PHASE_SIRONAS_SLAIN_EMOTE_2: // legoso exclamation after battle - stage 1.3
+ if (Player* player = GetPlayerForEscort())
+ player->GroupEventHappens(QUEST_ENDING_THEIR_WORLD, me);
+ me->HandleEmoteCommand(EMOTE_ONESHOT_CHEER);
+ _moveTimer = 5 * IN_MILLISECONDS;
+ _phase = PHASE_SIRONAS_SLAIN_SPEECH_2;
+ break;
+ case PHASE_SIRONAS_SLAIN_SPEECH_2: // legoso exclamation after battle - stage 2
+ Talk(SAY_LEGOSO_21);
+ _moveTimer = 30 * IN_MILLISECONDS;
+ _phase = PHASE_CONTINUE;
+ break;
+ default:
+ break;
+ }
+ }
+ else if (!me->IsInCombat())
+ _moveTimer -= diff;
+ }
+ }
+
+ void WaypointReached(uint32 waypointId) override
+ {
+ Player* player = GetPlayerForEscort();
+ if (!player)
+ return;
+
+ switch (waypointId)
+ {
+ case WP_START:
+ SetEscortPaused(true);
+ me->SetFacingToObject(player);
+ Talk(SAY_LEGOSO_1);
+ _moveTimer = 2.5 * IN_MILLISECONDS;
+ _phase = PHASE_CONTINUE;
+ break;
+ case WP_EXPLOSIVES_FIRST_POINT:
+ SetEscortPaused(true);
+ Talk(SAY_LEGOSO_2);
+ _moveTimer = 8 * IN_MILLISECONDS;
+ _phase = PHASE_WP_22;
+ break;
+ case WP_EXPLOSIVES_FIRST_PLANT:
+ me->SetFacingTo(1.46f);
+ break;
+ case WP_EXPLOSIVES_FIRST_DETONATE:
+ SetEscortPaused(true);
+ me->SetFacingTo(1.05f);
+ _moveTimer = 1 * IN_MILLISECONDS;
+ _phase = PHASE_PLANT_FIRST_TIMER_1;
+ break;
+ case WP_DEBUG_1:
+ SetEscortPaused(true);
+ _moveTimer = 0.5 * IN_MILLISECONDS;
+ _phase = PHASE_WP_26;
+ break;
+ case WP_SIRONAS_HILL:
+ {
+ SetEscortPaused(true);
+
+ //Find Sironas and make it respawn if needed
+ Creature* sironas = NULL;
+ Trinity::AllCreaturesOfEntryInRange check(me, NPC_SIRONAS, SIZE_OF_GRIDS);
+ Trinity::CreatureSearcher<Trinity::AllCreaturesOfEntryInRange> searcher(me, sironas, check);
+ me->VisitNearbyObject(SIZE_OF_GRIDS, searcher);
+
+ if (sironas)
+ {
+ if (!sironas->IsAlive())
+ sironas->Respawn(true);
+
+ sironas->AI()->DoAction(ACTION_SIRONAS_CHANNEL_START);
+ me->SetFacingToObject(sironas);
+ }
+ _moveTimer = 1 * IN_MILLISECONDS;
+ _phase = PHASE_FEEL_SIRONAS_1;
+ break;
+ }
+ case WP_EXPLOSIVES_SECOND_BATTLEROAR:
+ SetEscortPaused(true);
+ _moveTimer = 0.2 * IN_MILLISECONDS;
+ _phase = PHASE_MEET_SIRONAS_ROAR;
+ break;
+ case WP_EXPLOSIVES_SECOND_PLANT:
+ SetEscortPaused(true);
+ _moveTimer = 0.5 * IN_MILLISECONDS;
+ _phase = PHASE_PLANT_SECOND_KNEEL;
+ break;
+ case WP_EXPLOSIVES_SECOND_DETONATE:
+ SetEscortPaused(true);
+ me->SetFacingTo(5.7f);
+ _moveTimer = 2 * IN_MILLISECONDS;
+ _phase = PHASE_PLANT_SECOND_TIMER_1;
+ break;
+ default:
+ break;
+ }
+ }
+
+ void DoAction(int32 param) override
+ {
+ switch (param)
+ {
+ case ACTION_LEGOSO_SIRONAS_KILLED:
+ _phase = PHASE_SIRONAS_SLAIN_SPEECH_1;
+ _moveTimer = 5 * IN_MILLISECONDS;
+ break;
+ default:
+ break;
+ }
+ }
+
+ private:
+ int8 _phase;
+ uint32 _moveTimer;
+ uint32 _eventStarterGuidLow;
+ GuidList _explosivesGuids;
+ EventMap _events;
+ };
+};
+
void AddSC_bloodmyst_isle()
{
new npc_webbed_creature();
+ new npc_sironas();
+ new npc_demolitionist_legoso();
}
diff --git a/src/server/scripts/Kalimdor/zone_felwood.cpp b/src/server/scripts/Kalimdor/zone_felwood.cpp
index cdf04b1d4cc..91b9ce08010 100644
--- a/src/server/scripts/Kalimdor/zone_felwood.cpp
+++ b/src/server/scripts/Kalimdor/zone_felwood.cpp
@@ -100,7 +100,44 @@ public:
}
};
+/*######
+## at_ancient_leaf
+######*/
+
+enum AncientMisc
+{
+ QUEST_ANCIENT_LEAF = 7632,
+ NPC_VARTRUS = 14524,
+ NPC_STOMA = 14525,
+ NPC_HASTAT = 14526,
+ CREATURE_GROUP_ANCIENTS = 1
+};
+
+class at_ancient_leaf : public AreaTriggerScript
+{
+ public:
+ at_ancient_leaf() : AreaTriggerScript("at_ancient_leaf") { }
+
+ bool OnTrigger(Player* player, AreaTriggerEntry const* /*trigger*/) override
+ {
+ if (player->IsGameMaster() || !player->IsAlive())
+ return false;
+
+ // Handle Call Ancients event start - The area trigger summons 3 ancients
+ if ((player->GetQuestStatus(QUEST_ANCIENT_LEAF) == QUEST_STATUS_COMPLETE) || (player->GetQuestStatus(QUEST_ANCIENT_LEAF) == QUEST_STATUS_REWARDED))
+ {
+ // If ancients are already spawned, skip the rest
+ if (GetClosestCreatureWithEntry(player, NPC_VARTRUS, 50.0f) || GetClosestCreatureWithEntry(player, NPC_STOMA, 50.0f) || GetClosestCreatureWithEntry(player, NPC_HASTAT, 50.0f))
+ return true;
+
+ player->GetMap()->SummonCreatureGroup(CREATURE_GROUP_ANCIENTS);
+ }
+ return false;
+ }
+};
+
void AddSC_felwood()
{
new npcs_riverbreeze_and_silversky();
+ new at_ancient_leaf();
}
diff --git a/src/server/scripts/Kalimdor/zone_mulgore.cpp b/src/server/scripts/Kalimdor/zone_mulgore.cpp
deleted file mode 100644
index 0d0ef218885..00000000000
--- a/src/server/scripts/Kalimdor/zone_mulgore.cpp
+++ /dev/null
@@ -1,306 +0,0 @@
-/*
- * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
- * Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-/* ScriptData
-SDName: Mulgore
-SD%Complete: 100
-SDComment: Support for quest: 11129, 772
-SDCategory: Mulgore
-EndScriptData */
-
-/* ContentData
-npc_kyle_frenzied
-npc_plains_vision
-EndContentData */
-
-#include "ScriptMgr.h"
-#include "ScriptedCreature.h"
-#include "ScriptedGossip.h"
-#include "Player.h"
-#include "SpellInfo.h"
-
-/*#####
-# npc_kyle_frenzied
-######*/
-
-enum KyleFrenzied
-{
- EMOTE_SEE_LUNCH = 0,
- EMOTE_EAT_LUNCH = 1,
- EMOTE_DANCE = 2,
-
- SPELL_LUNCH = 42222,
- NPC_KYLE_FRENZIED = 23616,
- NPC_KYLE_FRIENDLY = 23622,
- POINT_ID = 1
-};
-
-class npc_kyle_frenzied : public CreatureScript
-{
-public:
- npc_kyle_frenzied() : CreatureScript("npc_kyle_frenzied") { }
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return new npc_kyle_frenziedAI(creature);
- }
-
- struct npc_kyle_frenziedAI : public ScriptedAI
- {
- npc_kyle_frenziedAI(Creature* creature) : ScriptedAI(creature)
- {
- Initialize();
- }
-
- void Initialize()
- {
- EventActive = false;
- IsMovingToLunch = false;
- PlayerGUID.Clear();
- EventTimer = 5000;
- EventPhase = 0;
- }
-
- bool EventActive;
- bool IsMovingToLunch;
- ObjectGuid PlayerGUID;
- uint32 EventTimer;
- uint8 EventPhase;
-
- void Reset() override
- {
- Initialize();
-
- if (me->GetEntry() == NPC_KYLE_FRIENDLY)
- me->UpdateEntry(NPC_KYLE_FRENZIED);
- }
-
- void SpellHit(Unit* Caster, SpellInfo const* Spell) override
- {
- if (!me->GetVictim() && !EventActive && Spell->Id == SPELL_LUNCH)
- {
- if (Caster->GetTypeId() == TYPEID_PLAYER)
- PlayerGUID = Caster->GetGUID();
-
- if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == WAYPOINT_MOTION_TYPE)
- {
- me->GetMotionMaster()->MovementExpired();
- me->GetMotionMaster()->MoveIdle();
- me->StopMoving();
- }
-
- EventActive = true;
- Talk(EMOTE_SEE_LUNCH);
- me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_CREATURE_SPECIAL);
- }
- }
-
- void MovementInform(uint32 Type, uint32 PointId) override
- {
- if (Type != POINT_MOTION_TYPE || !EventActive)
- return;
-
- if (PointId == POINT_ID)
- IsMovingToLunch = false;
- }
-
- void UpdateAI(uint32 diff) override
- {
- if (EventActive)
- {
- if (IsMovingToLunch)
- return;
-
- if (EventTimer <= diff)
- {
- EventTimer = 5000;
- ++EventPhase;
-
- switch (EventPhase)
- {
- case 1:
- if (Unit* unit = ObjectAccessor::GetUnit(*me, PlayerGUID))
- {
- if (GameObject* go = unit->GetGameObject(SPELL_LUNCH))
- {
- IsMovingToLunch = true;
- me->GetMotionMaster()->MovePoint(POINT_ID, go->GetPositionX(), go->GetPositionY(), go->GetPositionZ());
- }
- }
- break;
- case 2:
- Talk(EMOTE_EAT_LUNCH);
- me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_USE_STANDING);
- break;
- case 3:
- if (Player* unit = ObjectAccessor::GetPlayer(*me, PlayerGUID))
- unit->TalkedToCreature(me->GetEntry(), me->GetGUID());
-
- me->UpdateEntry(NPC_KYLE_FRIENDLY);
- break;
- case 4:
- EventTimer = 30000;
- Talk(EMOTE_DANCE);
- me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_DANCESPECIAL);
- break;
- case 5:
- me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_NONE);
- Reset();
- me->GetMotionMaster()->Clear();
- break;
- }
- }
- else
- EventTimer -= diff;
- }
- }
- };
-
-};
-
-/*#####
-# npc_plains_vision
-######*/
-
-Position const wpPlainVision[50] =
-{
- {-2226.32f, -408.095f, -9.36235f, 0.0f},
- {-2203.04f, -437.212f, -5.72498f, 0.0f},
- {-2163.91f, -457.851f, -7.09049f, 0.0f},
- {-2123.87f, -448.137f, -9.29591f, 0.0f},
- {-2104.66f, -427.166f, -6.49513f, 0.0f},
- {-2101.48f, -422.826f, -5.3567f, 0.0f},
- {-2097.56f, -417.083f, -7.16716f, 0.0f},
- {-2084.87f, -398.626f, -9.88973f, 0.0f},
- {-2072.71f, -382.324f, -10.2488f, 0.0f},
- {-2054.05f, -356.728f, -6.22468f, 0.0f},
- {-2051.8f, -353.645f, -5.35791f, 0.0f},
- {-2049.08f, -349.912f, -6.15723f, 0.0f},
- {-2030.6f, -310.724f, -9.59302f, 0.0f},
- {-2002.15f, -249.308f, -10.8124f, 0.0f},
- {-1972.85f, -195.811f, -10.6316f, 0.0f},
- {-1940.93f, -147.652f, -11.7055f, 0.0f},
- {-1888.06f, -81.943f, -11.4404f, 0.0f},
- {-1837.05f, -34.0109f, -12.258f, 0.0f},
- {-1796.12f, -14.6462f, -10.3581f, 0.0f},
- {-1732.61f, -4.27746f, -10.0213f, 0.0f},
- {-1688.94f, -0.829945f, -11.7103f, 0.0f},
- {-1681.32f, 13.0313f, -9.48056f, 0.0f},
- {-1677.04f, 36.8349f, -7.10318f, 0.0f},
- {-1675.2f, 68.559f, -8.95384f, 0.0f},
- {-1676.57f, 89.023f, -9.65104f, 0.0f},
- {-1678.16f, 110.939f, -10.1782f, 0.0f},
- {-1677.86f, 128.681f, -5.73869f, 0.0f},
- {-1675.27f, 144.324f, -3.47916f, 0.0f},
- {-1671.7f, 163.169f, -1.23098f, 0.0f},
- {-1666.61f, 181.584f, 5.26145f, 0.0f},
- {-1661.51f, 196.154f, 8.95252f, 0.0f},
- {-1655.47f, 210.811f, 8.38727f, 0.0f},
- {-1647.07f, 226.947f, 5.27755f, 0.0f},
- {-1621.65f, 232.91f, 2.69579f, 0.0f},
- {-1600.23f, 237.641f, 2.98539f, 0.0f},
- {-1576.07f, 242.546f, 4.66541f, 0.0f},
- {-1554.57f, 248.494f, 6.60377f, 0.0f},
- {-1547.53f, 259.302f, 10.6741f, 0.0f},
- {-1541.7f, 269.847f, 16.4418f, 0.0f},
- {-1539.83f, 278.989f, 21.0597f, 0.0f},
- {-1540.16f, 290.219f, 27.8247f, 0.0f},
- {-1538.99f, 298.983f, 34.0032f, 0.0f},
- {-1540.38f, 307.337f, 41.3557f, 0.0f},
- {-1536.61f, 314.884f, 48.0179f, 0.0f},
- {-1532.42f, 323.277f, 55.6667f, 0.0f},
- {-1528.77f, 329.774f, 61.1525f, 0.0f},
- {-1525.65f, 333.18f, 63.2161f, 0.0f},
- {-1517.01f, 350.713f, 62.4286f, 0.0f},
- {-1511.39f, 362.537f, 62.4539f, 0.0f},
- {-1508.68f, 366.822f, 62.733f, 0.0f}
-};
-
-class npc_plains_vision : public CreatureScript
-{
-public:
- npc_plains_vision() : CreatureScript("npc_plains_vision") { }
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return new npc_plains_visionAI(creature);
- }
-
- struct npc_plains_visionAI : public ScriptedAI
- {
- npc_plains_visionAI(Creature* creature) : ScriptedAI(creature)
- {
- Initialize();
- }
-
- void Initialize()
- {
- WayPointId = 0;
- newWaypoint = true;
- amountWP = 49;
- }
-
- bool newWaypoint;
- uint8 WayPointId;
- uint8 amountWP;
-
- void Reset() override
- {
- Initialize();
- }
-
- void EnterCombat(Unit* /*who*/) override { }
-
- void MovementInform(uint32 type, uint32 id) override
- {
- if (type != POINT_MOTION_TYPE)
- return;
-
- if (id < amountWP)
- {
- ++WayPointId;
- newWaypoint = true;
- }
- else
- {
- me->setDeathState(JUST_DIED);
- me->RemoveCorpse();
- }
- }
-
- void UpdateAI(uint32 /*diff*/) override
- {
- if (newWaypoint)
- {
- me->GetMotionMaster()->MovePoint(WayPointId, wpPlainVision[WayPointId]);
- newWaypoint = false;
- }
- }
- };
-
-};
-
-/*#####
-#
-######*/
-
-void AddSC_mulgore()
-{
- new npc_kyle_frenzied();
- new npc_plains_vision();
-}
diff --git a/src/server/scripts/Kalimdor/zone_the_barrens.cpp b/src/server/scripts/Kalimdor/zone_the_barrens.cpp
index c167bc700f7..eab104d8df2 100644
--- a/src/server/scripts/Kalimdor/zone_the_barrens.cpp
+++ b/src/server/scripts/Kalimdor/zone_the_barrens.cpp
@@ -659,6 +659,7 @@ public:
if (quest->GetQuestId() == QUEST_ESCAPE)
{
creature->setFaction(FACTION_RATCHET);
+ creature->AI()->Talk(SAY_START);
if (npc_escortAI* pEscortAI = CAST_AI(npc_wizzlecrank_shredder::npc_wizzlecrank_shredderAI, creature->AI()))
pEscortAI->Start(true, false, player->GetGUID());
}
diff --git a/src/server/scripts/Northrend/CMakeLists.txt b/src/server/scripts/Northrend/CMakeLists.txt
index e04dcf0ec96..66d9021223f 100644
--- a/src/server/scripts/Northrend/CMakeLists.txt
+++ b/src/server/scripts/Northrend/CMakeLists.txt
@@ -78,8 +78,7 @@ set(scripts_STAT_SRCS
Northrend/Nexus/Oculus/boss_urom.cpp
Northrend/Nexus/Oculus/oculus.cpp
Northrend/Nexus/Oculus/instance_oculus.cpp
- Northrend/Nexus/Nexus/boss_commander_kolurg.cpp
- Northrend/Nexus/Nexus/boss_commander_stoutbeard.cpp
+ Northrend/Nexus/Nexus/boss_nexus_commanders.cpp
Northrend/Nexus/Nexus/boss_ormorok.cpp
Northrend/Nexus/Nexus/boss_magus_telestra.cpp
Northrend/Nexus/Nexus/instance_nexus.cpp
diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/instance_trial_of_the_crusader.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/instance_trial_of_the_crusader.cpp
index 4f883fd7e90..23bfd773a9b 100644
--- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/instance_trial_of_the_crusader.cpp
+++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/instance_trial_of_the_crusader.cpp
@@ -255,12 +255,6 @@ class instance_trial_of_the_crusader : public InstanceMapScript
if (GetBossState(BOSS_VALKIRIES) == SPECIAL)
state = DONE;
break;
- case DONE:
- if (instance->GetPlayers().getFirst()->GetSource()->GetTeam() == ALLIANCE)
- EventStage = 4020;
- else
- EventStage = 4030;
- break;
default:
break;
}
@@ -336,7 +330,7 @@ class instance_trial_of_the_crusader : public InstanceMapScript
if (type < MAX_ENCOUNTERS)
{
- TC_LOG_INFO("scripts", "[ToCr] BossState(type %u) %u = state %u;", type, GetBossState(type), state);
+ TC_LOG_DEBUG("scripts", "[ToCr] BossState(type %u) %u = state %u;", type, GetBossState(type), state);
if (state == FAIL)
{
if (instance->IsHeroic())
diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.cpp
index 16526b694e9..974bd4672f1 100644
--- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.cpp
+++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.cpp
@@ -133,7 +133,7 @@ class npc_announcer_toc10 : public CreatureScript
char const* _message = "We are ready!";
- if (player->IsInCombat() || instance->IsEncounterInProgress() || instance->GetData(TYPE_EVENT))
+ if (player->IsInCombat() || instance->IsEncounterInProgress())
return true;
uint8 i = 0;
@@ -199,17 +199,11 @@ class npc_announcer_toc10 : public CreatureScript
}
else if (instance->GetBossState(BOSS_LICH_KING) != DONE)
{
- if (GameObject* floor = ObjectAccessor::GetGameObject(*player, instance->GetGuidData(GO_ARGENT_COLISEUM_FLOOR)))
- floor->SetDestructibleState(GO_DESTRUCTIBLE_DAMAGED);
-
- creature->CastSpell(creature, SPELL_CORPSE_TELEPORT, false);
- creature->CastSpell(creature, SPELL_DESTROY_FLOOR_KNOCKUP, false);
-
- if (!ObjectAccessor::GetCreature(*creature, instance->GetGuidData(NPC_ANUBARAK)))
- creature->SummonCreature(NPC_ANUBARAK, AnubarakLoc[0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME);
-
- if (creature->IsVisible())
- creature->SetVisible(false);
+ if (creature->GetMap()->GetPlayers().getFirst()->GetSource()->GetTeam() == ALLIANCE)
+ instance->SetData(TYPE_EVENT, 4020);
+ else
+ instance->SetData(TYPE_EVENT, 4030);
+ instance->SetBossState(BOSS_LICH_KING, NOT_STARTED);
}
creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
return true;
diff --git a/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_bronjahm.cpp b/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_bronjahm.cpp
index 97c4372f0e6..0b829c2c6dd 100644
--- a/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_bronjahm.cpp
+++ b/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_bronjahm.cpp
@@ -27,7 +27,7 @@ enum Yells
SAY_SLAY = 1,
SAY_DEATH = 2,
SAY_SOUL_STORM = 3,
- SAY_CORRUPT_SOUL = 4,
+ SAY_CORRUPT_SOUL = 4
};
enum Spells
@@ -39,9 +39,9 @@ enum Spells
SPELL_TELEPORT = 68988,
SPELL_FEAR = 68950,
SPELL_SOULSTORM = 68872,
- SPELL_SOULSTORM_CHANNEL = 69008, // pre-fight
- SPELL_SOULSTORM_VISUAL = 68870, // pre-cast soulstorm
- SPELL_PURPLE_BANISH_VISUAL = 68862 // Used by Soul Fragment (Aura)
+ SPELL_SOULSTORM_CHANNEL = 69008, // Pre-fight
+ SPELL_SOULSTORM_VISUAL = 68870, // Pre-cast Soulstorm
+ SPELL_PURPLE_BANISH_VISUAL = 68862 // Used by Soul Fragment (Aura)
};
enum Events
@@ -50,7 +50,7 @@ enum Events
EVENT_SHADOW_BOLT = 2,
EVENT_CORRUPT_SOUL = 3,
EVENT_SOULSTORM = 4,
- EVENT_FEAR = 5,
+ EVENT_FEAR = 5
};
enum CombatPhases
@@ -59,6 +59,11 @@ enum CombatPhases
PHASE_2 = 2
};
+enum Misc
+{
+ DATA_SOUL_POWER = 1
+};
+
class boss_bronjahm : public CreatureScript
{
public:
@@ -73,33 +78,30 @@ class boss_bronjahm : public CreatureScript
void Reset() override
{
- events.Reset();
+ _Reset();
events.SetPhase(PHASE_1);
events.ScheduleEvent(EVENT_SHADOW_BOLT, 2000);
events.ScheduleEvent(EVENT_MAGIC_BANE, urand(8000, 20000));
events.ScheduleEvent(EVENT_CORRUPT_SOUL, urand(25000, 35000), 0, PHASE_1);
-
- instance->SetBossState(DATA_BRONJAHM, NOT_STARTED);
}
- void JustReachedHome() override
- {
- DoCast(me, SPELL_SOULSTORM_CHANNEL, true);
- }
+ void JustReachedHome() override
+ {
+ _JustReachedHome();
+ DoCast(me, SPELL_SOULSTORM_CHANNEL, true);
+ }
void EnterCombat(Unit* /*who*/) override
{
+ _EnterCombat();
Talk(SAY_AGGRO);
me->RemoveAurasDueToSpell(SPELL_SOULSTORM_CHANNEL);
-
- instance->SetBossState(DATA_BRONJAHM, IN_PROGRESS);
}
void JustDied(Unit* /*killer*/) override
{
+ _JustDied();
Talk(SAY_DEATH);
-
- instance->SetBossState(DATA_BRONJAHM, DONE);
}
void KilledUnit(Unit* who) override
@@ -128,6 +130,23 @@ class boss_bronjahm : public CreatureScript
summon->CastSpell(summon, SPELL_PURPLE_BANISH_VISUAL, true);
}
+ uint32 GetData(uint32 type) const override
+ {
+ if (type == DATA_SOUL_POWER)
+ {
+ uint32 count = 0;
+ for (ObjectGuid const& guid : summons)
+ {
+ if (Creature* summon = ObjectAccessor::GetCreature(*me, guid))
+ if (summon->GetEntry() == NPC_CORRUPTED_SOUL_FRAGMENT && summon->IsAlive())
+ ++count;
+ }
+ return count;
+ }
+
+ return 0;
+ }
+
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
@@ -143,13 +162,21 @@ class boss_bronjahm : public CreatureScript
switch (eventId)
{
case EVENT_MAGIC_BANE:
- DoCastVictim(SPELL_MAGIC_S_BANE);
+ DoCastAOE(SPELL_MAGIC_S_BANE);
events.ScheduleEvent(EVENT_MAGIC_BANE, urand(8000, 20000));
break;
case EVENT_SHADOW_BOLT:
- if (!me->IsWithinMeleeRange(me->GetVictim()))
+ if (events.IsInPhase(PHASE_2))
+ {
DoCastVictim(SPELL_SHADOW_BOLT);
- events.ScheduleEvent(EVENT_SHADOW_BOLT, 2000);
+ events.ScheduleEvent(EVENT_SHADOW_BOLT, urand(1, 2) * IN_MILLISECONDS);
+ }
+ else
+ {
+ if (!me->IsWithinMeleeRange(me->GetVictim()))
+ DoCastVictim(SPELL_SHADOW_BOLT);
+ events.ScheduleEvent(EVENT_SHADOW_BOLT, 2 * IN_MILLISECONDS);
+ }
break;
case EVENT_CORRUPT_SOUL:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true))
@@ -165,8 +192,7 @@ class boss_bronjahm : public CreatureScript
me->CastSpell(me, SPELL_SOULSTORM, false);
break;
case EVENT_FEAR:
- if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true))
- me->CastCustomSpell(SPELL_FEAR, SPELLVALUE_MAX_TARGETS, 1, target, false);
+ me->CastCustomSpell(SPELL_FEAR, SPELLVALUE_MAX_TARGETS, 1, nullptr, false);
events.ScheduleEvent(EVENT_FEAR, urand(8000, 12000), 0, PHASE_2);
break;
default:
@@ -174,7 +200,8 @@ class boss_bronjahm : public CreatureScript
}
}
- DoMeleeAttackIfReady();
+ if (!events.IsInPhase(PHASE_2))
+ DoMeleeAttackIfReady();
}
};
@@ -201,17 +228,11 @@ class npc_corrupted_soul_fragment : public CreatureScript
if (type != CHASE_MOTION_TYPE)
return;
- if (TempSummon* summ = me->ToTempSummon())
- {
- ObjectGuid BronjahmGUID(instance->GetGuidData(DATA_BRONJAHM));
- if (BronjahmGUID.GetCounter() != id)
- return;
-
- if (Creature* bronjahm = ObjectAccessor::GetCreature(*me, BronjahmGUID))
- me->CastSpell(bronjahm, SPELL_CONSUME_SOUL, true);
+ if (instance->GetGuidData(DATA_BRONJAHM).GetCounter() != id)
+ return;
- summ->UnSummon();
- }
+ me->CastSpell((Unit*)nullptr, SPELL_CONSUME_SOUL, true);
+ me->DespawnOrUnsummon();
}
private:
@@ -220,7 +241,7 @@ class npc_corrupted_soul_fragment : public CreatureScript
CreatureAI* GetAI(Creature* creature) const override
{
- return GetInstanceAI<npc_corrupted_soul_fragmentAI>(creature);
+ return GetInstanceAI<npc_corrupted_soul_fragmentAI>(creature, FoSScriptName);
}
};
@@ -238,12 +259,10 @@ class spell_bronjahm_magic_bane : public SpellScriptLoader
if (GetHitUnit()->getPowerType() != POWER_MANA)
return;
- const int32 maxDamage = GetCaster()->GetMap()->GetSpawnMode() == 1 ? 15000 : 10000;
- int32 newDamage = GetHitDamage();
- newDamage += GetHitUnit()->GetMaxPower(POWER_MANA)/2;
- newDamage = std::min<int32>(maxDamage, newDamage);
+ int32 const maxDamage = GetCaster()->GetMap()->IsHeroic() ? 15000 : 10000;
+ int32 newDamage = GetHitDamage() + (GetHitUnit()->GetMaxPower(POWER_MANA) / 2);
- SetHitDamage(newDamage);
+ SetHitDamage(std::min<int32>(maxDamage, newDamage));
}
void Register() override
@@ -261,7 +280,7 @@ class spell_bronjahm_magic_bane : public SpellScriptLoader
class spell_bronjahm_consume_soul : public SpellScriptLoader
{
public:
- spell_bronjahm_consume_soul() : SpellScriptLoader("spell_bronjahm_consume_soul") { }
+ spell_bronjahm_consume_soul() : SpellScriptLoader("spell_bronjahm_consume_soul") { }
class spell_bronjahm_consume_soul_SpellScript : public SpellScript
{
@@ -285,38 +304,22 @@ class spell_bronjahm_consume_soul : public SpellScriptLoader
}
};
-class spell_bronjahm_soulstorm_channel : public SpellScriptLoader
+static uint32 const SoulstormVisualSpells[] =
{
- public:
- spell_bronjahm_soulstorm_channel() : SpellScriptLoader("spell_bronjahm_soulstorm_channel") { }
-
- class spell_bronjahm_soulstorm_channel_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_bronjahm_soulstorm_channel_AuraScript);
-
- void HandlePeriodicTick(AuraEffect const* /*aurEff*/)
- {
- PreventDefaultAction();
- for (uint32 i = 68904; i <= 68907; ++i)
- GetTarget()->CastSpell(GetTarget(), i, true);
- }
-
- void Register() override
- {
- OnEffectPeriodic += AuraEffectPeriodicFn(spell_bronjahm_soulstorm_channel_AuraScript::HandlePeriodicTick, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
- }
- };
-
- AuraScript* GetAuraScript() const override
- {
- return new spell_bronjahm_soulstorm_channel_AuraScript();
- }
+ 68904,
+ 68886,
+ 68905,
+ 68896,
+ 68906,
+ 68897,
+ 68907,
+ 68898
};
class spell_bronjahm_soulstorm_visual : public SpellScriptLoader
{
public:
- spell_bronjahm_soulstorm_visual() : SpellScriptLoader("spell_bronjahm_soulstorm_visual") { }
+ spell_bronjahm_soulstorm_visual(char const* scriptName) : SpellScriptLoader(scriptName) { }
class spell_bronjahm_soulstorm_visual_AuraScript : public AuraScript
{
@@ -325,11 +328,7 @@ class spell_bronjahm_soulstorm_visual : public SpellScriptLoader
void HandlePeriodicTick(AuraEffect const* aurEff)
{
PreventDefaultAction();
- if (aurEff->GetTickNumber()%5)
- return;
- GetTarget()->CastSpell(GetTarget(), 68886, true);
- for (uint32 i = 68896; i <= 68898; ++i)
- GetTarget()->CastSpell(GetTarget(), i, true);
+ GetTarget()->CastSpell(GetTarget(), SoulstormVisualSpells[aurEff->GetTickNumber() % 8], true);
}
void Register() override
@@ -344,21 +343,6 @@ class spell_bronjahm_soulstorm_visual : public SpellScriptLoader
}
};
-class DistanceCheck
-{
- public:
- explicit DistanceCheck(Unit* _caster) : caster(_caster) { }
-
- bool operator() (WorldObject* unit) const
- {
- if (caster->GetExactDist2d(unit) <= 10.0f)
- return true;
- return false;
- }
-
- Unit* caster;
-};
-
class spell_bronjahm_soulstorm_targeting : public SpellScriptLoader
{
public:
@@ -368,25 +352,19 @@ class spell_bronjahm_soulstorm_targeting : public SpellScriptLoader
{
PrepareSpellScript(spell_bronjahm_soulstorm_targeting_SpellScript);
- void FilterTargetsInitial(std::list<WorldObject*>& targets)
- {
- targets.remove_if(DistanceCheck(GetCaster()));
- sharedTargets = targets;
- }
-
- // use the same target for first and second effect
- void FilterTargetsSubsequent(std::list<WorldObject*>& targets)
+ void FilterTargets(std::list<WorldObject*>& targets)
{
- targets = sharedTargets;
+ Unit* caster = GetCaster();
+ targets.remove_if([caster](WorldObject* target)
+ {
+ return caster->GetExactDist2d(target) <= 10.0f;
+ });
}
void Register() override
{
- OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_bronjahm_soulstorm_targeting_SpellScript::FilterTargetsInitial, EFFECT_1, TARGET_UNIT_DEST_AREA_ENEMY);
- OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_bronjahm_soulstorm_targeting_SpellScript::FilterTargetsSubsequent, EFFECT_2, TARGET_UNIT_DEST_AREA_ENEMY);
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_bronjahm_soulstorm_targeting_SpellScript::FilterTargets, EFFECT_ALL, TARGET_UNIT_DEST_AREA_ENEMY);
}
-
- std::list<WorldObject*> sharedTargets;
};
SpellScript* GetSpellScript() const override
@@ -395,13 +373,25 @@ class spell_bronjahm_soulstorm_targeting : public SpellScriptLoader
}
};
+class achievement_bronjahm_soul_power : public AchievementCriteriaScript
+{
+ public:
+ achievement_bronjahm_soul_power() : AchievementCriteriaScript("achievement_bronjahm_soul_power") { }
+
+ bool OnCheck(Player* /*source*/, Unit* target) override
+ {
+ return target && target->GetAI()->GetData(DATA_SOUL_POWER) >= 4;
+ }
+};
+
void AddSC_boss_bronjahm()
{
new boss_bronjahm();
new npc_corrupted_soul_fragment();
new spell_bronjahm_magic_bane();
new spell_bronjahm_consume_soul();
- new spell_bronjahm_soulstorm_channel();
- new spell_bronjahm_soulstorm_visual();
+ new spell_bronjahm_soulstorm_visual("spell_bronjahm_soulstorm_channel");
+ new spell_bronjahm_soulstorm_visual("spell_bronjahm_soulstorm_visual");
new spell_bronjahm_soulstorm_targeting();
+ new achievement_bronjahm_soul_power();
}
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 2f1d4943019..d5f00757039 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
@@ -128,7 +128,7 @@ class boss_devourer_of_souls : public CreatureScript
struct boss_devourer_of_soulsAI : public BossAI
{
- boss_devourer_of_soulsAI(Creature* creature) : BossAI(creature, DATA_DEVOURER_EVENT)
+ boss_devourer_of_soulsAI(Creature* creature) : BossAI(creature, DATA_DEVOURER_OF_SOULS)
{
Initialize();
beamAngle = 0.f;
@@ -143,20 +143,17 @@ class boss_devourer_of_souls : public CreatureScript
void Reset() override
{
+ _Reset();
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE);
me->SetDisplayId(DISPLAY_ANGER);
me->SetReactState(REACT_AGGRESSIVE);
- events.Reset();
- summons.DespawnAll();
-
Initialize();
-
- instance->SetData(DATA_DEVOURER_EVENT, NOT_STARTED);
}
void EnterCombat(Unit* /*who*/) override
{
+ _EnterCombat();
Talk(SAY_FACE_AGGRO);
if (!me->FindNearestCreature(NPC_CRUCIBLE_OF_SOULS, 60)) // Prevent double spawn
@@ -166,8 +163,6 @@ class boss_devourer_of_souls : public CreatureScript
events.ScheduleEvent(EVENT_WELL_OF_SOULS, 30000);
events.ScheduleEvent(EVENT_UNLEASHED_SOULS, 20000);
events.ScheduleEvent(EVENT_WAILING_SOULS, urand(60000, 70000));
-
- instance->SetData(DATA_DEVOURER_EVENT, IN_PROGRESS);
}
void KilledUnit(Unit* victim) override
@@ -175,7 +170,7 @@ class boss_devourer_of_souls : public CreatureScript
if (victim->GetTypeId() != TYPEID_PLAYER)
return;
- int32 textId = 0;
+ uint8 textId = 0;
switch (me->GetDisplayId())
{
case DISPLAY_ANGER:
@@ -197,14 +192,12 @@ class boss_devourer_of_souls : public CreatureScript
void JustDied(Unit* /*killer*/) override
{
- summons.DespawnAll();
+ _JustDied();
Position spawnPoint = {5618.139f, 2451.873f, 705.854f, 0};
Talk(SAY_FACE_DEATH);
- instance->SetData(DATA_DEVOURER_EVENT, DONE);
-
int32 entryIndex;
if (instance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE)
entryIndex = 0;
@@ -402,11 +395,6 @@ class spell_devourer_of_souls_mirrored_soul_proc : public SpellScriptLoader
return true;
}
- bool Load() override
- {
- return true;
- }
-
bool CheckProc(ProcEventInfo& /*eventInfo*/)
{
return GetCaster() && GetCaster()->IsAlive();
diff --git a/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/forge_of_souls.h b/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/forge_of_souls.h
index 054e5d5a7bd..ddbc117e7fd 100644
--- a/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/forge_of_souls.h
+++ b/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/forge_of_souls.h
@@ -15,38 +15,44 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef DEF_FORGE_OF_SOULS_H
-#define DEF_FORGE_OF_SOULS_H
+#ifndef FORGE_OF_SOULS_H_
+#define FORGE_OF_SOULS_H_
#define FoSScriptName "instance_forge_of_souls"
#define DataHeader "FOS"
+uint32 const EncounterCount = 2;
+
enum Data
{
- DATA_BRONJAHM = 0,
- DATA_DEVOURER = 1,
- DATA_DEVOURER_EVENT = 2,
- DATA_TEAM_IN_INSTANCE = 3,
+ // Encounter states and GUIDs
+ DATA_BRONJAHM = 0,
+ DATA_DEVOURER_OF_SOULS = 1,
+
+ // Additional Data
+ DATA_TEAM_IN_INSTANCE = 2
};
enum Creatures
{
- CREATURE_BRONJAHM = 36497,
- CREATURE_DEVOURER = 36502,
-
- NPC_SYLVANAS_PART1 = 37596,
- NPC_SYLVANAS_PART2 = 38161,
- NPC_JAINA_PART1 = 37597,
- NPC_JAINA_PART2 = 38160,
- NPC_KALIRA = 37583,
- NPC_ELANDRA = 37774,
- NPC_LORALEN = 37779,
- NPC_KORELN = 37582,
- NPC_CHAMPION_1_HORDE = 37584,
- NPC_CHAMPION_2_HORDE = 37587,
- NPC_CHAMPION_3_HORDE = 37588,
- NPC_CHAMPION_1_ALLIANCE = 37496,
- NPC_CHAMPION_2_ALLIANCE = 37497,
- NPC_CRUCIBLE_OF_SOULS = 37094,
+ NPC_BRONJAHM = 36497,
+ NPC_DEVOURER = 36502,
+ NPC_CORRUPTED_SOUL_FRAGMENT = 36535,
+
+ NPC_SYLVANAS_PART1 = 37596,
+ NPC_SYLVANAS_PART2 = 38161,
+ NPC_JAINA_PART1 = 37597,
+ NPC_JAINA_PART2 = 38160,
+ NPC_KALIRA = 37583,
+ NPC_ELANDRA = 37774,
+ NPC_LORALEN = 37779,
+ NPC_KORELN = 37582,
+ NPC_CHAMPION_1_HORDE = 37584,
+ NPC_CHAMPION_2_HORDE = 37587,
+ NPC_CHAMPION_3_HORDE = 37588,
+ NPC_CHAMPION_1_ALLIANCE = 37496,
+ NPC_CHAMPION_2_ALLIANCE = 37497,
+ NPC_CRUCIBLE_OF_SOULS = 37094
};
-#endif
+
+#endif // FORGE_OF_SOULS_H_
diff --git a/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/instance_forge_of_souls.cpp b/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/instance_forge_of_souls.cpp
index 8b586ea7fc2..db7628ebada 100644
--- a/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/instance_forge_of_souls.cpp
+++ b/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/instance_forge_of_souls.cpp
@@ -20,13 +20,6 @@
#include "forge_of_souls.h"
#include "Player.h"
-#define MAX_ENCOUNTER 2
-
-/* Forge of Souls encounters:
-0- Bronjahm, The Godfather of Souls
-1- The Devourer of Souls
-*/
-
class instance_forge_of_souls : public InstanceMapScript
{
public:
@@ -37,7 +30,7 @@ class instance_forge_of_souls : public InstanceMapScript
instance_forge_of_souls_InstanceScript(Map* map) : InstanceScript(map)
{
SetHeaders(DataHeader);
- SetBossNumber(MAX_ENCOUNTER);
+ SetBossNumber(EncounterCount);
teamInInstance = 0;
}
@@ -60,10 +53,10 @@ class instance_forge_of_souls : public InstanceMapScript
switch (creature->GetEntry())
{
- case CREATURE_BRONJAHM:
+ case NPC_BRONJAHM:
bronjahm = creature->GetGUID();
break;
- case CREATURE_DEVOURER:
+ case NPC_DEVOURER:
devourerOfSouls = creature->GetGUID();
break;
case NPC_SYLVANAS_PART1:
@@ -100,7 +93,7 @@ class instance_forge_of_souls : public InstanceMapScript
{
case DATA_BRONJAHM:
return bronjahm;
- case DATA_DEVOURER:
+ case DATA_DEVOURER_OF_SOULS:
return devourerOfSouls;
default:
break;
diff --git a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp
index 9edde447f32..927ebfbc55c 100644
--- a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp
+++ b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp
@@ -2640,13 +2640,7 @@ class npc_quel_delar_sword : public CreatureScript
break;
case EVENT_QUEL_DELAR_FLIGHT:
{
- Movement::MoveSplineInit init(me);
- FillCirclePath(QuelDelarCenterPos, 18.0f, 718.046f, init.Path(), true);
- init.SetFly();
- init.SetCyclic();
- init.SetAnimation(Movement::ToFly);
- init.Launch();
-
+ me->GetMotionMaster()->MoveCirclePath(QuelDelarCenterPos.GetPositionX(), QuelDelarCenterPos.GetPositionY(), 718.046f, 18.0f, true, 16);
_events.ScheduleEvent(EVENT_QUEL_DELAR_LAND, 15000);
break;
}
@@ -2694,21 +2688,6 @@ class npc_quel_delar_sword : public CreatureScript
}
private:
- void FillCirclePath(Position const& centerPos, float radius, float z, Movement::PointsArray& path, bool clockwise)
- {
- float step = clockwise ? -M_PI / 8.0f : M_PI / 8.0f;
- float angle = centerPos.GetAngle(me->GetPositionX(), me->GetPositionY());
-
- for (uint8 i = 0; i < 16; angle += step, ++i)
- {
- G3D::Vector3 point;
- point.x = centerPos.GetPositionX() + radius * cosf(angle);
- point.y = centerPos.GetPositionY() + radius * sinf(angle);
- point.z = z;
- path.push_back(point);
- }
- }
-
EventMap _events;
InstanceScript* _instance;
bool _intro;
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_rotface.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_rotface.cpp
index 4d7b9ec42b4..d56a3f80f75 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_rotface.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_rotface.cpp
@@ -18,7 +18,7 @@
#include "ObjectMgr.h"
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
-#include "SpellAuras.h"
+#include "SpellAuraEffects.h"
#include "GridNotifiers.h"
#include "icecrown_citadel.h"
@@ -213,7 +213,7 @@ class boss_rotface : public CreatureScript
}
break;
case EVENT_MUTATED_INFECTION:
- me->CastCustomSpell(SPELL_MUTATED_INFECTION, SPELLVALUE_MAX_TARGETS, 1, NULL, false);
+ DoCastAOE(SPELL_MUTATED_INFECTION);
events.ScheduleEvent(EVENT_MUTATED_INFECTION, infectionCooldown);
break;
case EVENT_VILE_GAS:
@@ -509,13 +509,6 @@ class spell_rotface_mutated_infection : public SpellScriptLoader
{
PrepareSpellScript(spell_rotface_mutated_infection_SpellScript);
- public:
- spell_rotface_mutated_infection_SpellScript()
- {
- _target = nullptr;
- }
-
- private:
void FilterTargets(std::list<WorldObject*>& targets)
{
// remove targets with this aura already
@@ -527,14 +520,6 @@ class spell_rotface_mutated_infection : public SpellScriptLoader
WorldObject* target = Trinity::Containers::SelectRandomContainerElement(targets);
targets.clear();
targets.push_back(target);
- _target = target;
- }
-
- void ReplaceTargets(std::list<WorldObject*>& targets)
- {
- targets.clear();
- if (_target)
- targets.push_back(_target);
}
void NotifyTargets()
@@ -546,19 +531,43 @@ class spell_rotface_mutated_infection : public SpellScriptLoader
void Register() override
{
- OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_rotface_mutated_infection_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY);
- OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_rotface_mutated_infection_SpellScript::ReplaceTargets, EFFECT_1, TARGET_UNIT_SRC_AREA_ENEMY);
- OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_rotface_mutated_infection_SpellScript::ReplaceTargets, EFFECT_2, TARGET_UNIT_SRC_AREA_ENEMY);
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_rotface_mutated_infection_SpellScript::FilterTargets, EFFECT_ALL, TARGET_UNIT_SRC_AREA_ENEMY);
AfterHit += SpellHitFn(spell_rotface_mutated_infection_SpellScript::NotifyTargets);
}
+ };
+
+ class spell_rotface_mutated_infection_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_rotface_mutated_infection_AuraScript);
- WorldObject* _target;
+ bool Validate(SpellInfo const* spellInfo) override
+ {
+ if (!sSpellMgr->GetSpellInfo(uint32(spellInfo->Effects[EFFECT_2].CalcValue())))
+ return false;
+ return true;
+ }
+
+ void HandleEffectRemove(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
+ {
+ Unit* target = GetTarget();
+ target->CastSpell(target, uint32(GetSpellInfo()->Effects[EFFECT_2].CalcValue()), true, nullptr, aurEff, GetCasterGUID());
+ }
+
+ void Register() override
+ {
+ AfterEffectRemove += AuraEffectRemoveFn(spell_rotface_mutated_infection_AuraScript::HandleEffectRemove, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE, AURA_EFFECT_HANDLE_REAL);
+ }
};
SpellScript* GetSpellScript() const override
{
return new spell_rotface_mutated_infection_SpellScript();
}
+
+ AuraScript* GetAuraScript() const override
+ {
+ return new spell_rotface_mutated_infection_AuraScript();
+ }
};
class spell_rotface_little_ooze_combine : public SpellScriptLoader
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp
index ae0e00cb849..07816ebbe39 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp
@@ -2417,6 +2417,7 @@ class spell_the_lich_king_defile : public SpellScriptLoader
void CorrectRange(std::list<WorldObject*>& targets)
{
targets.remove_if(ExactDistanceCheck(GetCaster(), 10.0f * GetCaster()->GetObjectScale()));
+ targets.remove_if(Trinity::UnitAuraCheck(true, SPELL_HARVEST_SOUL_VALKYR));
}
void ChangeDamageAndGrow()
diff --git a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp
index 43069f10464..6c3b2187325 100644
--- a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp
+++ b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp
@@ -520,11 +520,7 @@ public:
_despawned = false;
break;
case ACTION_CYCLIC_MOVEMENT:
- Movement::MoveSplineInit init(me);
- FillCirclePath(MalygosPositions[3], 120.0f, 283.2763f, init.Path(), true);
- init.SetFly();
- init.SetCyclic();
- init.Launch();
+ me->GetMotionMaster()->MoveCirclePath(MalygosPositions[3].GetPositionX(), MalygosPositions[3].GetPositionY(), 283.2763f, 120.0f, true, 16);
break;
}
}
@@ -1020,22 +1016,6 @@ public:
}
private:
- // Used to generate perfect cyclic movements (Enter Circle).
- void FillCirclePath(Position const& centerPos, float radius, float z, Movement::PointsArray& path, bool clockwise)
- {
- float step = clockwise ? float(-M_PI) / 8.0f : float(M_PI) / 8.0f;
- float angle = centerPos.GetAngle(me->GetPositionX(), me->GetPositionY());
-
- for (uint8 i = 0; i < 16; angle += step, ++i)
- {
- G3D::Vector3 point;
- point.x = centerPos.GetPositionX() + radius * cosf(angle);
- point.y = centerPos.GetPositionY() + radius * sinf(angle);
- point.z = z; // Don't use any height getters unless all bugs are fixed.
- path.push_back(point);
- }
- }
-
uint8 _phase; // Counter for phases used with a getter.
uint8 _summonDeaths; // Keeps count of arcane trash.
uint8 _preparingPulsesChecker; // In retail they use 2 preparing pulses with 7 sec CD, after they pass 2 seconds.
@@ -1326,11 +1306,7 @@ public:
{
if (action < ACTION_DELAYED_DESPAWN)
{
- Movement::MoveSplineInit init(me);
- FillCirclePath(MalygosPositions[3], 35.0f, 282.3402f, init.Path(), true);
- init.SetFly();
- init.SetCyclic();
- init.Launch();
+ me->GetMotionMaster()->MoveCirclePath(MalygosPositions[3].GetPositionX(), MalygosPositions[3].GetPositionY(), 282.3402f, 35.0f, true, 16);
}
else
{
@@ -1339,21 +1315,6 @@ public:
}
private:
- void FillCirclePath(Position const& centerPos, float radius, float z, Movement::PointsArray& path, bool clockwise)
- {
- float step = clockwise ? float(-M_PI) / 9.0f : float(M_PI) / 9.0f;
- float angle = centerPos.GetAngle(me->GetPositionX(), me->GetPositionY());
-
- for (uint8 i = 0; i < 18; angle += step, ++i)
- {
- G3D::Vector3 point;
- point.x = centerPos.GetPositionX() + radius * cosf(angle);
- point.y = centerPos.GetPositionY() + radius * sinf(angle);
- point.z = z; // Don't use any height getters unless all bugs are fixed.
- path.push_back(point);
- }
- }
-
InstanceScript* _instance;
};
diff --git a/src/server/scripts/Northrend/Nexus/Nexus/boss_commander_kolurg.cpp b/src/server/scripts/Northrend/Nexus/Nexus/boss_commander_kolurg.cpp
deleted file mode 100644
index fc56f541a4b..00000000000
--- a/src/server/scripts/Northrend/Nexus/Nexus/boss_commander_kolurg.cpp
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-/* Script Data Start
-SDName: Boss Commander Kolurg
-SDAuthor: LordVanMartin
-SD%Complete:
-SDComment: Only Alliance Heroic
-SDCategory:
-Script Data End */
-
-#include "ScriptMgr.h"
-#include "ScriptedCreature.h"
-
-enum Spells
-{
- SPELL_BATTLE_SHOUT = 31403,
- SPELL_CHARGE = 60067,
- SPELL_FRIGHTENING_SHOUT = 19134,
- SPELL_WHIRLWIND_1 = 38619,
- SPELL_WHIRLWIND_2 = 38618
-
-};
-
-//not used
-//Yell
-#define SAY_AGGRO -1576024
-#define SAY_KILL -1576025
-#define SAY_DEATH -1576026
-
-class boss_commander_kolurg : public CreatureScript
-{
-public:
- boss_commander_kolurg() : CreatureScript("boss_commander_kolurg") { }
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return new boss_commander_kolurgAI(creature);
- }
-
- struct boss_commander_kolurgAI : public ScriptedAI
- {
- boss_commander_kolurgAI(Creature* creature) : ScriptedAI(creature) { }
-
- void Reset() override { }
- void EnterCombat(Unit* /*who*/) override { }
- void AttackStart(Unit* /*who*/) override { }
- void MoveInLineOfSight(Unit* /*who*/) override { }
-
- void UpdateAI(uint32 /*diff*/) override
- {
- //Return since we have no target
- if (!UpdateVictim())
- return;
-
- DoMeleeAttackIfReady();
- }
- void JustDied(Unit* /*killer*/) override { }
- };
-
-};
-
-void AddSC_boss_commander_kolurg()
-{
- new boss_commander_kolurg();
-}
diff --git a/src/server/scripts/Northrend/Nexus/Nexus/boss_commander_stoutbeard.cpp b/src/server/scripts/Northrend/Nexus/Nexus/boss_commander_stoutbeard.cpp
deleted file mode 100644
index ff08038d898..00000000000
--- a/src/server/scripts/Northrend/Nexus/Nexus/boss_commander_stoutbeard.cpp
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-/* Script Data Start
-SDName: Boss Commander Stoutbeard
-SDAuthor: LordVanMartin
-SD%Complete:
-SDComment: Only Horde Heroic
-SDCategory:
-Script Data End */
-
-#include "ScriptMgr.h"
-#include "ScriptedCreature.h"
-
-enum CommanderStoutbeard
-{
- SPELL_BATTLE_SHOUT = 31403,
- SPELL_CHARGE = 60067,
- SPELL_FRIGHTENING_SHOUT = 19134,
- SPELL_WHIRLWIND_1 = 38619,
- SPELL_WHIRLWIND_2 = 38618
-};
-
-
-class boss_commander_stoutbeard : public CreatureScript
-{
-public:
- boss_commander_stoutbeard() : CreatureScript("boss_commander_stoutbeard") { }
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return new boss_commander_stoutbeardAI(creature);
- }
-
- struct boss_commander_stoutbeardAI : public ScriptedAI
- {
- boss_commander_stoutbeardAI(Creature* creature) : ScriptedAI(creature) { }
-
- void Reset() override { }
- void AttackStart(Unit* /*who*/) override { }
- void MoveInLineOfSight(Unit* /*who*/) override { }
-
- void UpdateAI(uint32 /*diff*/) override
- {
- //Return since we have no target
- if (!UpdateVictim())
- return;
-
- DoMeleeAttackIfReady();
- }
- };
-
-};
-
-void AddSC_boss_commander_stoutbeard()
-{
- new boss_commander_stoutbeard();
-}
diff --git a/src/server/scripts/Northrend/Nexus/Nexus/boss_nexus_commanders.cpp b/src/server/scripts/Northrend/Nexus/Nexus/boss_nexus_commanders.cpp
new file mode 100644
index 00000000000..d40f9fecc6a
--- /dev/null
+++ b/src/server/scripts/Northrend/Nexus/Nexus/boss_nexus_commanders.cpp
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "ScriptMgr.h"
+#include "ScriptedCreature.h"
+#include "nexus.h"
+
+enum Spells
+{
+ SPELL_BATTLE_SHOUT = 31403,
+ SPELL_CHARGE = 60067,
+ SPELL_FRIGHTENING_SHOUT = 19134,
+ SPELL_WHIRLWIND = 38618,
+ SPELL_FROZEN_PRISON = 47543
+};
+
+enum Yells
+{
+ SAY_AGGRO = 0,
+ SAY_KILL = 1,
+ SAY_DEATH = 2
+};
+
+enum Events
+{
+ EVENT_CHARGE_COMMANDER = 1,
+ EVENT_WHIRLWIND,
+ EVENT_FRIGHTENING_SHOUT
+};
+
+class boss_nexus_commanders : public CreatureScript
+{
+ public:
+ boss_nexus_commanders() : CreatureScript("boss_nexus_commanders") { }
+
+ struct boss_nexus_commandersAI : public BossAI
+ {
+ boss_nexus_commandersAI(Creature* creature) : BossAI(creature, DATA_COMMANDER) { }
+
+ void EnterCombat(Unit* /*who*/) override
+ {
+ _EnterCombat();
+ Talk(SAY_AGGRO);
+ me->RemoveAurasDueToSpell(SPELL_FROZEN_PRISON);
+ DoCast(me, SPELL_BATTLE_SHOUT);
+
+ events.ScheduleEvent(EVENT_CHARGE_COMMANDER, urand(3000, 4000));
+ events.ScheduleEvent(EVENT_WHIRLWIND, urand(6000, 8000));
+ events.ScheduleEvent(EVENT_FRIGHTENING_SHOUT, urand(13000, 15000));
+ }
+
+ void ExecuteEvent(uint32 eventId) override
+ {
+ switch (eventId)
+ {
+ case EVENT_CHARGE_COMMANDER:
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true))
+ DoCast(target, SPELL_CHARGE);
+ events.ScheduleEvent(EVENT_CHARGE_COMMANDER, urand(11000, 15000));
+ break;
+ case EVENT_WHIRLWIND:
+ DoCast(me, SPELL_WHIRLWIND);
+ events.ScheduleEvent(EVENT_WHIRLWIND, urand(19500, 25000));
+ break;
+ case EVENT_FRIGHTENING_SHOUT:
+ DoCastAOE(SPELL_FRIGHTENING_SHOUT);
+ events.ScheduleEvent(EVENT_FRIGHTENING_SHOUT, urand(45000, 55000));
+ break;
+ default:
+ break;
+ }
+ }
+
+ void JustDied(Unit* /*killer*/) override
+ {
+ _JustDied();
+ Talk(SAY_DEATH);
+ }
+
+ void KilledUnit(Unit* who) override
+ {
+ if (who->GetTypeId() == TYPEID_PLAYER)
+ Talk(SAY_KILL);
+ }
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetInstanceAI<boss_nexus_commandersAI>(creature);
+ }
+};
+
+void AddSC_boss_nexus_commanders()
+{
+ new boss_nexus_commanders();
+}
diff --git a/src/server/scripts/Northrend/Nexus/Nexus/nexus.h b/src/server/scripts/Northrend/Nexus/Nexus/nexus.h
index 90866ea83f8..c48c7323301 100644
--- a/src/server/scripts/Northrend/Nexus/Nexus/nexus.h
+++ b/src/server/scripts/Northrend/Nexus/Nexus/nexus.h
@@ -21,32 +21,33 @@
#define NexusScriptName "instance_nexus"
#define DataHeader "NEX"
-uint32 const EncounterCount = 4;
+uint32 const EncounterCount = 5;
enum DataTypes
{
- DATA_MAGUS_TELESTRA = 0,
- DATA_ANOMALUS = 1,
- DATA_ORMOROK = 2,
- DATA_KERISTRASZA = 3,
+ DATA_COMMANDER = 0,
+ DATA_MAGUS_TELESTRA = 1,
+ DATA_ANOMALUS = 2,
+ DATA_ORMOROK = 3,
+ DATA_KERISTRASZA = 4,
- ANOMALUS_CONTAINMET_SPHERE = 4,
- ORMOROKS_CONTAINMET_SPHERE = 5,
- TELESTRAS_CONTAINMET_SPHERE = 6
+ ANOMALUS_CONTAINMET_SPHERE = 5,
+ ORMOROKS_CONTAINMET_SPHERE = 6,
+ TELESTRAS_CONTAINMET_SPHERE = 7
};
enum CreatureIds
{
NPC_ANOMALUS = 26763,
NPC_KERISTRASZA = 26723,
-
+
// Alliance
NPC_ALLIANCE_BERSERKER = 26800,
NPC_ALLIANCE_RANGER = 26802,
NPC_ALLIANCE_CLERIC = 26805,
NPC_ALLIANCE_COMMANDER = 27949,
NPC_COMMANDER_STOUTBEARD = 26796,
-
+
// Horde
NPC_HORDE_BERSERKER = 26799,
NPC_HORDE_RANGER = 26801,
@@ -59,7 +60,7 @@ enum GameObjectIds
{
GO_ANOMALUS_CONTAINMET_SPHERE = 188527,
GO_ORMOROKS_CONTAINMET_SPHERE = 188528,
- GO_TELESTRAS_CONTAINMET_SPHERE = 188526
+ GO_TELESTRAS_CONTAINMET_SPHERE = 188526
};
#endif
diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp
index 7bc8a5300f4..536cae08483 100644
--- a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp
+++ b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp
@@ -29,7 +29,7 @@ EndScriptData */
#include "Player.h"
#include "SpellInfo.h"
-enum Enums
+enum Texts
{
SAY_AGGRO = 0,
SAY_FORGE = 1,
@@ -38,29 +38,50 @@ enum Enums
SAY_DEATH = 4,
EMOTE_TO_ANVIL = 5,
EMOTE_SHATTER = 6,
+};
+enum Spells
+{
SPELL_HEAT = 52387,
SPELL_SHATTERING_STOMP = 52237,
-
SPELL_TEMPER = 52238,
SPELL_TEMPER_DUMMY = 52654,
-
SPELL_SUMMON_MOLTEN_GOLEM = 52405,
+ SPELL_FORGE_VISUAL = 52654,
// Molten Golem
SPELL_BLAST_WAVE = 23113,
SPELL_IMMOLATION_STRIKE = 52433,
SPELL_SHATTER = 52429,
+};
+enum Events
+{
+ EVENT_PAUSE = 1,
+ EVENT_SHATTERING_STOMP = 2,
+ EVENT_SHATTER = 3,
+ EVENT_FORGE_CAST = 4,
+
+ // Molten Golem
+ EVENT_BLAST = 5,
+ EVENT_IMMOLATION = 6
+};
+
+enum Npcs
+{
NPC_VOLKHAN_ANVIL = 28823,
NPC_MOLTEN_GOLEM = 28695,
NPC_BRITTLE_GOLEM = 28681,
-
MAX_GOLEM = 2,
-
DATA_SHATTER_RESISTANT = 2042
};
+enum Phases
+{
+ PHASE_INTRO = 1,
+ PHASE_NORMAL
+};
+
/*######
## Boss Volkhan
######*/
@@ -68,68 +89,44 @@ class boss_volkhan : public CreatureScript
{
public:
boss_volkhan() : CreatureScript("boss_volkhan") { }
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return GetInstanceAI<boss_volkhanAI>(creature);
- }
-
- struct boss_volkhanAI : public ScriptedAI
+
+ struct boss_volkhanAI : public BossAI
{
- boss_volkhanAI(Creature* creature) : ScriptedAI(creature)
+ boss_volkhanAI(Creature* creature) : BossAI(creature, DATA_VOLKHAN)
{
Initialize();
- instance = creature->GetInstanceScript();
}
void Initialize()
{
- m_bIsStriking = false;
- m_bHasTemper = false;
+ m_bIsStriking = false;
+ m_bHasTemper = false;
m_bCanShatterGolem = false;
-
- m_uiPause_Timer = 3500;
- m_uiShatteringStomp_Timer = 0;
- m_uiShatter_Timer = 5000;
- m_uiDelay_Timer = 1000;
- m_uiSummonPhase = 0;
- GolemsShattered = 0;
+ m_uiDelay_Timer = 1000;
+ m_uiSummonPhase = 0;
+ GolemsShattered = 0;
m_uiHealthAmountModifier = 1;
}
- InstanceScript* instance;
-
- GuidList m_lGolemGUIDList;
-
- bool m_bHasTemper;
- bool m_bIsStriking;
- bool m_bCanShatterGolem;
-
- uint8 GolemsShattered;
- uint32 m_uiPause_Timer;
- uint32 m_uiShatteringStomp_Timer;
- uint32 m_uiShatter_Timer;
- uint32 m_uiDelay_Timer;
- uint32 m_uiSummonPhase;
-
- uint32 m_uiHealthAmountModifier;
-
void Reset() override
{
Initialize();
-
+ _Reset();
DespawnGolem();
m_lGolemGUIDList.clear();
-
- instance->SetBossState(DATA_VOLKHAN, NOT_STARTED);
+ events.SetPhase(PHASE_INTRO);
+ events.ScheduleEvent(EVENT_FORGE_CAST, 2 * IN_MILLISECONDS, 0, PHASE_INTRO);
}
void EnterCombat(Unit* /*who*/) override
{
Talk(SAY_AGGRO);
-
- instance->SetBossState(DATA_VOLKHAN, IN_PROGRESS);
+ events.SetPhase(PHASE_NORMAL);
+ events.ScheduleEvent(EVENT_PAUSE, 3.5 * IN_MILLISECONDS, 0, PHASE_NORMAL);
+ events.ScheduleEvent(EVENT_SHATTERING_STOMP, 0 * IN_MILLISECONDS, 0, PHASE_NORMAL);
+ events.ScheduleEvent(EVENT_SHATTER, 5 * IN_MILLISECONDS, 0, PHASE_NORMAL);
+ _EnterCombat();
}
void AttackStart(Unit* who) override
@@ -150,7 +147,7 @@ public:
Talk(SAY_DEATH);
DespawnGolem();
- instance->SetBossState(DATA_VOLKHAN, DONE);
+ _JustDied();
}
void KilledUnit(Unit* who) override
@@ -224,59 +221,61 @@ public:
return 0;
}
- void UpdateAI(uint32 uiDiff) override
+ void UpdateAI(uint32 diff) override
{
- if (!UpdateVictim())
+ // Return since we have no target and are in CombatPhase
+ if (events.IsInPhase(PHASE_NORMAL) && !UpdateVictim())
return;
- if (m_bIsStriking)
- {
- if (m_uiPause_Timer <= uiDiff)
- {
- if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() != CHASE_MOTION_TYPE)
- if (me->GetVictim())
- me->GetMotionMaster()->MoveChase(me->GetVictim());
-
- m_bHasTemper = false;
- m_bIsStriking = false;
- m_uiPause_Timer = 3500;
- }
- else
- m_uiPause_Timer -= uiDiff;
+ events.Update(diff);
+ if (me->HasUnitState(UNIT_STATE_CASTING))
return;
- }
- // When to start shatter? After 60, 40 or 20% hp?
- if (!m_bHasTemper && m_uiHealthAmountModifier >= 3)
+ while (uint32 eventId = events.ExecuteEvent())
{
- if (m_uiShatteringStomp_Timer <= uiDiff)
+ switch (eventId)
{
- // Should he stomp even if he has no brittle golem to shatter?
- Talk(SAY_STOMP);
-
- DoCast(me, SPELL_SHATTERING_STOMP);
+ case EVENT_PAUSE:
+ if (m_bIsStriking)
+ {
+ if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() != CHASE_MOTION_TYPE)
+ if (me->GetVictim())
+ me->GetMotionMaster()->MoveChase(me->GetVictim());
- Talk(EMOTE_SHATTER);
+ m_bHasTemper = false;
+ m_bIsStriking = false;
+ events.ScheduleEvent(EVENT_PAUSE, 3.5 * IN_MILLISECONDS, 0, PHASE_NORMAL);
+ }
+ break;
+ case EVENT_SHATTERING_STOMP:
+ if (!m_bHasTemper && m_uiHealthAmountModifier >= 3)
+ {
+ // Should he stomp even if he has no brittle golem to shatter?
+ Talk(SAY_STOMP);
- m_uiShatteringStomp_Timer = 30000;
- m_bCanShatterGolem = true;
- }
- else
- m_uiShatteringStomp_Timer -= uiDiff;
- }
+ DoCast(me, SPELL_SHATTERING_STOMP);
- // Shatter Golems 3 seconds after Shattering Stomp
- if (m_bCanShatterGolem)
- {
- if (m_uiShatter_Timer <= uiDiff)
- {
- ShatterGolem();
- m_uiShatter_Timer = 3000;
- m_bCanShatterGolem = false;
+ Talk(EMOTE_SHATTER);
+ events.ScheduleEvent(EVENT_SHATTERING_STOMP, 30 * IN_MILLISECONDS, 0, PHASE_NORMAL);
+ m_bCanShatterGolem = true;
+ }
+ break;
+ case EVENT_SHATTER:
+ if (m_bCanShatterGolem)
+ {
+ ShatterGolem();
+ events.ScheduleEvent(EVENT_SHATTER, 3 * IN_MILLISECONDS, 0, PHASE_NORMAL);
+ m_bCanShatterGolem = false;
+ }
+ break;
+ case EVENT_FORGE_CAST:
+ DoCast(me, SPELL_FORGE_VISUAL);
+ events.ScheduleEvent(EVENT_FORGE_CAST, 15 * IN_MILLISECONDS, 0, PHASE_INTRO);
+ break;
+ default:
+ break;
}
- else
- m_uiShatter_Timer -= uiDiff;
}
// Health check
@@ -302,12 +301,10 @@ public:
me->GetMotionMaster()->MoveTargetedHome();
m_uiSummonPhase = 2; // Set Next Phase
break;
-
case 2:
// 2 - Check if reached Anvil
// This is handled in: void JustReachedHome() override
break;
-
case 3:
// 3 - Cast Temper on the Anvil
if (Unit* target = GetClosestCreatureWithEntry(me, NPC_VOLKHAN_ANVIL, 1000.0f, true))
@@ -319,10 +316,9 @@ public:
m_uiDelay_Timer = 1000; // Delay 2 seconds before next phase can begin
m_uiSummonPhase = 4; // Set Next Phase
break;
-
case 4:
// 4 - Wait for delay to expire
- if (m_uiDelay_Timer <= uiDiff)
+ if (m_uiDelay_Timer <= diff)
{
if (Unit* target = SelectTarget(SELECT_TARGET_TOPAGGRO, 0))
{
@@ -333,9 +329,8 @@ public:
m_uiSummonPhase = 5;
}
else
- m_uiDelay_Timer -= uiDiff;
+ m_uiDelay_Timer -= diff;
break;
-
case 5:
// 5 - Spawn the Golems
if (Creature* creatureTarget = GetClosestCreatureWithEntry(me, NPC_VOLKHAN_ANVIL, 1000.0f, true))
@@ -349,13 +344,30 @@ public:
DoMeleeAttackIfReady();
}
+
+ private:
+ GuidList m_lGolemGUIDList;
+ uint32 m_uiHealthAmountModifier;
+ uint8 GolemsShattered;
+ uint32 m_uiDelay_Timer;
+ uint32 m_uiSummonPhase;
+
+ bool m_bHasTemper;
+ bool m_bIsStriking;
+ bool m_bCanShatterGolem;
};
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetInstanceAI<boss_volkhanAI>(creature);
+ }
+
};
/*######
## npc_molten_golem
######*/
+
class npc_molten_golem : public CreatureScript
{
public:
@@ -376,18 +388,12 @@ public:
void Initialize()
{
m_bIsFrozen = false;
-
- m_uiBlast_Timer = 20000;
- m_uiDeathDelay_Timer = 0;
- m_uiImmolation_Timer = 5000;
+ events.ScheduleEvent(EVENT_BLAST, 20 * IN_MILLISECONDS);
+ events.ScheduleEvent(EVENT_IMMOLATION, 5 * IN_MILLISECONDS);
}
bool m_bIsFrozen;
- uint32 m_uiBlast_Timer;
- uint32 m_uiDeathDelay_Timer;
- uint32 m_uiImmolation_Timer;
-
void Reset() override
{
Initialize();
@@ -433,30 +439,39 @@ public:
me->DespawnOrUnsummon();
}
- void UpdateAI(uint32 uiDiff) override
+ void UpdateAI(uint32 diff) override
{
// Return since we have no target or if we are frozen
if (!UpdateVictim() || m_bIsFrozen)
return;
- if (m_uiBlast_Timer <= uiDiff)
- {
- DoCast(me, SPELL_BLAST_WAVE);
- m_uiBlast_Timer = 20000;
- }
- else
- m_uiBlast_Timer -= uiDiff;
+ events.Update(diff);
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
- if (m_uiImmolation_Timer <= uiDiff)
+ while (uint32 eventId = events.ExecuteEvent())
{
- DoCastVictim(SPELL_IMMOLATION_STRIKE);
- m_uiImmolation_Timer = 5000;
+ switch (eventId)
+ {
+ case EVENT_BLAST:
+ DoCast(me, SPELL_BLAST_WAVE);
+ events.ScheduleEvent(EVENT_BLAST, 20 * IN_MILLISECONDS);
+ break;
+ case EVENT_IMMOLATION:
+ DoCastVictim(SPELL_IMMOLATION_STRIKE);
+ events.ScheduleEvent(EVENT_BLAST, 5 * IN_MILLISECONDS);
+ break;
+ default:
+ break;
+ }
}
- else
- m_uiImmolation_Timer -= uiDiff;
DoMeleeAttackIfReady();
}
+
+ private:
+ EventMap events;
};
};
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp
index a682e405d08..a7a9f8dde88 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp
@@ -1126,30 +1126,11 @@ class npc_ominous_cloud : public CreatureScript
DoCast(me, SPELL_OMINOUS_CLOUD_VISUAL);
}
- void FillCirclePath(Position const& centerPos, float radius, float z, Movement::PointsArray& path, bool clockwise)
- {
- float step = clockwise ? float(-M_PI) / 8.0f : float(M_PI) / 8.0f;
- float angle = centerPos.GetAngle(me->GetPositionX(), me->GetPositionY());
-
- for (uint8 i = 0; i < 16; angle += step, ++i)
- {
- G3D::Vector3 point;
- point.x = centerPos.GetPositionX() + radius * cosf(angle);
- point.y = centerPos.GetPositionY() + radius * sinf(angle);
- point.z = me->GetMap()->GetHeight(me->GetPhaseMask(), point.x, point.y, z + 5.0f);
- path.push_back(point);
- }
- }
-
void UpdateAI(uint32 /*diff*/) override { }
void DoAction(int32 action) override
{
- Movement::MoveSplineInit init(me);
- FillCirclePath(YoggSaronSpawnPos, me->GetDistance2d(YoggSaronSpawnPos.GetPositionX(), YoggSaronSpawnPos.GetPositionY()), me->GetPositionZ(), init.Path(), action != 0);
- init.SetWalk(true);
- init.SetCyclic();
- init.Launch();
+ me->GetMotionMaster()->MoveCirclePath(YoggSaronSpawnPos.GetPositionX(), YoggSaronSpawnPos.GetPositionY(), me->GetPositionZ() + 5.0f, me->GetDistance2d(YoggSaronSpawnPos.GetPositionX(), YoggSaronSpawnPos.GetPositionY()), true, 16);
}
};
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp
index 952e35642d0..49ed9609a03 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp
@@ -16,6 +16,7 @@
*/
#include "InstanceScript.h"
+#include "Vehicle.h"
#include "Player.h"
#include "ScriptedCreature.h"
#include "ScriptMgr.h"
@@ -91,6 +92,7 @@ class instance_ulduar : public InstanceMapScript
// Creatures
ObjectGuid LeviathanGUID;
+ GuidVector LeviathanVehicleGUIDs;
ObjectGuid IgnisGUID;
ObjectGuid RazorscaleGUID;
ObjectGuid RazorscaleController;
@@ -217,6 +219,11 @@ class instance_ulduar : public InstanceMapScript
case NPC_LEVIATHAN:
LeviathanGUID = creature->GetGUID();
break;
+ case NPC_SALVAGED_DEMOLISHER:
+ case NPC_SALVAGED_SIEGE_ENGINE:
+ case NPC_SALVAGED_CHOPPER:
+ LeviathanVehicleGUIDs.push_back(creature->GetGUID());
+ break;
case NPC_IGNIS:
IgnisGUID = creature->GetGUID();
break;
@@ -682,6 +689,24 @@ class instance_ulduar : public InstanceMapScript
switch (type)
{
case BOSS_LEVIATHAN:
+ if (state == DONE)
+ {
+ // Eject all players from vehicles and make them untargetable.
+ // They will be despawned after a while
+ for (auto const& vehicleGuid : LeviathanVehicleGUIDs)
+ {
+ if (Creature* vehicleCreature = instance->GetCreature(vehicleGuid))
+ {
+ if (Vehicle* vehicle = vehicleCreature->GetVehicleKit())
+ {
+ vehicle->RemoveAllPassengers();
+ vehicleCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ vehicleCreature->DespawnOrUnsummon(5 * MINUTE * IN_MILLISECONDS);
+ }
+ }
+ }
+ }
+ break;
case BOSS_IGNIS:
case BOSS_RAZORSCALE:
case BOSS_XT002:
@@ -1143,6 +1168,34 @@ class instance_ulduar : public InstanceMapScript
}
}
+ void UpdateDoorState(GameObject* door) override
+ {
+ // Leviathan doors are set to DOOR_TYPE_ROOM except the one it uses to enter the room
+ // which has to be set to DOOR_TYPE_PASSAGE
+ if (door->GetEntry() == GO_LEVIATHAN_DOOR && door->GetPositionX() > 400.f)
+ door->SetGoState(GetBossState(BOSS_LEVIATHAN) == DONE ? GO_STATE_ACTIVE : GO_STATE_READY);
+ else
+ InstanceScript::UpdateDoorState(door);
+ }
+
+ void AddDoor(GameObject* door, bool add) override
+ {
+ // Leviathan doors are South except the one it uses to enter the room
+ // which is North and should not be used for boundary checks in BossAI::CheckBoundary()
+ if (door->GetEntry() == GO_LEVIATHAN_DOOR && door->GetPositionX() > 400.f)
+ {
+ if (add)
+ GetBossInfo(BOSS_LEVIATHAN)->door[DOOR_TYPE_PASSAGE].insert(door->GetGUID());
+ else
+ GetBossInfo(BOSS_LEVIATHAN)->door[DOOR_TYPE_PASSAGE].erase(door->GetGUID());
+
+ if (add)
+ UpdateDoorState(door);
+ }
+ else
+ InstanceScript::AddDoor(door, add);
+ }
+
private:
EventMap _events;
uint32 _algalonTimer;
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h b/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h
index ddf293dd8b8..d40fb698658 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h
@@ -54,6 +54,7 @@ enum UlduarNPCs
NPC_LEVIATHAN = 33113,
NPC_SALVAGED_DEMOLISHER = 33109,
NPC_SALVAGED_SIEGE_ENGINE = 33060,
+ NPC_SALVAGED_CHOPPER = 33062,
NPC_IGNIS = 33118,
NPC_RAZORSCALE = 33186,
NPC_RAZORSCALE_CONTROLLER = 33233,
diff --git a/src/server/scripts/Northrend/VioletHold/boss_zuramat.cpp b/src/server/scripts/Northrend/VioletHold/boss_zuramat.cpp
index d1df244b733..90fd936e853 100644
--- a/src/server/scripts/Northrend/VioletHold/boss_zuramat.cpp
+++ b/src/server/scripts/Northrend/VioletHold/boss_zuramat.cpp
@@ -26,9 +26,6 @@ enum Spells
SPELL_SUMMON_VOID_SENTRY = 54369,
SPELL_VOID_SHIFT = 54361,
H_SPELL_VOID_SHIFT = 59743,
-
- SPELL_ZURAMAT_ADD_2 = 54342,
- H_SPELL_ZURAMAT_ADD_2 = 59747
};
enum Creatures
@@ -192,12 +189,6 @@ public:
Talk(SAY_SLAY);
}
- void JustSummoned(Creature* summon) override
- {
- summon->AI()->AttackStart(me->GetVictim());
- summon->CastSpell((Unit*)NULL, SPELL_ZURAMAT_ADD_2);
- summon->SetPhaseMask(17, true);
- }
};
};
diff --git a/src/server/scripts/Northrend/VioletHold/instance_violet_hold.cpp b/src/server/scripts/Northrend/VioletHold/instance_violet_hold.cpp
index 3e3ce5cde75..a462c68e084 100644
--- a/src/server/scripts/Northrend/VioletHold/instance_violet_hold.cpp
+++ b/src/server/scripts/Northrend/VioletHold/instance_violet_hold.cpp
@@ -133,6 +133,7 @@ public:
uiCyanigosaEventTimer = 3 * IN_MILLISECONDS;
bActive = false;
+ bWiped = false;
bIsDoorSpellCast = false;
bCrystalActivated = false;
defenseless = true;
diff --git a/src/server/scripts/Northrend/zone_borean_tundra.cpp b/src/server/scripts/Northrend/zone_borean_tundra.cpp
index 9a577516126..4aea36e3fe7 100644
--- a/src/server/scripts/Northrend/zone_borean_tundra.cpp
+++ b/src/server/scripts/Northrend/zone_borean_tundra.cpp
@@ -29,7 +29,6 @@ npc_corastrasza
npc_sinkhole_kill_credit
npc_khunok_the_behemoth
npc_nerubar_victim
-npc_keristrasza
npc_nesingwary_trapper
npc_lurgglbr
npc_nexus_drake_hatchling
@@ -223,48 +222,6 @@ public:
};
/*######
-## npc_keristrasza
-######*/
-
-enum Keristrasza
-{
- SPELL_TELEPORT_TO_SARAGOSA = 46772
-};
-
-#define GOSSIP_HELLO_KERI "I am prepared to face Saragosa!"
-
-class npc_keristrasza : public CreatureScript
-{
-public:
- npc_keristrasza() : CreatureScript("npc_keristrasza") { }
-
- bool OnGossipHello(Player* player, Creature* creature) override
- {
- if (creature->IsQuestGiver())
- player->PrepareQuestMenu(creature->GetGUID());
-
- if (player->GetQuestStatus(11957) == QUEST_STATUS_INCOMPLETE)
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO_KERI, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
-
- player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID());
-
- return true;
- }
-
- bool OnGossipSelect(Player* player, Creature* /*creature*/, uint32 /*sender*/, uint32 action) override
- {
- player->PlayerTalkClass->ClearMenus();
- if (action == GOSSIP_ACTION_INFO_DEF + 1)
- {
- player->CLOSE_GOSSIP_MENU();
- player->CastSpell(player, SPELL_TELEPORT_TO_SARAGOSA, true);
- }
-
- return true;
- }
-};
-
-/*######
## npc_corastrasza
######*/
@@ -438,6 +395,9 @@ enum NesingwaryTrapper
GO_CARIBOU_TRAP_15 = 188008,
SPELL_TRAPPED = 46104,
+
+ // Texts
+ SAY_NESINGWARY_1 = 0
};
#define CaribouTrapsNum 15
@@ -514,7 +474,7 @@ public:
phase = 3;
break;
case 3:
- //Talk(SAY_NESINGWARY_1);
+ Talk(SAY_NESINGWARY_1);
phaseTimer = 2000;
phase = 4;
break;
@@ -2488,7 +2448,6 @@ void AddSC_borean_tundra()
{
new npc_sinkhole_kill_credit();
new npc_khunok_the_behemoth();
- new npc_keristrasza();
new npc_corastrasza();
new npc_iruk();
new npc_nerubar_victim();
diff --git a/src/server/scripts/Northrend/zone_grizzly_hills.cpp b/src/server/scripts/Northrend/zone_grizzly_hills.cpp
index dad71ab0c24..15fa6d836cd 100644
--- a/src/server/scripts/Northrend/zone_grizzly_hills.cpp
+++ b/src/server/scripts/Northrend/zone_grizzly_hills.cpp
@@ -816,6 +816,44 @@ class spell_shredder_delivery : public SpellScriptLoader
}
};
+enum InfectedWorgenBite
+{
+ SPELL_INFECTED_WORGEN_BITE = 53094,
+ SPELL_WORGENS_CALL = 53095
+};
+
+class spell_infected_worgen_bite : public SpellScriptLoader
+{
+ public:
+ spell_infected_worgen_bite() : SpellScriptLoader("spell_infected_worgen_bite") { }
+
+ class spell_infected_worgen_bite_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_infected_worgen_bite_AuraScript);
+
+ void HandleAfterEffectApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
+ {
+ Unit* target = GetTarget();
+ if (target->GetTypeId() == TYPEID_PLAYER)
+ if (GetStackAmount() == GetSpellInfo()->StackAmount)
+ {
+ Remove();
+ target->CastSpell(target, SPELL_WORGENS_CALL, true);
+ }
+ }
+
+ void Register() override
+ {
+ AfterEffectApply += AuraEffectApplyFn(spell_infected_worgen_bite_AuraScript::HandleAfterEffectApply, EFFECT_1, SPELL_AURA_PERIODIC_DAMAGE, AURA_EFFECT_HANDLE_REAPPLY);
+ }
+ };
+
+ AuraScript* GetAuraScript() const override
+ {
+ return new spell_infected_worgen_bite_AuraScript();
+ }
+};
+
void AddSC_grizzly_hills()
{
new npc_emily();
@@ -827,4 +865,5 @@ void AddSC_grizzly_hills()
new npc_venture_co_straggler();
new npc_lake_frog();
new spell_shredder_delivery();
+ new spell_infected_worgen_bite();
}
diff --git a/src/server/scripts/Northrend/zone_storm_peaks.cpp b/src/server/scripts/Northrend/zone_storm_peaks.cpp
index bfdea4a1435..bb1e88ce158 100644
--- a/src/server/scripts/Northrend/zone_storm_peaks.cpp
+++ b/src/server/scripts/Northrend/zone_storm_peaks.cpp
@@ -641,97 +641,6 @@ enum JokkumScriptcast
EVENT_KROLMIR_9 = 24,
};
-class npc_king_jokkum_vehicle : public CreatureScript
-{
-public:
- npc_king_jokkum_vehicle() : CreatureScript("npc_king_jokkum_vehicle") { }
-
- struct npc_king_jokkum_vehicleAI : public VehicleAI
- {
- npc_king_jokkum_vehicleAI(Creature* creature) : VehicleAI(creature)
- {
- pathEnd = false;
- }
-
- void Reset() override
- {
- playerGUID.Clear();
- pathEnd = false;
- }
-
- void OnCharmed(bool /*apply*/) override { }
-
- void PassengerBoarded(Unit* who, int8 /*seat*/, bool apply) override
- {
- if (apply)
- {
- playerGUID = who->GetGUID();
- Talk(SAY_HOLD_ON, who);
- me->CastSpell(who, SPELL_JOKKUM_KILL_CREDIT, true);
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_NPC);
- me->GetMotionMaster()->MovePath(PATH_JOKKUM, false);
- }
- }
-
- void MovementInform(uint32 type, uint32 id) override
- {
- if (type != WAYPOINT_MOTION_TYPE)
- return;
-
- if (pathEnd)
- {
- if (id == 4)
- {
-
- }
- }
- else
- {
- if (id == 19)
- {
- pathEnd = true;
- me->SetFacingTo(0.418879f);
- Talk(SAY_JOKKUM_1);
- if (Player* player = ObjectAccessor::GetPlayer(*me, playerGUID))
- me->CastSpell(player, SPELL_PLAYER_CAST_VERANUS_SUMMON);
- me->CastSpell(me, SPELL_EJECT_ALL_PASSENGERS);
-
- }
- }
- }
-
- void UpdateAI(uint32 diff) override
- {
- if (!pathEnd)
- return;
-
- events.Update(diff);
-
- while (uint32 eventId = events.ExecuteEvent())
- {
- switch (eventId)
- {
- case EVENT_KROLMIR_1:
- Talk(SAY_JOKKUM_2);
- events.ScheduleEvent(EVENT_KROLMIR_2, 4000);
- break;
- }
- }
- }
-
- private:
- EventMap events;
- ObjectGuid playerGUID;
- bool pathEnd;
-
- };
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return new npc_king_jokkum_vehicleAI(creature);
- }
-};
-
class spell_jokkum_scriptcast : public SpellScriptLoader
{
public: spell_jokkum_scriptcast() : SpellScriptLoader("spell_jokkum_scriptcast") { }
@@ -855,7 +764,6 @@ void AddSC_storm_peaks()
new npc_icefang();
new npc_hyldsmeet_protodrake();
new npc_brann_bronzebeard_keystone();
- new npc_king_jokkum_vehicle();
new spell_jokkum_scriptcast();
new spell_veranus_summon();
new spell_close_rift();
diff --git a/src/server/scripts/Outland/BlackTemple/boss_shade_of_akama.cpp b/src/server/scripts/Outland/BlackTemple/boss_shade_of_akama.cpp
index 728b164cc04..e4369f0348d 100644
--- a/src/server/scripts/Outland/BlackTemple/boss_shade_of_akama.cpp
+++ b/src/server/scripts/Outland/BlackTemple/boss_shade_of_akama.cpp
@@ -93,15 +93,12 @@ enum Factions
FACTION_COMBAT = 1868
};
-enum SetData
+enum Actions
{
- SETDATA_DATA = 1,
- SETDATA_RESET = 1,
- SETDATA_CHANNELER_DIED = 2,
- SETDATA_START_SPAWNING = 3,
- SETDATA_STOP_SPAWNING = 4,
- SETDATA_DESPAWN_ALL_SPAWNS = 5,
- SETDATA_START_ATTACK_AKAMA = 6
+ ACTION_CHANNELER_DIED = 1,
+ ACTION_START_SPAWNING = 2,
+ ACTION_STOP_SPAWNING = 3,
+ ACTION_DESPAWN_ALL_SPAWNS = 4,
};
enum Events
@@ -158,12 +155,11 @@ class boss_shade_of_akama : public CreatureScript
public:
boss_shade_of_akama() : CreatureScript("boss_shade_of_akama") { }
- struct boss_shade_of_akamaAI : public ScriptedAI
+ struct boss_shade_of_akamaAI : public BossAI
{
- boss_shade_of_akamaAI(Creature* creature) : ScriptedAI(creature)
+ boss_shade_of_akamaAI(Creature* creature) : BossAI(creature, DATA_SHADE_OF_AKAMA)
{
Initialize();
- instance = creature->GetInstanceScript();
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
}
@@ -177,6 +173,7 @@ public:
void Reset() override
{
+ _Reset();
if (!HasKilledAkamaAndReseting)
{
for (GuidList::const_iterator itr = Channelers.begin(); itr != Channelers.end(); ++itr)
@@ -185,7 +182,7 @@ public:
for (GuidList::const_iterator itr = Spawners.begin(); itr != Spawners.end(); ++itr)
if (Creature* Spawner = ObjectAccessor::GetCreature(*me, *itr))
- Spawner->AI()->SetData(SETDATA_DATA, SETDATA_DESPAWN_ALL_SPAWNS);
+ Spawner->AI()->DoAction(ACTION_DESPAWN_ALL_SPAWNS);
events.ScheduleEvent(EVENT_FIND_CHANNELERS_SPAWNERS, 3000);
events.ScheduleEvent(EVENT_RESET_ENCOUNTER, 5000);
@@ -197,11 +194,6 @@ public:
Initialize();
}
- void JustDied(Unit* /*killer*/) override
- {
- instance->SetBossState(DATA_SHADE_OF_AKAMA, DONE);
- }
-
void EnterCombat(Unit* /*who*/) override { }
void AttackStart(Unit* who) override
@@ -216,9 +208,9 @@ public:
ScriptedAI::AttackStart(who);
}
- void SetData(uint32 data, uint32 value) override
+ void DoAction(int32 actionId) override
{
- if (data == SETDATA_DATA && value == SETDATA_CHANNELER_DIED)
+ if (actionId == ACTION_CHANNELER_DIED)
me->RemoveAuraFromStack(SPELL_SHADE_SOUL_CHANNEL_2);
UpdateSpeed();
@@ -314,7 +306,7 @@ public:
for (GuidList::const_iterator itr = Spawners.begin(); itr != Spawners.end(); ++itr)
if (Creature* Spawner = ObjectAccessor::GetCreature(*me, *itr))
- Spawner->AI()->SetData(SETDATA_DATA, SETDATA_START_SPAWNING);
+ Spawner->AI()->DoAction(ACTION_START_SPAWNING);
break;
}
case EVENT_START_ATTACK_AKAMA:
@@ -353,7 +345,7 @@ public:
for (GuidList::const_iterator itr = Spawners.begin(); itr != Spawners.end(); ++itr)
if (Creature* Spawner = ObjectAccessor::GetCreature(*me, *itr))
- Spawner->AI()->SetData(SETDATA_DATA, SETDATA_DESPAWN_ALL_SPAWNS);
+ Spawner->AI()->DoAction(ACTION_DESPAWN_ALL_SPAWNS);
events.ScheduleEvent(EVENT_FIND_CHANNELERS_SPAWNERS, 10000);
events.ScheduleEvent(EVENT_RESET_ENCOUNTER, 20000);
@@ -378,7 +370,7 @@ public:
for (GuidList::const_iterator itr = Spawners.begin(); itr != Spawners.end(); ++itr)
if (Creature* Spawner = ObjectAccessor::GetCreature(*me, *itr))
- Spawner->AI()->SetData(SETDATA_DATA, SETDATA_STOP_SPAWNING);
+ Spawner->AI()->DoAction(ACTION_STOP_SPAWNING);
}
}
}
@@ -390,8 +382,6 @@ public:
public:
bool HasKilledAkama;
private:
- InstanceScript* instance;
- EventMap events;
GuidList Channelers;
GuidList Spawners;
bool akamaReached;
@@ -433,9 +423,11 @@ public:
void Reset() override
{
me->setFaction(FACTION_FRIENDLY);
- me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
DoCast(me, SPELL_STEALTH);
Initialize();
+
+ if (instance->GetBossState(DATA_SHADE_OF_AKAMA) != DONE)
+ me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
}
void JustDied(Unit* /*killer*/) override
@@ -581,7 +573,7 @@ public:
void JustDied(Unit* /*killer*/) override
{
if (Creature* Shade = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_SHADE_OF_AKAMA)))
- Shade->AI()->SetData(SETDATA_DATA, SETDATA_CHANNELER_DIED);
+ Shade->AI()->DoAction(ACTION_CHANNELER_DIED);
}
void EnterCombat(Unit* /*who*/) override { }
@@ -603,7 +595,7 @@ public:
else
{
me->InterruptSpell(CURRENT_CHANNELED_SPELL);
- Shade->AI()->SetData(SETDATA_DATA, SETDATA_CHANNELER_DIED);
+ Shade->AI()->DoAction(ACTION_CHANNELER_DIED);
}
}
events.ScheduleEvent(EVENT_CHANNEL, 2000);
@@ -663,36 +655,33 @@ public:
Summons.Summon(summon);
}
- void SetData(uint32 data, uint32 value) override
+ void DoAction(int32 actionId) override
{
- if (data == SETDATA_DATA)
- {
- doSpawning = true;
+ doSpawning = true;
- switch (value)
- {
- case SETDATA_START_SPAWNING:
- if (leftSide)
- {
- events.ScheduleEvent(EVENT_SPAWN_WAVE_B, 100);
- events.ScheduleEvent(EVENT_SUMMON_ASHTONGUE_SORCERER, urand(2000, 5000));
- }
- else
- {
- events.ScheduleEvent(EVENT_SPAWN_WAVE_B, 10000);
- events.ScheduleEvent(EVENT_SUMMON_ASHTONGUE_DEFENDER, urand(2000, 5000));
- }
- break;
- case SETDATA_STOP_SPAWNING:
- doSpawning = false;
- break;
- case SETDATA_DESPAWN_ALL_SPAWNS:
- doSpawning = false;
- Summons.DespawnAll();
- break;
- default:
- break;
- }
+ switch (actionId)
+ {
+ case ACTION_START_SPAWNING:
+ if (leftSide)
+ {
+ events.ScheduleEvent(EVENT_SPAWN_WAVE_B, 100);
+ events.ScheduleEvent(EVENT_SUMMON_ASHTONGUE_SORCERER, urand(2000, 5000));
+ }
+ else
+ {
+ events.ScheduleEvent(EVENT_SPAWN_WAVE_B, 10000);
+ events.ScheduleEvent(EVENT_SUMMON_ASHTONGUE_DEFENDER, urand(2000, 5000));
+ }
+ break;
+ case ACTION_STOP_SPAWNING:
+ doSpawning = false;
+ break;
+ case ACTION_DESPAWN_ALL_SPAWNS:
+ doSpawning = false;
+ Summons.DespawnAll();
+ break;
+ default:
+ break;
}
}
@@ -778,23 +767,16 @@ public:
}
}
- summonerGuid.Clear();
Initialize();
}
void JustDied(Unit* /*killer*/) override
{
if (Creature* Shade = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_SHADE_OF_AKAMA)))
- Shade->AI()->SetData(SETDATA_DATA, SETDATA_CHANNELER_DIED);
+ Shade->AI()->DoAction(ACTION_CHANNELER_DIED);
me->DespawnOrUnsummon(5000);
}
- void IsSummonedBy(Unit* /*summoner*/) override
- {
- if (Creature* summoner = (ObjectAccessor::GetCreature((*me), summonerGuid)))
- ENSURE_AI(npc_creature_generator_akama::npc_creature_generator_akamaAI, summoner->AI())->JustSummoned(me);
- }
-
void EnterCombat(Unit* /*who*/) override { }
void AttackStart(Unit* who) override
@@ -824,7 +806,7 @@ public:
else
{
me->InterruptSpell(CURRENT_CHANNELED_SPELL);
- Shade->AI()->SetData(SETDATA_DATA, SETDATA_CHANNELER_DIED);
+ Shade->AI()->DoAction(ACTION_CHANNELER_DIED);
switchToCombat = true;
if (Unit* target = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_AKAMA_SHADE)))
AttackStart(target);
@@ -855,7 +837,6 @@ public:
private:
InstanceScript* instance;
EventMap events;
- ObjectGuid summonerGuid;
bool startedBanishing;
bool switchToCombat;
};
@@ -884,8 +865,6 @@ public:
void Reset() override
{
- summonerGuid.Clear();
-
if (Unit* target = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_AKAMA_SHADE)))
AttackStart(target);
}
@@ -895,12 +874,6 @@ public:
me->DespawnOrUnsummon(5000);
}
- void IsSummonedBy(Unit* /*summoner*/) override
- {
- if (Creature* summoner = (ObjectAccessor::GetCreature((*me), summonerGuid)))
- ENSURE_AI(npc_creature_generator_akama::npc_creature_generator_akamaAI, summoner->AI())->JustSummoned(me);
- }
-
void EnterCombat(Unit* /*who*/) override
{
events.ScheduleEvent(EVENT_HEROIC_STRIKE, 5000);
@@ -947,7 +920,6 @@ public:
private:
InstanceScript* instance;
EventMap events;
- ObjectGuid summonerGuid;
};
CreatureAI* GetAI(Creature* creature) const override
@@ -974,8 +946,6 @@ public:
void Reset() override
{
- summonerGuid.Clear();
-
if (Unit* target = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_AKAMA_SHADE)))
AttackStart(target);
}
@@ -985,12 +955,6 @@ public:
me->DespawnOrUnsummon(5000);
}
- void IsSummonedBy(Unit* /*summoner*/) override
- {
- if (Creature* summoner = (ObjectAccessor::GetCreature((*me), summonerGuid)))
- ENSURE_AI(npc_creature_generator_akama::npc_creature_generator_akamaAI, summoner->AI())->JustSummoned(me);
- }
-
void EnterCombat(Unit* /*who*/) override
{
events.ScheduleEvent(EVENT_DEBILITATING_POISON, urand(500, 2000));
@@ -1027,7 +991,6 @@ public:
private:
InstanceScript* instance;
EventMap events;
- ObjectGuid summonerGuid;
};
CreatureAI* GetAI(Creature* creature) const override
@@ -1054,8 +1017,6 @@ public:
void Reset() override
{
- summonerGuid.Clear();
-
if (Unit* target = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_AKAMA_SHADE)))
AttackStart(target);
}
@@ -1065,12 +1026,6 @@ public:
me->DespawnOrUnsummon(5000);
}
- void IsSummonedBy(Unit* /*summoner*/) override
- {
- if (Creature* summoner = (ObjectAccessor::GetCreature((*me), summonerGuid)))
- ENSURE_AI(npc_creature_generator_akama::npc_creature_generator_akamaAI, summoner->AI())->JustSummoned(me);
- }
-
void EnterCombat(Unit* /*who*/) override
{
events.ScheduleEvent(EVENT_RAIN_OF_FIRE, 18000);
@@ -1107,7 +1062,6 @@ public:
private:
InstanceScript* instance;
EventMap events;
- ObjectGuid summonerGuid;
};
CreatureAI* GetAI(Creature* creature) const override
@@ -1137,7 +1091,6 @@ public:
{
spiritMend = false;
chainHeal = false;
- summonerGuid.Clear();
}
void Reset() override
@@ -1153,12 +1106,6 @@ public:
me->DespawnOrUnsummon(5000);
}
- void IsSummonedBy(Unit* /*summoner*/) override
- {
- if (Creature* summoner = (ObjectAccessor::GetCreature((*me), summonerGuid)))
- ENSURE_AI(npc_creature_generator_akama::npc_creature_generator_akamaAI, summoner->AI())->JustSummoned(me);
- }
-
void EnterCombat(Unit* /*who*/) override
{
events.ScheduleEvent(EVENT_SPIRIT_HEAL, urand (5000, 6000));
@@ -1208,7 +1155,6 @@ public:
private:
InstanceScript* instance;
EventMap events;
- ObjectGuid summonerGuid;
bool spiritMend;
bool chainHeal;
};
diff --git a/src/server/scripts/Outland/TempestKeep/arcatraz/arcatraz.cpp b/src/server/scripts/Outland/TempestKeep/arcatraz/arcatraz.cpp
index 2407f3980de..9ffc151b3b9 100644
--- a/src/server/scripts/Outland/TempestKeep/arcatraz/arcatraz.cpp
+++ b/src/server/scripts/Outland/TempestKeep/arcatraz/arcatraz.cpp
@@ -338,6 +338,13 @@ class npc_warden_mellichar : public CreatureScript
IsRunning = true;
}
+ void JustSummoned(Creature* summon) override
+ {
+ DoZoneInCombat(summon);
+ if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true))
+ summon->AI()->AttackStart(target);
+ }
+
bool CanProgress()
{
if (Phase == 7 && instance->GetData(DATA_WARDEN_4) == DONE)
diff --git a/src/server/scripts/Outland/TempestKeep/arcatraz/boss_harbinger_skyriss.cpp b/src/server/scripts/Outland/TempestKeep/arcatraz/boss_harbinger_skyriss.cpp
index 50b77aac410..213f31b280f 100644
--- a/src/server/scripts/Outland/TempestKeep/arcatraz/boss_harbinger_skyriss.cpp
+++ b/src/server/scripts/Outland/TempestKeep/arcatraz/boss_harbinger_skyriss.cpp
@@ -283,7 +283,10 @@ class boss_harbinger_skyriss_illusion : public CreatureScript
{
boss_harbinger_skyriss_illusionAI(Creature* creature) : ScriptedAI(creature) { }
- void Reset() override { }
+ void Reset() override
+ {
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ }
void EnterCombat(Unit* /*who*/) override { }
};
diff --git a/src/server/scripts/Outland/zone_shadowmoon_valley.cpp b/src/server/scripts/Outland/zone_shadowmoon_valley.cpp
index c661e19a98d..318214978ae 100644
--- a/src/server/scripts/Outland/zone_shadowmoon_valley.cpp
+++ b/src/server/scripts/Outland/zone_shadowmoon_valley.cpp
@@ -31,7 +31,6 @@ npc_enslaved_netherwing_drake
npc_drake_dealer_hurlunk
npcs_flanis_swiftwing_and_kagrosh
npc_karynaku
-npc_overlord_morghor
npc_earthmender_wilda
npc_torloth_the_magnificent
npc_illidari_spawn
@@ -677,331 +676,6 @@ class npc_karynaku : public CreatureScript
};
/*####
-# npc_overlord_morghor
-# this whole script is wrong and needs a rewrite.even the illidan npc used is the wrong one.npc id 23467 may be the correct one
-####*/
-enum OverlordData
-{
- QUEST_LORD_ILLIDAN_STORMRAGE = 11108,
-
- C_ILLIDAN = 22083,
- C_YARZILL = 23141,
-
- SPELL_ONE = 39990, // Red Lightning Bolt
- SPELL_TWO = 41528, // Mark of Stormrage
- SPELL_THREE = 40216, // Dragonaw Faction
- SPELL_FOUR = 42016, // Dragonaw Trasform
-
- OVERLORD_SAY_1 = 0,
- OVERLORD_SAY_2 = 1,
- //OVERLORD_SAY_3 = 2,
- OVERLORD_SAY_4 = 3,
- OVERLORD_SAY_5 = 4,
- OVERLORD_SAY_6 = 5,
-
- OVERLORD_YELL_1 = 6,
- OVERLORD_YELL_2 = 7,
-
- LORD_ILLIDAN_SAY_1 = 0,
- LORD_ILLIDAN_SAY_2 = 1,
- LORD_ILLIDAN_SAY_3 = 2,
- LORD_ILLIDAN_SAY_4 = 3,
- LORD_ILLIDAN_SAY_5 = 4,
- LORD_ILLIDAN_SAY_6 = 5,
- LORD_ILLIDAN_SAY_7 = 6,
-
- YARZILL_THE_MERC_SAY = 0
-};
-
-class npc_overlord_morghor : public CreatureScript
-{
-public:
- npc_overlord_morghor() : CreatureScript("npc_overlord_morghor") { }
-
- bool OnQuestAccept(Player* player, Creature* creature, const Quest *_Quest) override
- {
- if (_Quest->GetQuestId() == QUEST_LORD_ILLIDAN_STORMRAGE)
- {
- ENSURE_AI(npc_overlord_morghor::npc_overlord_morghorAI, creature->AI())->PlayerGUID = player->GetGUID();
- ENSURE_AI(npc_overlord_morghor::npc_overlord_morghorAI, creature->AI())->StartEvent();
- return true;
- }
- return false;
- }
-
- CreatureAI* GetAI(Creature* creature) const override
- {
- return new npc_overlord_morghorAI(creature);
- }
-
- struct npc_overlord_morghorAI : public ScriptedAI
- {
- npc_overlord_morghorAI(Creature* creature) : ScriptedAI(creature)
- {
- Initialize();
- }
-
- void Initialize()
- {
- PlayerGUID.Clear();
- IllidanGUID.Clear();
-
- ConversationTimer = 0;
- Step = 0;
-
- Event = false;
- }
-
- ObjectGuid PlayerGUID;
- ObjectGuid IllidanGUID;
-
- uint32 ConversationTimer;
- uint32 Step;
-
- bool Event;
-
- void Reset() override
- {
- Initialize();
- me->SetUInt32Value(UNIT_NPC_FLAGS, 2);
- }
-
- void StartEvent()
- {
- me->SetUInt32Value(UNIT_NPC_FLAGS, 0);
- me->SetUInt32Value(UNIT_FIELD_BYTES_1, 0);
- Unit* Illidan = me->SummonCreature(C_ILLIDAN, -5107.83f, 602.584f, 85.2393f, 4.92598f, TEMPSUMMON_CORPSE_DESPAWN, 0);
- if (Illidan)
- {
- IllidanGUID = Illidan->GetGUID();
- Illidan->SetVisible(false);
- }
- if (PlayerGUID)
- {
- Player* player = ObjectAccessor::GetPlayer(*me, PlayerGUID);
- if (player)
- Talk(OVERLORD_SAY_1, player);
- }
- ConversationTimer = 4200;
- Step = 0;
- Event = true;
- }
-
- uint32 NextStep(uint32 Step)
- {
- Player* player = ObjectAccessor::GetPlayer(*me, PlayerGUID);
- Creature* Illi = ObjectAccessor::GetCreature(*me, IllidanGUID);
-
- if (!player)
- {
- EnterEvadeMode();
- return 0;
- }
-
- switch (Step)
- {
- case 0:
- return 0;
- break;
- case 1:
- me->GetMotionMaster()->MovePoint(0, -5104.41f, 595.297f, 85.6838f);
- return 9000;
- break;
- case 2:
- Talk(OVERLORD_YELL_1, player);
- return 4500;
- break;
- case 3:
- me->SetInFront(player);
- return 3200;
- break;
- case 4:
- Talk(OVERLORD_SAY_2, player);
- return 2000;
- break;
- case 5:
- if (Illi)
- {
- Illi->SetVisible(true);
- Illi->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- Illi->SetDisplayId(21526);
- }
- return 350;
- break;
- case 6:
- if (Illi)
- {
- Illi->CastSpell(Illi, SPELL_ONE, true);
- Illi->SetTarget(me->GetGUID());
- me->SetTarget(IllidanGUID);
- }
- return 2000;
- break;
- case 7:
- Talk(OVERLORD_YELL_2);
- return 4500;
- break;
- case 8:
- me->SetUInt32Value(UNIT_FIELD_BYTES_1, 8);
- return 2500;
- break;
- case 9:
- // missing text "Lord Illidan, this is the Dragonmaw that I, and others, have told you about. He will lead us to victory!"
- return 5000;
- break;
- case 10:
- if (Illi)
- Illi->AI()->Talk(LORD_ILLIDAN_SAY_1);
- return 5000;
- break;
- case 11:
- Talk(OVERLORD_SAY_4, player);
- return 6000;
- break;
- case 12:
- if (Illi)
- Illi->AI()->Talk(LORD_ILLIDAN_SAY_2);
- return 5500;
- break;
- case 13:
- if (Illi)
- Illi->AI()->Talk(LORD_ILLIDAN_SAY_3);
- return 4000;
- break;
- case 14:
- if (Illi)
- Illi->SetTarget(PlayerGUID);
- return 1500;
- break;
- case 15:
- if (Illi)
- Illi->AI()->Talk(LORD_ILLIDAN_SAY_4);
- return 1500;
- break;
- case 16:
- if (Illi)
- Illi->CastSpell(player, SPELL_TWO, true);
- player->RemoveAurasDueToSpell(SPELL_THREE);
- player->RemoveAurasDueToSpell(SPELL_FOUR);
- return 5000;
- break;
- case 17:
- if (Illi)
- Illi->AI()->Talk(LORD_ILLIDAN_SAY_5);
- return 5000;
- break;
- case 18:
- if (Illi)
- Illi->AI()->Talk(LORD_ILLIDAN_SAY_6);
- return 5000;
- break;
- case 19:
- if (Illi)
- Illi->AI()->Talk(LORD_ILLIDAN_SAY_7);
- return 5000;
- break;
- case 20:
- if (Illi)
- {
- Illi->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF);
- Illi->SetDisableGravity(true);
- }
- return 500;
- break;
- case 21:
- Talk(OVERLORD_SAY_5);
- return 500;
- break;
- case 22:
- if (Illi)
- {
- Illi->SetVisible(false);
- Illi->setDeathState(JUST_DIED);
- }
- return 1000;
- break;
- case 23:
- me->SetUInt32Value(UNIT_FIELD_BYTES_1, 0);
- return 2000;
- break;
- case 24:
- me->SetTarget(PlayerGUID);
- return 5000;
- break;
- case 25:
- Talk(OVERLORD_SAY_6);
- return 2000;
- break;
- case 26:
- player->GroupEventHappens(QUEST_LORD_ILLIDAN_STORMRAGE, me);
- return 6000;
- break;
- case 27:
- {
- Unit* Yarzill = me->FindNearestCreature(C_YARZILL, 50.0f);
- if (Yarzill)
- Yarzill->SetTarget(PlayerGUID);
- return 500;
- }
- break;
- case 28:
- player->RemoveAurasDueToSpell(SPELL_TWO);
- player->RemoveAurasDueToSpell(41519);
- player->CastSpell(player, SPELL_THREE, true);
- player->CastSpell(player, SPELL_FOUR, true);
- return 1000;
- break;
- case 29:
- {
- if (Creature* Yarzill = me->FindNearestCreature(C_YARZILL, 50.0f))
- Yarzill->AI()->Talk(YARZILL_THE_MERC_SAY, player);
- return 5000;
- }
- break;
- case 30:
- {
- if (Creature* Yarzill = me->FindNearestCreature(C_YARZILL, 50.0f))
- Yarzill->SetTarget(ObjectGuid::Empty);
- return 5000;
- }
- break;
- case 31:
- {
- if (Creature* Yarzill = me->FindNearestCreature(C_YARZILL, 50.0f))
- Yarzill->CastSpell(player, 41540, true);
- return 1000;
- }
- break;
- case 32:
- me->GetMotionMaster()->MovePoint(0, -5085.77f, 577.231f, 86.6719f);
- return 5000;
- break;
- case 33:
- me->SetTarget(ObjectGuid::Empty);
- Reset();
- return 100;
- break;
- default :
- return 0;
- break;
- }
- }
-
- void UpdateAI(uint32 diff) override
- {
- if (!ConversationTimer)
- return;
-
- if (ConversationTimer <= diff)
- {
- if (Event && PlayerGUID)
- ConversationTimer = NextStep(++Step);
- } else ConversationTimer -= diff;
- }
- };
-};
-
-/*####
# npc_earthmender_wilda
####*/
@@ -2026,7 +1700,6 @@ void AddSC_shadowmoon_valley()
new npc_drake_dealer_hurlunk();
new npcs_flanis_swiftwing_and_kagrosh();
new npc_karynaku();
- new npc_overlord_morghor();
new npc_earthmender_wilda();
new npc_lord_illidan_stormrage();
new go_crystal_prison();
diff --git a/src/server/scripts/Spells/spell_generic.cpp b/src/server/scripts/Spells/spell_generic.cpp
index ee70cca2e50..993e64f22dc 100644
--- a/src/server/scripts/Spells/spell_generic.cpp
+++ b/src/server/scripts/Spells/spell_generic.cpp
@@ -3629,6 +3629,43 @@ class spell_gen_eject_all_passengers : public SpellScriptLoader
}
};
+class spell_gen_eject_passenger : public SpellScriptLoader
+{
+ public:
+ spell_gen_eject_passenger() : SpellScriptLoader("spell_gen_eject_passenger") { }
+
+ class spell_gen_eject_passenger_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_gen_eject_passenger_SpellScript);
+
+ bool Validate(SpellInfo const* spellInfo) override
+ {
+ if (spellInfo->Effects[EFFECT_0].CalcValue() < 1)
+ return false;
+ return true;
+ }
+
+ void EjectPassenger(SpellEffIndex /*effIndex*/)
+ {
+ if (Vehicle* vehicle = GetHitUnit()->GetVehicleKit())
+ {
+ if (Unit* passenger = vehicle->GetPassenger(GetEffectValue() - 1))
+ passenger->ExitVehicle();
+ }
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_gen_eject_passenger_SpellScript::EjectPassenger, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
+ };
+
+ SpellScript* GetSpellScript() const override
+ {
+ return new spell_gen_eject_passenger_SpellScript();
+ }
+};
+
enum GMFreeze
{
SPELL_GM_FREEZE = 9454
@@ -4121,6 +4158,7 @@ void AddSC_generic_spell_scripts()
new spell_gen_wg_water();
new spell_gen_whisper_gulch_yogg_saron_whisper();
new spell_gen_eject_all_passengers();
+ new spell_gen_eject_passenger();
new spell_gen_gm_freeze();
new spell_gen_stand();
new spell_gen_mixology_bonus();
diff --git a/src/server/scripts/Spells/spell_quest.cpp b/src/server/scripts/Spells/spell_quest.cpp
index 629630d0bef..d98ef2ec799 100644
--- a/src/server/scripts/Spells/spell_quest.cpp
+++ b/src/server/scripts/Spells/spell_quest.cpp
@@ -2422,6 +2422,36 @@ class spell_q10929_fumping : SpellScriptLoader
}
};
+class spell_q12414_hand_over_reins : public SpellScriptLoader
+{
+ public:
+ spell_q12414_hand_over_reins() : SpellScriptLoader("spell_q12414_hand_over_reins") { }
+
+ class spell_q12414_hand_over_reins_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_q12414_hand_over_reins_SpellScript);
+
+ void HandleScript(SpellEffIndex /*effIndex*/)
+ {
+ Creature* caster = GetCaster()->ToCreature();
+ GetHitUnit()->ExitVehicle();
+
+ if (caster)
+ caster->DespawnOrUnsummon();
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_q12414_hand_over_reins_SpellScript::HandleScript, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
+ };
+
+ SpellScript* GetSpellScript() const override
+ {
+ return new spell_q12414_hand_over_reins_SpellScript();
+ }
+};
+
void AddSC_quest_spell_scripts()
{
new spell_q55_sacred_cleansing();
@@ -2480,4 +2510,5 @@ void AddSC_quest_spell_scripts()
new spell_q13400_illidan_kill_master();
new spell_q14100_q14111_make_player_destroy_totems();
new spell_q10929_fumping();
+ new spell_q12414_hand_over_reins();
}
diff --git a/src/server/shared/CMakeLists.txt b/src/server/shared/CMakeLists.txt
index fb86ac7db18..abc019863b1 100644
--- a/src/server/shared/CMakeLists.txt
+++ b/src/server/shared/CMakeLists.txt
@@ -21,6 +21,7 @@ file(GLOB_RECURSE sources_Logging Logging/*.cpp Logging/*.h)
file(GLOB_RECURSE sources_Networking Networking/*.cpp Networking/*.h)
file(GLOB_RECURSE sources_Packets Packets/*.cpp Packets/*.h)
file(GLOB_RECURSE sources_Threading Threading/*.cpp Threading/*.h)
+file(GLOB_RECURSE sources_Updater Updater/*.cpp Updater/*.h)
file(GLOB_RECURSE sources_Utilities Utilities/*.cpp Utilities/*.h)
file(GLOB sources_localdir *.cpp *.h)
@@ -51,6 +52,7 @@ set(shared_STAT_SRCS
${sources_Networking}
${sources_Packets}
${sources_Threading}
+ ${sources_Updater}
${sources_Utilities}
${sources_localdir}
)
@@ -59,8 +61,9 @@ include_directories(
${CMAKE_BINARY_DIR}
${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour
${CMAKE_SOURCE_DIR}/dep/SFMT
- ${CMAKE_SOURCE_DIR}/dep/sockets/include
+ ${CMAKE_SOURCE_DIR}/dep/cppformat
${CMAKE_SOURCE_DIR}/dep/utf8cpp
+ ${CMAKE_SOURCE_DIR}/dep/process
${CMAKE_SOURCE_DIR}/src/server
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/Configuration
@@ -74,12 +77,15 @@ include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/Packets
${CMAKE_CURRENT_SOURCE_DIR}/Threading
${CMAKE_CURRENT_SOURCE_DIR}/Utilities
+ ${CMAKE_CURRENT_SOURCE_DIR}/Updater
${CMAKE_SOURCE_DIR}/src/server/game/Entities/Object
${MYSQL_INCLUDE_DIR}
${OPENSSL_INCLUDE_DIR}
${VALGRIND_INCLUDE_DIR}
)
+GroupSources(${CMAKE_CURRENT_SOURCE_DIR})
+
add_library(shared STATIC
${shared_STAT_SRCS}
${shared_STAT_PCH_SRC}
diff --git a/src/server/shared/Configuration/Config.cpp b/src/server/shared/Configuration/Config.cpp
index 1e1f8c7c3c6..ea426a5d33e 100644
--- a/src/server/shared/Configuration/Config.cpp
+++ b/src/server/shared/Configuration/Config.cpp
@@ -21,7 +21,6 @@
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/ini_parser.hpp>
#include "Config.h"
-#include "Errors.h"
using namespace boost::property_tree;
diff --git a/src/server/shared/Cryptography/ARC4.cpp b/src/server/shared/Cryptography/ARC4.cpp
index 28c3da8d228..d1082b39347 100644
--- a/src/server/shared/Cryptography/ARC4.cpp
+++ b/src/server/shared/Cryptography/ARC4.cpp
@@ -17,7 +17,6 @@
*/
#include "ARC4.h"
-#include <openssl/sha.h>
ARC4::ARC4(uint8 len) : m_ctx()
{
diff --git a/src/server/shared/Cryptography/BigNumber.cpp b/src/server/shared/Cryptography/BigNumber.cpp
index 434268097fe..720e8e30441 100644
--- a/src/server/shared/Cryptography/BigNumber.cpp
+++ b/src/server/shared/Cryptography/BigNumber.cpp
@@ -18,7 +18,6 @@
#include "Cryptography/BigNumber.h"
#include <openssl/bn.h>
-#include <openssl/crypto.h>
#include <cstring>
#include <algorithm>
#include <memory>
@@ -171,19 +170,20 @@ bool BigNumber::isZero() const
std::unique_ptr<uint8[]> BigNumber::AsByteArray(int32 minSize, bool littleEndian)
{
- int length = (minSize >= GetNumBytes()) ? minSize : GetNumBytes();
+ int numBytes = GetNumBytes();
+ int length = (minSize >= numBytes) ? minSize : numBytes;
uint8* array = new uint8[length];
// If we need more bytes than length of BigNumber set the rest to 0
- if (length > GetNumBytes())
+ if (length > numBytes)
memset((void*)array, 0, length);
BN_bn2bin(_bn, (unsigned char *)array);
// openssl's BN stores data internally in big endian format, reverse if little endian desired
if (littleEndian)
- std::reverse(array, array + length);
+ std::reverse(array, array + numBytes);
std::unique_ptr<uint8[]> ret(array);
return ret;
diff --git a/src/server/shared/Database/DatabaseLoader.cpp b/src/server/shared/Database/DatabaseLoader.cpp
new file mode 100644
index 00000000000..36ee4b12c83
--- /dev/null
+++ b/src/server/shared/Database/DatabaseLoader.cpp
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "DatabaseLoader.h"
+#include "DBUpdater.h"
+#include "Config.h"
+
+#include <mysqld_error.h>
+
+DatabaseLoader::DatabaseLoader(std::string const& logger, uint32 const defaultUpdateMask)
+ : _logger(logger), _autoSetup(sConfigMgr->GetBoolDefault("Updates.AutoSetup", true)),
+ _updateFlags(sConfigMgr->GetIntDefault("Updates.EnableDatabases", defaultUpdateMask))
+{
+}
+
+template <class T>
+DatabaseLoader& DatabaseLoader::AddDatabase(DatabaseWorkerPool<T>& pool, std::string const& name)
+{
+ bool const updatesEnabledForThis = DBUpdater<T>::IsEnabled(_updateFlags);
+
+ _open.push(std::make_pair([this, name, updatesEnabledForThis, &pool]() -> bool
+ {
+ std::string const dbString = sConfigMgr->GetStringDefault(name + "DatabaseInfo", "");
+ if (dbString.empty())
+ {
+ TC_LOG_ERROR(_logger.c_str(), "Database %s not specified in configuration file!", name.c_str());
+ return false;
+ }
+
+ uint8 const asyncThreads = uint8(sConfigMgr->GetIntDefault(name + "Database.WorkerThreads", 1));
+ if (asyncThreads < 1 || asyncThreads > 32)
+ {
+ TC_LOG_ERROR(_logger.c_str(), "%s database: invalid number of worker threads specified. "
+ "Please pick a value between 1 and 32.", name.c_str());
+ return false;
+ }
+
+ uint8 const synchThreads = uint8(sConfigMgr->GetIntDefault(name + "Database.SynchThreads", 1));
+
+ pool.SetConnectionInfo(dbString, asyncThreads, synchThreads);
+ if (uint32 error = pool.Open())
+ {
+ // Database does not exist
+ if ((error == ER_BAD_DB_ERROR) && updatesEnabledForThis && _autoSetup)
+ {
+ // Try to create the database and connect again if auto setup is enabled
+ if (DBUpdater<T>::Create(pool) && (!pool.Open()))
+ error = 0;
+ }
+
+ // If the error wasn't handled quit
+ if (error)
+ {
+ TC_LOG_ERROR("sql.driver", "\nDatabasePool %s NOT opened. There were errors opening the MySQL connections. Check your SQLDriverLogFile "
+ "for specific errors. Read wiki at http://collab.kpsn.org/display/tc/TrinityCore+Home", name.c_str());
+
+ return false;
+ }
+ }
+ return true;
+ },
+ [&pool]()
+ {
+ pool.Close();
+ }));
+
+ // Populate and update only if updates are enabled for this pool
+ if (updatesEnabledForThis)
+ {
+ _populate.push([this, name, &pool]() -> bool
+ {
+ if (!DBUpdater<T>::Populate(pool))
+ {
+ TC_LOG_ERROR(_logger.c_str(), "Could not populate the %s database, see log for details.", name.c_str());
+ return false;
+ }
+ return true;
+ });
+
+ _update.push([this, name, &pool]() -> bool
+ {
+ if (!DBUpdater<T>::Update(pool))
+ {
+ TC_LOG_ERROR(_logger.c_str(), "Could not update the %s database, see log for details.", name.c_str());
+ return false;
+ }
+ return true;
+ });
+ }
+
+ _prepare.push([this, name, &pool]() -> bool
+ {
+ if (!pool.PrepareStatements())
+ {
+ TC_LOG_ERROR(_logger.c_str(), "Could not prepare statements of the %s database, see log for details.", name.c_str());
+ return false;
+ }
+ return true;
+ });
+
+ return *this;
+}
+
+bool DatabaseLoader::Load()
+{
+ if (!OpenDatabases())
+ return false;
+
+ if (!PopulateDatabases())
+ return false;
+
+ if (!UpdateDatabases())
+ return false;
+
+ if (!PrepareStatements())
+ return false;
+
+ return true;
+}
+
+bool DatabaseLoader::OpenDatabases()
+{
+ while (!_open.empty())
+ {
+ std::pair<Predicate, std::function<void()>> const load = _open.top();
+ if (load.first())
+ _close.push(load.second);
+ else
+ {
+ // Close all loaded databases
+ while (!_close.empty())
+ {
+ _close.top()();
+ _close.pop();
+ }
+ return false;
+ }
+
+ _open.pop();
+ }
+ return true;
+}
+
+// Processes the elements of the given stack until a predicate returned false.
+bool DatabaseLoader::Process(std::stack<Predicate>& stack)
+{
+ while (!stack.empty())
+ {
+ if (!stack.top()())
+ return false;
+
+ stack.pop();
+ }
+ return true;
+}
+
+bool DatabaseLoader::PopulateDatabases()
+{
+ return Process(_populate);
+}
+
+bool DatabaseLoader::UpdateDatabases()
+{
+ return Process(_update);
+}
+
+bool DatabaseLoader::PrepareStatements()
+{
+ return Process(_prepare);
+}
+
+template
+DatabaseLoader& DatabaseLoader::AddDatabase<LoginDatabaseConnection>(DatabaseWorkerPool<LoginDatabaseConnection>& pool, std::string const& name);
+template
+DatabaseLoader& DatabaseLoader::AddDatabase<WorldDatabaseConnection>(DatabaseWorkerPool<WorldDatabaseConnection>& pool, std::string const& name);
+template
+DatabaseLoader& DatabaseLoader::AddDatabase<CharacterDatabaseConnection>(DatabaseWorkerPool<CharacterDatabaseConnection>& pool, std::string const& name);
diff --git a/src/server/shared/Database/DatabaseLoader.h b/src/server/shared/Database/DatabaseLoader.h
new file mode 100644
index 00000000000..d35597ba807
--- /dev/null
+++ b/src/server/shared/Database/DatabaseLoader.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef DatabaseLoader_h__
+#define DatabaseLoader_h__
+
+#include "DatabaseWorkerPool.h"
+#include "DatabaseEnv.h"
+
+#include <stack>
+#include <functional>
+
+// A helper class to initiate all database worker pools,
+// handles updating, delays preparing of statements and cleans up on failure.
+class DatabaseLoader
+{
+public:
+ DatabaseLoader(std::string const& logger, uint32 const defaultUpdateMask);
+
+ // Register a database to the loader (lazy implemented)
+ template <class T>
+ DatabaseLoader& AddDatabase(DatabaseWorkerPool<T>& pool, std::string const& name);
+
+ // Load all databases
+ bool Load();
+
+ enum DatabaseTypeFlags
+ {
+ DATABASE_NONE = 0,
+
+ DATABASE_LOGIN = 1,
+ DATABASE_CHARACTER = 2,
+ DATABASE_WORLD = 4,
+
+ DATABASE_MASK_ALL = DATABASE_LOGIN | DATABASE_CHARACTER | DATABASE_WORLD
+ };
+
+private:
+ bool OpenDatabases();
+ bool PopulateDatabases();
+ bool UpdateDatabases();
+ bool PrepareStatements();
+
+ using Predicate = std::function<bool()>;
+
+ static bool Process(std::stack<Predicate>& stack);
+
+ std::string const _logger;
+ bool const _autoSetup;
+ uint32 const _updateFlags;
+
+ std::stack<std::pair<Predicate, std::function<void()>>> _open;
+ std::stack<std::function<void()>> _close;
+ std::stack<Predicate> _populate, _update, _prepare;
+};
+
+#endif // DatabaseLoader_h__
diff --git a/src/server/shared/Database/DatabaseWorker.cpp b/src/server/shared/Database/DatabaseWorker.cpp
index 1fe638552a0..56757ce12a0 100644
--- a/src/server/shared/Database/DatabaseWorker.cpp
+++ b/src/server/shared/Database/DatabaseWorker.cpp
@@ -18,8 +18,6 @@
#include "DatabaseEnv.h"
#include "DatabaseWorker.h"
#include "SQLOperation.h"
-#include "MySQLConnection.h"
-#include "MySQLThreading.h"
#include "ProducerConsumerQueue.h"
DatabaseWorker::DatabaseWorker(ProducerConsumerQueue<SQLOperation*>* newQueue, MySQLConnection* connection)
diff --git a/src/server/shared/Database/DatabaseWorkerPool.h b/src/server/shared/Database/DatabaseWorkerPool.h
index f0ddbe91ad8..6bc204fbf76 100644
--- a/src/server/shared/Database/DatabaseWorkerPool.h
+++ b/src/server/shared/Database/DatabaseWorkerPool.h
@@ -28,8 +28,10 @@
#include "QueryResult.h"
#include "QueryHolder.h"
#include "AdhocStatement.h"
+#include "StringFormat.h"
#include <mysqld_error.h>
+#include <memory>
#define MIN_MYSQL_SERVER_VERSION 50100u
#define MIN_MYSQL_CLIENT_VERSION 50100u
@@ -57,9 +59,9 @@ class DatabaseWorkerPool
public:
/* Activity state */
- DatabaseWorkerPool() : _connectionInfo(NULL)
+ DatabaseWorkerPool() : _queue(new ProducerConsumerQueue<SQLOperation*>()),
+ _async_threads(0), _synch_threads(0)
{
- _queue = new ProducerConsumerQueue<SQLOperation*>();
memset(_connectionCount, 0, sizeof(_connectionCount));
_connections.resize(IDX_SIZE);
@@ -70,31 +72,37 @@ class DatabaseWorkerPool
~DatabaseWorkerPool()
{
_queue->Cancel();
+ }
- delete _queue;
+ void SetConnectionInfo(std::string const& infoString, uint8 const asyncThreads, uint8 const synchThreads)
+ {
+ _connectionInfo.reset(new MySQLConnectionInfo(infoString));
- delete _connectionInfo;
+ _async_threads = asyncThreads;
+ _synch_threads = synchThreads;
}
- bool Open(const std::string& infoString, uint8 async_threads, uint8 synch_threads)
+ uint32 Open()
{
- _connectionInfo = new MySQLConnectionInfo(infoString);
+ WPFatal(_connectionInfo.get(), "Connection info was not set!");
TC_LOG_INFO("sql.driver", "Opening DatabasePool '%s'. Asynchronous connections: %u, synchronous connections: %u.",
- GetDatabaseName(), async_threads, synch_threads);
+ GetDatabaseName(), _async_threads, _synch_threads);
- bool res = OpenConnections(IDX_ASYNC, async_threads);
+ uint32 error = OpenConnections(IDX_ASYNC, _async_threads);
- if (!res)
- return res;
+ if (error)
+ return error;
- res = OpenConnections(IDX_SYNCH, synch_threads);
+ error = OpenConnections(IDX_SYNCH, _synch_threads);
- if (res)
+ if (!error)
+ {
TC_LOG_INFO("sql.driver", "DatabasePool '%s' opened successfully. %u total connections running.", GetDatabaseName(),
(_connectionCount[IDX_SYNCH] + _connectionCount[IDX_ASYNC]));
+ }
- return res;
+ return error;
}
void Close()
@@ -120,6 +128,32 @@ class DatabaseWorkerPool
TC_LOG_INFO("sql.driver", "All connections on DatabasePool '%s' closed.", GetDatabaseName());
}
+ //! Prepares all prepared statements
+ bool PrepareStatements()
+ {
+ for (uint8 i = 0; i < IDX_SIZE; ++i)
+ for (uint32 c = 0; c < _connectionCount[i]; ++c)
+ {
+ T* t = _connections[i][c];
+ t->LockIfReady();
+ if (!t->PrepareStatements())
+ {
+ t->Unlock();
+ Close();
+ return false;
+ }
+ else
+ t->Unlock();
+ }
+
+ return true;
+ }
+
+ inline MySQLConnectionInfo const* GetConnectionInfo() const
+ {
+ return _connectionInfo.get();
+ }
+
/**
Delayed one-way statement methods.
*/
@@ -137,18 +171,13 @@ class DatabaseWorkerPool
//! Enqueues a one-way SQL operation in string format -with variable args- that will be executed asynchronously.
//! This method should only be used for queries that are only executed once, e.g during startup.
- void PExecute(const char* sql, ...)
+ template<typename... Args>
+ void PExecute(const char* sql, Args const&... args)
{
if (!sql)
return;
- va_list ap;
- char szQuery[MAX_QUERY_LEN];
- va_start(ap, sql);
- vsnprintf(szQuery, MAX_QUERY_LEN, sql, ap);
- va_end(ap);
-
- Execute(szQuery);
+ Execute(Trinity::StringFormat(sql, args...).c_str());
}
//! Enqueues a one-way SQL operation in prepared statement format that will be executed asynchronously.
@@ -177,18 +206,13 @@ class DatabaseWorkerPool
//! Directly executes a one-way SQL operation in string format -with variable args-, that will block the calling thread until finished.
//! This method should only be used for queries that are only executed once, e.g during startup.
- void DirectPExecute(const char* sql, ...)
+ template<typename... Args>
+ void DirectPExecute(const char* sql, Args const&... args)
{
if (!sql)
return;
- va_list ap;
- char szQuery[MAX_QUERY_LEN];
- va_start(ap, sql);
- vsnprintf(szQuery, MAX_QUERY_LEN, sql, ap);
- va_end(ap);
-
- return DirectExecute(szQuery);
+ DirectExecute(Trinity::StringFormat(sql, args...).c_str());
}
//! Directly executes a one-way SQL operation in prepared statement format, that will block the calling thread until finished.
@@ -227,34 +251,24 @@ class DatabaseWorkerPool
//! Directly executes an SQL query in string format -with variable args- that will block the calling thread until finished.
//! Returns reference counted auto pointer, no need for manual memory management in upper level code.
- QueryResult PQuery(const char* sql, T* conn, ...)
+ template<typename... Args>
+ QueryResult PQuery(const char* sql, T* conn, Args const&... args)
{
if (!sql)
return QueryResult(NULL);
- va_list ap;
- char szQuery[MAX_QUERY_LEN];
- va_start(ap, conn);
- vsnprintf(szQuery, MAX_QUERY_LEN, sql, ap);
- va_end(ap);
-
- return Query(szQuery, conn);
+ return Query(Trinity::StringFormat(sql, args...).c_str(), conn);
}
//! Directly executes an SQL query in string format -with variable args- that will block the calling thread until finished.
//! Returns reference counted auto pointer, no need for manual memory management in upper level code.
- QueryResult PQuery(const char* sql, ...)
+ template<typename... Args>
+ QueryResult PQuery(const char* sql, Args const&... args)
{
if (!sql)
return QueryResult(NULL);
- va_list ap;
- char szQuery[MAX_QUERY_LEN];
- va_start(ap, sql);
- vsnprintf(szQuery, MAX_QUERY_LEN, sql, ap);
- va_end(ap);
-
- return Query(szQuery);
+ return Query(Trinity::StringFormat(sql, args...).c_str());
}
//! Directly executes an SQL query in prepared format that will block the calling thread until finished.
@@ -295,15 +309,10 @@ class DatabaseWorkerPool
//! Enqueues a query in string format -with variable args- that will set the value of the QueryResultFuture return object as soon as the query is executed.
//! The return value is then processed in ProcessQueryCallback methods.
- QueryResultFuture AsyncPQuery(const char* sql, ...)
+ template<typename... Args>
+ QueryResultFuture AsyncPQuery(const char* sql, Args const&... args)
{
- va_list ap;
- char szQuery[MAX_QUERY_LEN];
- va_start(ap, sql);
- vsnprintf(szQuery, MAX_QUERY_LEN, sql, ap);
- va_end(ap);
-
- return AsyncQuery(szQuery);
+ return AsyncQuery(Trinity::StringFormat(sql, args...).c_str());
}
//! Enqueues a query in prepared format that will set the value of the PreparedQueryResultFuture return object as soon as the query is executed.
@@ -461,7 +470,7 @@ class DatabaseWorkerPool
}
private:
- bool OpenConnections(InternalIndex type, uint8 numConnections)
+ uint32 OpenConnections(InternalIndex type, uint8 numConnections)
{
_connections[type].resize(numConnections);
for (uint8 i = 0; i < numConnections; ++i)
@@ -469,7 +478,7 @@ class DatabaseWorkerPool
T* t;
if (type == IDX_ASYNC)
- t = new T(_queue, *_connectionInfo);
+ t = new T(_queue.get(), *_connectionInfo);
else if (type == IDX_SYNCH)
t = new T(*_connectionInfo);
else
@@ -478,35 +487,32 @@ class DatabaseWorkerPool
_connections[type][i] = t;
++_connectionCount[type];
- bool res = t->Open();
+ uint32 error = t->Open();
- if (res)
+ if (!error)
{
if (mysql_get_server_version(t->GetHandle()) < MIN_MYSQL_SERVER_VERSION)
{
TC_LOG_ERROR("sql.driver", "TrinityCore does not support MySQL versions below 5.1");
- res = false;
+ error = 1;
}
}
// Failed to open a connection or invalid version, abort and cleanup
- if (!res)
+ if (error)
{
- TC_LOG_ERROR("sql.driver", "DatabasePool %s NOT opened. There were errors opening the MySQL connections. Check your SQLDriverLogFile "
- "for specific errors. Read wiki at http://collab.kpsn.org/display/tc/TrinityCore+Home", GetDatabaseName());
-
while (_connectionCount[type] != 0)
{
T* t = _connections[type][i--];
delete t;
--_connectionCount[type];
}
-
- return false;
+ return error;
}
}
- return true;
+ // Everything is fine
+ return 0;
}
unsigned long EscapeString(char *to, const char *from, unsigned long length)
@@ -546,10 +552,13 @@ class DatabaseWorkerPool
return _connectionInfo->database.c_str();
}
- ProducerConsumerQueue<SQLOperation*>* _queue; //! Queue shared by async worker threads.
- std::vector< std::vector<T*> > _connections;
- uint32 _connectionCount[2]; //! Counter of MySQL connections;
- MySQLConnectionInfo* _connectionInfo;
+ //! Queue shared by async worker threads.
+ std::unique_ptr<ProducerConsumerQueue<SQLOperation*>> _queue;
+ std::vector<std::vector<T*>> _connections;
+ //! Counter of MySQL connections;
+ uint32 _connectionCount[IDX_SIZE];
+ std::unique_ptr<MySQLConnectionInfo> _connectionInfo;
+ uint8 _async_threads, _synch_threads;
};
#endif
diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.cpp b/src/server/shared/Database/Implementation/CharacterDatabase.cpp
index 265b0578841..c8632b8a3c2 100644
--- a/src/server/shared/Database/Implementation/CharacterDatabase.cpp
+++ b/src/server/shared/Database/Implementation/CharacterDatabase.cpp
@@ -60,7 +60,8 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_SEL_CHAR_POSITION_XYZ, "SELECT map, position_x, position_y, position_z FROM characters WHERE guid = ?", CONNECTION_SYNCH);
PrepareStatement(CHAR_SEL_CHAR_POSITION, "SELECT position_x, position_y, position_z, orientation, map, taxi_path FROM characters WHERE guid = ?", CONNECTION_SYNCH);
- PrepareStatement(CHAR_DEL_BATTLEGROUND_RANDOM, "DELETE FROM character_battleground_random", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_DEL_BATTLEGROUND_RANDOM_ALL, "DELETE FROM character_battleground_random", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_DEL_BATTLEGROUND_RANDOM, "DELETE FROM character_battleground_random WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_INS_BATTLEGROUND_RANDOM, "INSERT INTO character_battleground_random (guid) VALUES (?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_CHARACTER, "SELECT guid, account, name, race, class, gender, level, xp, money, playerBytes, playerBytes2, playerFlags, "
@@ -300,6 +301,7 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_DEL_ARENA_TEAM_MEMBER, "DELETE FROM arena_team_member WHERE arenaTeamId = ? AND guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_UPD_ARENA_TEAM_STATS, "UPDATE arena_team SET rating = ?, weekGames = ?, weekWins = ?, seasonGames = ?, seasonWins = ?, rank = ? WHERE arenaTeamId = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_UPD_ARENA_TEAM_MEMBER, "UPDATE arena_team_member SET personalRating = ?, weekGames = ?, weekWins = ?, seasonGames = ?, seasonWins = ? WHERE arenaTeamId = ? AND guid = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_DEL_CHARACTER_ARENA_STATS, "DELETE FROM character_arena_stats WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_REP_CHARACTER_ARENA_STATS, "REPLACE INTO character_arena_stats (guid, slot, matchMakerRating) VALUES (?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_PLAYER_ARENA_TEAMS, "SELECT arena_team_member.arenaTeamId FROM arena_team_member JOIN arena_team ON arena_team_member.arenaTeamId = arena_team.arenaTeamId WHERE guid = ?", CONNECTION_SYNCH);
PrepareStatement(CHAR_UPD_ARENA_TEAM_NAME, "UPDATE arena_team SET name = ? WHERE arenaTeamId = ?", CONNECTION_ASYNC);
diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.h b/src/server/shared/Database/Implementation/CharacterDatabase.h
index f7ff5b9186e..e56a24d6865 100644
--- a/src/server/shared/Database/Implementation/CharacterDatabase.h
+++ b/src/server/shared/Database/Implementation/CharacterDatabase.h
@@ -72,6 +72,7 @@ enum CharacterDatabaseStatements
CHAR_SEL_CHAR_POSITION_XYZ,
CHAR_SEL_CHAR_POSITION,
+ CHAR_DEL_BATTLEGROUND_RANDOM_ALL,
CHAR_DEL_BATTLEGROUND_RANDOM,
CHAR_INS_BATTLEGROUND_RANDOM,
@@ -253,6 +254,7 @@ enum CharacterDatabaseStatements
CHAR_DEL_ARENA_TEAM_MEMBER,
CHAR_UPD_ARENA_TEAM_STATS,
CHAR_UPD_ARENA_TEAM_MEMBER,
+ CHAR_DEL_CHARACTER_ARENA_STATS,
CHAR_REP_CHARACTER_ARENA_STATS,
CHAR_SEL_PLAYER_ARENA_TEAMS,
CHAR_UPD_ARENA_TEAM_NAME,
diff --git a/src/server/shared/Database/MySQLConnection.cpp b/src/server/shared/Database/MySQLConnection.cpp
index 1a9f973d47b..10f4a7baa18 100644
--- a/src/server/shared/Database/MySQLConnection.cpp
+++ b/src/server/shared/Database/MySQLConnection.cpp
@@ -22,11 +22,9 @@
#include <winsock2.h>
#endif
#include <mysql.h>
-#include <mysqld_error.h>
#include <errmsg.h>
#include "MySQLConnection.h"
-#include "MySQLThreading.h"
#include "QueryResult.h"
#include "SQLOperation.h"
#include "PreparedStatement.h"
@@ -72,14 +70,14 @@ void MySQLConnection::Close()
delete this;
}
-bool MySQLConnection::Open()
+uint32 MySQLConnection::Open()
{
MYSQL *mysqlInit;
mysqlInit = mysql_init(NULL);
if (!mysqlInit)
{
TC_LOG_ERROR("sql.sql", "Could not initialize Mysql connection to database `%s`", m_connectionInfo.database.c_str());
- return false;
+ return CR_UNKNOWN_ERROR;
}
int port;
@@ -137,13 +135,13 @@ bool MySQLConnection::Open()
// set connection properties to UTF8 to properly handle locales for different
// server configs - core sends data in UTF8, so MySQL must expect UTF8 too
mysql_set_character_set(m_Mysql, "utf8");
- return PrepareStatements();
+ return 0;
}
else
{
- TC_LOG_ERROR("sql.sql", "Could not connect to MySQL database at %s: %s\n", m_connectionInfo.host.c_str(), mysql_error(mysqlInit));
+ TC_LOG_ERROR("sql.sql", "Could not connect to MySQL database at %s: %s", m_connectionInfo.host.c_str(), mysql_error(mysqlInit));
mysql_close(mysqlInit);
- return false;
+ return mysql_errno(mysqlInit);
}
}
@@ -491,8 +489,18 @@ bool MySQLConnection::_HandleMySQLErrno(uint32 errNo)
m_reconnecting = true;
uint64 oldThreadId = mysql_thread_id(GetHandle());
mysql_close(GetHandle());
- if (this->Open()) // Don't remove 'this' pointer unless you want to skip loading all prepared statements....
+
+ uint32 const lErrno = Open();
+ if (!lErrno)
{
+ // Don't remove 'this' pointer unless you want to skip loading all prepared statements...
+ if (!this->PrepareStatements())
+ {
+ TC_LOG_ERROR("sql.sql", "Could not re-prepare statements!");
+ Close();
+ return false;
+ }
+
TC_LOG_INFO("sql.sql", "Connection to the MySQL server is active.");
if (oldThreadId != mysql_thread_id(GetHandle()))
TC_LOG_INFO("sql.sql", "Successfully reconnected to %s @%s:%s (%s).",
@@ -503,7 +511,7 @@ bool MySQLConnection::_HandleMySQLErrno(uint32 errNo)
return true;
}
- uint32 lErrno = mysql_errno(GetHandle()); // It's possible this attempted reconnect throws 2006 at us. To prevent crazy recursive calls, sleep here.
+ // It's possible this attempted reconnect throws 2006 at us. To prevent crazy recursive calls, sleep here.
std::this_thread::sleep_for(std::chrono::seconds(3)); // Sleep 3 seconds
return _HandleMySQLErrno(lErrno); // Call self (recursive)
}
diff --git a/src/server/shared/Database/MySQLConnection.h b/src/server/shared/Database/MySQLConnection.h
index d486f5b4679..78d8d2fb5dd 100644
--- a/src/server/shared/Database/MySQLConnection.h
+++ b/src/server/shared/Database/MySQLConnection.h
@@ -72,9 +72,11 @@ class MySQLConnection
MySQLConnection(ProducerConsumerQueue<SQLOperation*>* queue, MySQLConnectionInfo& connInfo); //! Constructor for asynchronous connections.
virtual ~MySQLConnection();
- virtual bool Open();
+ virtual uint32 Open();
void Close();
+ bool PrepareStatements();
+
public:
bool Execute(const char* sql);
bool Execute(PreparedStatement* stmt);
@@ -111,7 +113,6 @@ class MySQLConnection
MySQLPreparedStatement* GetPreparedStatement(uint32 index);
void PrepareStatement(uint32 index, const char* sql, ConnectionFlags flags);
- bool PrepareStatements();
virtual void DoPrepareStatements() = 0;
protected:
diff --git a/src/server/shared/Database/QueryHolder.cpp b/src/server/shared/Database/QueryHolder.cpp
index 75b96e1996c..2fdb3825526 100644
--- a/src/server/shared/Database/QueryHolder.cpp
+++ b/src/server/shared/Database/QueryHolder.cpp
@@ -40,29 +40,6 @@ bool SQLQueryHolder::SetQuery(size_t index, const char *sql)
return true;
}
-bool SQLQueryHolder::SetPQuery(size_t index, const char *format, ...)
-{
- if (!format)
- {
- TC_LOG_ERROR("sql.sql", "Query (index: %u) is empty.", uint32(index));
- return false;
- }
-
- va_list ap;
- char szQuery [MAX_QUERY_LEN];
- va_start(ap, format);
- int res = vsnprintf(szQuery, MAX_QUERY_LEN, format, ap);
- va_end(ap);
-
- if (res == -1)
- {
- TC_LOG_ERROR("sql.sql", "SQL Query truncated (and not execute) for format: %s", format);
- return false;
- }
-
- return SetQuery(index, szQuery);
-}
-
bool SQLQueryHolder::SetPreparedQuery(size_t index, PreparedStatement* stmt)
{
if (m_queries.size() <= index)
diff --git a/src/server/shared/Database/QueryHolder.h b/src/server/shared/Database/QueryHolder.h
index 6fd1901447e..4102bba1223 100644
--- a/src/server/shared/Database/QueryHolder.h
+++ b/src/server/shared/Database/QueryHolder.h
@@ -29,8 +29,9 @@ class SQLQueryHolder
public:
SQLQueryHolder() { }
~SQLQueryHolder();
- bool SetQuery(size_t index, const char *sql);
- bool SetPQuery(size_t index, const char *format, ...) ATTR_PRINTF(3, 4);
+ bool SetQuery(size_t index, const char* sql);
+ template<typename... Args>
+ bool SetPQuery(size_t index, const char* sql, Args const&... args) { return SetQuery(index, Trinity::StringFormat(sql, args...).c_str()); }
bool SetPreparedQuery(size_t index, PreparedStatement* stmt);
void SetSize(size_t size);
QueryResult GetResult(size_t index);
diff --git a/src/server/shared/Database/Transaction.cpp b/src/server/shared/Database/Transaction.cpp
index b83b787a106..f657411f716 100644
--- a/src/server/shared/Database/Transaction.cpp
+++ b/src/server/shared/Database/Transaction.cpp
@@ -19,6 +19,8 @@
#include "Transaction.h"
#include <mysqld_error.h>
+std::mutex TransactionTask::_deadlockLock;
+
//- Append a raw ad-hoc query to the transaction
void Transaction::Append(const char* sql)
{
@@ -28,17 +30,6 @@ void Transaction::Append(const char* sql)
m_queries.push_back(data);
}
-void Transaction::PAppend(const char* sql, ...)
-{
- va_list ap;
- char szQuery [MAX_QUERY_LEN];
- va_start(ap, sql);
- vsnprintf(szQuery, MAX_QUERY_LEN, sql, ap);
- va_end(ap);
-
- Append(szQuery);
-}
-
//- Append a prepared statement to the transaction
void Transaction::Append(PreparedStatement* stmt)
{
@@ -81,6 +72,8 @@ bool TransactionTask::Execute()
if (errorCode == ER_LOCK_DEADLOCK)
{
+ // Make sure only 1 async thread retries a transaction so they don't keep dead-locking each other
+ std::lock_guard<std::mutex> lock(_deadlockLock);
uint8 loopBreaker = 5; // Handle MySQL Errno 1213 without extending deadlock to the core itself
for (uint8 i = 0; i < loopBreaker; ++i)
if (!m_conn->ExecuteTransaction(m_trans))
diff --git a/src/server/shared/Database/Transaction.h b/src/server/shared/Database/Transaction.h
index cf6aa98b386..43850b1d016 100644
--- a/src/server/shared/Database/Transaction.h
+++ b/src/server/shared/Database/Transaction.h
@@ -19,6 +19,7 @@
#define _TRANSACTION_H
#include "SQLOperation.h"
+#include "StringFormat.h"
//- Forward declare (don't include header to prevent circular includes)
class PreparedStatement;
@@ -38,7 +39,8 @@ class Transaction
void Append(PreparedStatement* statement);
void Append(const char* sql);
- void PAppend(const char* sql, ...);
+ template<typename... Args>
+ void PAppend(const char* sql, Args const&... args) { Append(Trinity::StringFormat(sql, args...).c_str()); }
size_t GetSize() const { return m_queries.size(); }
@@ -66,6 +68,7 @@ class TransactionTask : public SQLOperation
bool Execute() override;
SQLTransaction m_trans;
+ static std::mutex _deadlockLock;
};
#endif
diff --git a/src/server/shared/Debugging/WheatyExceptionReport.cpp b/src/server/shared/Debugging/WheatyExceptionReport.cpp
index e9f4f9ca9ac..f8f641a9ea7 100644
--- a/src/server/shared/Debugging/WheatyExceptionReport.cpp
+++ b/src/server/shared/Debugging/WheatyExceptionReport.cpp
@@ -1068,7 +1068,7 @@ bool logChildren)
{
case btChar:
case btStdString:
- FormatOutputValue(buffer, basicType, length, (PVOID)offset, sizeof(buffer));
+ FormatOutputValue(buffer, basicType, length, (PVOID)offset, sizeof(buffer), elementsCount);
symbolDetails.top().Value = buffer;
break;
default:
@@ -1196,7 +1196,8 @@ void WheatyExceptionReport::FormatOutputValue(char * pszCurrBuffer,
BasicType basicType,
DWORD64 length,
PVOID pAddress,
-size_t bufferSize)
+size_t bufferSize,
+size_t countOverride)
{
__try
{
@@ -1204,10 +1205,15 @@ size_t bufferSize)
{
case btChar:
{
- if (strlen((char*)pAddress) > bufferSize - 6)
+ // Special case handling for char[] type
+ if (countOverride != 0)
+ length = countOverride;
+ else
+ length = strlen((char*)pAddress);
+ if (length > bufferSize - 6)
pszCurrBuffer += sprintf(pszCurrBuffer, "\"%.*s...\"", bufferSize - 6, (char*)pAddress);
else
- pszCurrBuffer += sprintf(pszCurrBuffer, "\"%s\"", (char*)pAddress);
+ pszCurrBuffer += sprintf(pszCurrBuffer, "\"%.*s\"", length, (char*)pAddress);
break;
}
case btStdString:
diff --git a/src/server/shared/Debugging/WheatyExceptionReport.h b/src/server/shared/Debugging/WheatyExceptionReport.h
index 9137b91aac9..b7731daaa2b 100644
--- a/src/server/shared/Debugging/WheatyExceptionReport.h
+++ b/src/server/shared/Debugging/WheatyExceptionReport.h
@@ -172,7 +172,7 @@ class WheatyExceptionReport
static char * DumpTypeIndex(char *, DWORD64, DWORD, unsigned, DWORD_PTR, bool &, const char*, char*, bool, bool);
- static void FormatOutputValue(char * pszCurrBuffer, BasicType basicType, DWORD64 length, PVOID pAddress, size_t bufferSize);
+ static void FormatOutputValue(char * pszCurrBuffer, BasicType basicType, DWORD64 length, PVOID pAddress, size_t bufferSize, size_t countOverride = 0);
static BasicType GetBasicType(DWORD typeIndex, DWORD64 modBase);
static DWORD_PTR DereferenceUnsafePointer(DWORD_PTR address);
diff --git a/src/server/shared/Logging/Appender.cpp b/src/server/shared/Logging/Appender.cpp
index dff931e3da8..ba23d879ec2 100644
--- a/src/server/shared/Logging/Appender.cpp
+++ b/src/server/shared/Logging/Appender.cpp
@@ -18,6 +18,10 @@
#include "Appender.h"
#include "Common.h"
#include "Util.h"
+#include "StringFormat.h"
+
+#include <utility>
+#include <sstream>
std::string LogMessage::getTimeStr(time_t time)
{
@@ -68,38 +72,23 @@ void Appender::setLogLevel(LogLevel _level)
level = _level;
}
-void Appender::write(LogMessage& message)
+void Appender::write(LogMessage* message)
{
- if (!level || level > message.level)
+ if (!level || level > message->level)
return;
- message.prefix.clear();
+ std::ostringstream ss;
+
if (flags & APPENDER_FLAGS_PREFIX_TIMESTAMP)
- message.prefix.append(message.getTimeStr());
+ ss << message->getTimeStr() << ' ';
if (flags & APPENDER_FLAGS_PREFIX_LOGLEVEL)
- {
- if (!message.prefix.empty())
- message.prefix.push_back(' ');
-
- char text[MAX_QUERY_LEN];
- snprintf(text, MAX_QUERY_LEN, "%-5s", Appender::getLogLevelString(message.level));
- message.prefix.append(text);
- }
+ ss << Trinity::StringFormat("%-5s ", Appender::getLogLevelString(message->level));
if (flags & APPENDER_FLAGS_PREFIX_LOGFILTERTYPE)
- {
- if (!message.prefix.empty())
- message.prefix.push_back(' ');
-
- message.prefix.push_back('[');
- message.prefix.append(message.type);
- message.prefix.push_back(']');
- }
-
- if (!message.prefix.empty())
- message.prefix.push_back(' ');
+ ss << '[' << message->type << "] ";
+ message->prefix = std::move(ss.str());
_write(message);
}
diff --git a/src/server/shared/Logging/Appender.h b/src/server/shared/Logging/Appender.h
index 6f38eb6aaf7..73af351e41d 100644
--- a/src/server/shared/Logging/Appender.h
+++ b/src/server/shared/Logging/Appender.h
@@ -21,6 +21,7 @@
#include <unordered_map>
#include <string>
#include <time.h>
+#include <type_traits>
#include "Define.h"
// Values assigned have their equivalent in enum ACE_Log_Priority
@@ -57,16 +58,19 @@ enum AppenderFlags
struct LogMessage
{
- LogMessage(LogLevel _level, std::string const& _type, std::string const& _text)
- : level(_level), type(_type), text(_text), mtime(time(NULL))
+ LogMessage(LogLevel _level, std::string const& _type, std::string&& _text)
+ : level(_level), type(_type), text(std::forward<std::string>(_text)), mtime(time(NULL))
{ }
+ LogMessage(LogMessage const& /*other*/) = delete;
+ LogMessage& operator=(LogMessage const& /*other*/) = delete;
+
static std::string getTimeStr(time_t time);
std::string getTimeStr();
- LogLevel level;
- std::string type;
- std::string text;
+ LogLevel const level;
+ std::string const type;
+ std::string const text;
std::string prefix;
std::string param1;
time_t mtime;
@@ -91,11 +95,11 @@ class Appender
AppenderFlags getFlags() const;
void setLogLevel(LogLevel);
- void write(LogMessage& message);
+ void write(LogMessage* message);
static const char* getLogLevelString(LogLevel level);
private:
- virtual void _write(LogMessage const& /*message*/) = 0;
+ virtual void _write(LogMessage const* /*message*/) = 0;
uint8 id;
std::string name;
diff --git a/src/server/shared/Logging/AppenderConsole.cpp b/src/server/shared/Logging/AppenderConsole.cpp
index ae27337fb9a..2efa4db4d2e 100644
--- a/src/server/shared/Logging/AppenderConsole.cpp
+++ b/src/server/shared/Logging/AppenderConsole.cpp
@@ -158,14 +158,14 @@ void AppenderConsole::ResetColor(bool stdout_stream)
#endif
}
-void AppenderConsole::_write(LogMessage const& message)
+void AppenderConsole::_write(LogMessage const* message)
{
- bool stdout_stream = !(message.level == LOG_LEVEL_ERROR || message.level == LOG_LEVEL_FATAL);
+ bool stdout_stream = !(message->level == LOG_LEVEL_ERROR || message->level == LOG_LEVEL_FATAL);
if (_colored)
{
uint8 index;
- switch (message.level)
+ switch (message->level)
{
case LOG_LEVEL_TRACE:
index = 5;
@@ -189,9 +189,9 @@ void AppenderConsole::_write(LogMessage const& message)
}
SetColor(stdout_stream, _colors[index]);
- utf8printf(stdout_stream ? stdout : stderr, "%s%s", message.prefix.c_str(), message.text.c_str());
+ utf8printf(stdout_stream ? stdout : stderr, "%s%s\n", message->prefix.c_str(), message->text.c_str());
ResetColor(stdout_stream);
}
else
- utf8printf(stdout_stream ? stdout : stderr, "%s%s", message.prefix.c_str(), message.text.c_str());
+ utf8printf(stdout_stream ? stdout : stderr, "%s%s\n", message->prefix.c_str(), message->text.c_str());
}
diff --git a/src/server/shared/Logging/AppenderConsole.h b/src/server/shared/Logging/AppenderConsole.h
index 0f9536b3111..0acf7636e35 100644
--- a/src/server/shared/Logging/AppenderConsole.h
+++ b/src/server/shared/Logging/AppenderConsole.h
@@ -51,7 +51,7 @@ class AppenderConsole: public Appender
private:
void SetColor(bool stdout_stream, ColorTypes color);
void ResetColor(bool stdout_stream);
- void _write(LogMessage const& message) override;
+ void _write(LogMessage const* message) override;
bool _colored;
ColorTypes _colors[MaxLogLevels];
};
diff --git a/src/server/shared/Logging/AppenderDB.cpp b/src/server/shared/Logging/AppenderDB.cpp
index d297d6d08d3..8a329ea3a0f 100644
--- a/src/server/shared/Logging/AppenderDB.cpp
+++ b/src/server/shared/Logging/AppenderDB.cpp
@@ -23,18 +23,18 @@ AppenderDB::AppenderDB(uint8 id, std::string const& name, LogLevel level)
AppenderDB::~AppenderDB() { }
-void AppenderDB::_write(LogMessage const& message)
+void AppenderDB::_write(LogMessage const* message)
{
// Avoid infinite loop, PExecute triggers Logging with "sql.sql" type
- if (!enabled || !message.type.find("sql"))
+ if (!enabled || (message->type.find("sql") != std::string::npos))
return;
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_LOG);
- stmt->setUInt64(0, message.mtime);
+ stmt->setUInt64(0, message->mtime);
stmt->setUInt32(1, realmId);
- stmt->setString(2, message.type);
- stmt->setUInt8(3, uint8(message.level));
- stmt->setString(4, message.text);
+ stmt->setString(2, message->type);
+ stmt->setUInt8(3, uint8(message->level));
+ stmt->setString(4, message->text);
LoginDatabase.Execute(stmt);
}
diff --git a/src/server/shared/Logging/AppenderDB.h b/src/server/shared/Logging/AppenderDB.h
index e20ceaf77b4..09affdb46f1 100644
--- a/src/server/shared/Logging/AppenderDB.h
+++ b/src/server/shared/Logging/AppenderDB.h
@@ -31,7 +31,7 @@ class AppenderDB: public Appender
private:
uint32 realmId;
bool enabled;
- void _write(LogMessage const& message) override;
+ void _write(LogMessage const* message) override;
};
#endif
diff --git a/src/server/shared/Logging/AppenderFile.cpp b/src/server/shared/Logging/AppenderFile.cpp
index 07a88a367ae..3892adbe3be 100644
--- a/src/server/shared/Logging/AppenderFile.cpp
+++ b/src/server/shared/Logging/AppenderFile.cpp
@@ -43,21 +43,21 @@ AppenderFile::~AppenderFile()
CloseFile();
}
-void AppenderFile::_write(LogMessage const& message)
+void AppenderFile::_write(LogMessage const* message)
{
- bool exceedMaxSize = maxFileSize > 0 && (fileSize.load() + message.Size()) > maxFileSize;
+ bool exceedMaxSize = maxFileSize > 0 && (fileSize.load() + message->Size()) > maxFileSize;
if (dynamicName)
{
char namebuf[TRINITY_PATH_MAX];
- snprintf(namebuf, TRINITY_PATH_MAX, filename.c_str(), message.param1.c_str());
+ snprintf(namebuf, TRINITY_PATH_MAX, filename.c_str(), message->param1.c_str());
// always use "a" with dynamic name otherwise it could delete the log we wrote in last _write() call
FILE* file = OpenFile(namebuf, "a", backup || exceedMaxSize);
if (!file)
return;
- fprintf(file, "%s%s", message.prefix.c_str(), message.text.c_str());
+ fprintf(file, "%s%s", message->prefix.c_str(), message->text.c_str());
fflush(file);
- fileSize += uint64(message.Size());
+ fileSize += uint64(message->Size());
fclose(file);
return;
}
@@ -67,9 +67,9 @@ void AppenderFile::_write(LogMessage const& message)
if (!logfile)
return;
- fprintf(logfile, "%s%s", message.prefix.c_str(), message.text.c_str());
+ fprintf(logfile, "%s%s\n", message->prefix.c_str(), message->text.c_str());
fflush(logfile);
- fileSize += uint64(message.Size());
+ fileSize += uint64(message->Size());
}
FILE* AppenderFile::OpenFile(std::string const &filename, std::string const &mode, bool backup)
diff --git a/src/server/shared/Logging/AppenderFile.h b/src/server/shared/Logging/AppenderFile.h
index 23651fc1129..36afdd23ad1 100644
--- a/src/server/shared/Logging/AppenderFile.h
+++ b/src/server/shared/Logging/AppenderFile.h
@@ -30,7 +30,7 @@ class AppenderFile: public Appender
private:
void CloseFile();
- void _write(LogMessage const& message) override;
+ void _write(LogMessage const* message) override;
FILE* logfile;
std::string filename;
std::string logDir;
diff --git a/src/server/shared/Logging/Log.cpp b/src/server/shared/Logging/Log.cpp
index 4bf4dacb302..a2150733c6b 100644
--- a/src/server/shared/Logging/Log.cpp
+++ b/src/server/shared/Logging/Log.cpp
@@ -25,7 +25,6 @@
#include "AppenderDB.h"
#include "LogOperation.h"
-#include <cstdarg>
#include <cstdio>
#include <sstream>
@@ -199,6 +198,9 @@ void Log::CreateLoggerFromConfig(std::string const& appenderName)
return;
}
+ if (level < lowestLogLevel)
+ lowestLogLevel = level;
+
logger.Create(name, level);
//fprintf(stdout, "Log::CreateLoggerFromConfig: Created Logger %s, Level %u\n", name.c_str(), level);
@@ -261,30 +263,18 @@ void Log::ReadLoggersFromConfig()
}
}
-void Log::vlog(std::string const& filter, LogLevel level, char const* str, va_list argptr)
-{
- char text[MAX_QUERY_LEN];
- vsnprintf(text, MAX_QUERY_LEN, str, argptr);
- write(new LogMessage(level, filter, text));
-}
-
-void Log::write(LogMessage* msg) const
+void Log::write(std::unique_ptr<LogMessage>&& msg) const
{
Logger const* logger = GetLoggerByType(msg->type);
- msg->text.append("\n");
if (_ioService)
{
- auto logOperation = std::shared_ptr<LogOperation>(new LogOperation(logger, msg));
+ auto logOperation = std::shared_ptr<LogOperation>(new LogOperation(logger, std::forward<std::unique_ptr<LogMessage>>(msg)));
_ioService->post(_strand->wrap([logOperation](){ logOperation->call(); }));
-
}
else
- {
- logger->write(*msg);
- delete msg;
- }
+ logger->write(msg.get());
}
std::string Log::GetTimestampStr()
@@ -321,6 +311,9 @@ bool Log::SetLogLevel(std::string const& name, const char* newLevelc, bool isLog
return false;
it->second.setLogLevel(newLevel);
+
+ if (newLevel != LOG_LEVEL_DISABLED && newLevel < lowestLogLevel)
+ lowestLogLevel = newLevel;
}
else
{
@@ -343,40 +336,20 @@ void Log::outCharDump(char const* str, uint32 accountId, uint64 guid, char const
ss << "== START DUMP == (account: " << accountId << " guid: " << guid << " name: " << name
<< ")\n" << str << "\n== END DUMP ==\n";
- LogMessage* msg = new LogMessage(LOG_LEVEL_INFO, "entities.player.dump", ss.str());
+ std::unique_ptr<LogMessage> msg(new LogMessage(LOG_LEVEL_INFO, "entities.player.dump", ss.str()));
std::ostringstream param;
param << guid << '_' << name;
msg->param1 = param.str();
- write(msg);
-}
-
-void Log::outCommand(uint32 account, const char * str, ...)
-{
- if (!str || !ShouldLog("commands.gm", LOG_LEVEL_INFO))
- return;
-
- va_list ap;
- va_start(ap, str);
- char text[MAX_QUERY_LEN];
- vsnprintf(text, MAX_QUERY_LEN, str, ap);
- va_end(ap);
-
- LogMessage* msg = new LogMessage(LOG_LEVEL_INFO, "commands.gm", text);
-
- std::ostringstream ss;
- ss << account;
- msg->param1 = ss.str();
-
- write(msg);
+ write(std::move(msg));
}
void Log::SetRealmId(uint32 id)
{
for (AppenderMap::iterator it = appenders.begin(); it != appenders.end(); ++it)
if (it->second && it->second->getType() == APPENDER_DB)
- ((AppenderDB *)it->second)->setRealmId(id);
+ static_cast<AppenderDB*>(it->second)->setRealmId(id);
}
void Log::Close()
@@ -394,6 +367,7 @@ void Log::LoadFromConfig()
{
Close();
+ lowestLogLevel = LOG_LEVEL_FATAL;
AppenderId = 0;
m_logsDir = sConfigMgr->GetStringDefault("LogsDir", "");
if (!m_logsDir.empty())
diff --git a/src/server/shared/Logging/Log.h b/src/server/shared/Logging/Log.h
index 1d67ff87f76..d4653960b15 100644
--- a/src/server/shared/Logging/Log.h
+++ b/src/server/shared/Logging/Log.h
@@ -22,12 +22,14 @@
#include "Define.h"
#include "Appender.h"
#include "Logger.h"
-#include <stdarg.h>
+#include "StringFormat.h"
#include <boost/asio/io_service.hpp>
#include <boost/asio/strand.hpp>
+#include <stdarg.h>
#include <unordered_map>
#include <string>
+#include <memory>
#define LOGGER_ROOT "root"
@@ -59,17 +61,32 @@ class Log
bool ShouldLog(std::string const& type, LogLevel level) const;
bool SetLogLevel(std::string const& name, char const* level, bool isLogger = true);
- void outMessage(std::string const& f, LogLevel level, char const* str, ...) ATTR_PRINTF(4, 5);
+ template<typename... Args>
+ inline void outMessage(std::string const& filter, LogLevel const level, const char* fmt, Args const&... args)
+ {
+ write(std::move(std::unique_ptr<LogMessage>(new LogMessage(level, filter, std::move(Trinity::StringFormat(fmt, args...))))));
+ }
+
+ template<typename... Args>
+ void outCommand(uint32 account, const char* fmt, Args const&... args)
+ {
+ if (!ShouldLog("commands.gm", LOG_LEVEL_INFO))
+ return;
+
+ std::unique_ptr<LogMessage> msg(new LogMessage(LOG_LEVEL_INFO, "commands.gm", std::move(Trinity::StringFormat(fmt, args...))));
+
+ msg->param1 = std::to_string(account);
+
+ write(std::move(msg));
+ }
- void outCommand(uint32 account, const char * str, ...) ATTR_PRINTF(3, 4);
void outCharDump(char const* str, uint32 account_id, uint64 guid, char const* name);
void SetRealmId(uint32 id);
private:
static std::string GetTimestampStr();
- void vlog(std::string const& f, LogLevel level, char const* str, va_list argptr);
- void write(LogMessage* msg) const;
+ void write(std::unique_ptr<LogMessage>&& msg) const;
Logger const* GetLoggerByType(std::string const& type) const;
Appender* GetAppenderByName(std::string const& name);
@@ -82,6 +99,7 @@ class Log
AppenderMap appenders;
LoggerMap loggers;
uint8 AppenderId;
+ LogLevel lowestLogLevel;
std::string m_logsDir;
std::string m_logsTimestamp;
@@ -113,6 +131,10 @@ inline bool Log::ShouldLog(std::string const& type, LogLevel level) const
// Speed up in cases where requesting "Type.sub1.sub2" but only configured
// Logger "Type"
+ // Don't even look for a logger if the LogLevel is lower than lowest log levels across all loggers
+ if (level < lowestLogLevel)
+ return false;
+
Logger const* logger = GetLoggerByType(type);
if (!logger)
return false;
@@ -121,23 +143,34 @@ inline bool Log::ShouldLog(std::string const& type, LogLevel level) const
return logLevel != LOG_LEVEL_DISABLED && logLevel <= level;
}
-inline void Log::outMessage(std::string const& filter, LogLevel level, const char * str, ...)
-{
- va_list ap;
- va_start(ap, str);
-
- vlog(filter, level, str, ap);
-
- va_end(ap);
-}
-
#define sLog Log::instance()
+#define LOG_EXCEPTION_FREE(filterType__, level__, ...) \
+ { \
+ try \
+ { \
+ sLog->outMessage(filterType__, level__, __VA_ARGS__); \
+ } \
+ catch (std::exception& e) \
+ { \
+ sLog->outMessage("server", LOG_LEVEL_ERROR, "Wrong format occurred (%s) at %s:%u.", \
+ e.what(), __FILE__, __LINE__); \
+ } \
+ }
+
#if PLATFORM != PLATFORM_WINDOWS
+void check_args(const char* format, ...) ATTR_PRINTF(1, 2);
+
+// This will catch format errors on build time
#define TC_LOG_MESSAGE_BODY(filterType__, level__, ...) \
do { \
if (sLog->ShouldLog(filterType__, level__)) \
- sLog->outMessage(filterType__, level__, __VA_ARGS__); \
+ { \
+ if (false) \
+ check_args(__VA_ARGS__); \
+ \
+ LOG_EXCEPTION_FREE(filterType__, level__, __VA_ARGS__); \
+ } \
} while (0)
#else
#define TC_LOG_MESSAGE_BODY(filterType__, level__, ...) \
@@ -145,7 +178,7 @@ inline void Log::outMessage(std::string const& filter, LogLevel level, const cha
__pragma(warning(disable:4127)) \
do { \
if (sLog->ShouldLog(filterType__, level__)) \
- sLog->outMessage(filterType__, level__, __VA_ARGS__); \
+ LOG_EXCEPTION_FREE(filterType__, level__, __VA_ARGS__); \
} while (0) \
__pragma(warning(pop))
#endif
diff --git a/src/server/shared/Logging/LogOperation.cpp b/src/server/shared/Logging/LogOperation.cpp
index 9afb28a49c2..bcd923c705e 100644
--- a/src/server/shared/Logging/LogOperation.cpp
+++ b/src/server/shared/Logging/LogOperation.cpp
@@ -18,14 +18,8 @@
#include "LogOperation.h"
#include "Logger.h"
-LogOperation::~LogOperation()
-{
- delete msg;
-}
-
int LogOperation::call()
{
- if (logger && msg)
- logger->write(*msg);
+ logger->write(msg.get());
return 0;
}
diff --git a/src/server/shared/Logging/LogOperation.h b/src/server/shared/Logging/LogOperation.h
index b8655413273..ffdd35c3c09 100644
--- a/src/server/shared/Logging/LogOperation.h
+++ b/src/server/shared/Logging/LogOperation.h
@@ -18,23 +18,25 @@
#ifndef LOGOPERATION_H
#define LOGOPERATION_H
+#include <memory>
+
class Logger;
struct LogMessage;
class LogOperation
{
public:
- LogOperation(Logger const* _logger, LogMessage* _msg)
- : logger(_logger), msg(_msg)
+ LogOperation(Logger const* _logger, std::unique_ptr<LogMessage>&& _msg)
+ : logger(_logger), msg(std::forward<std::unique_ptr<LogMessage>>(_msg))
{ }
- ~LogOperation();
+ ~LogOperation() { }
int call();
protected:
Logger const* logger;
- LogMessage* msg;
+ std::unique_ptr<LogMessage> msg;
};
#endif
diff --git a/src/server/shared/Logging/Logger.cpp b/src/server/shared/Logging/Logger.cpp
index 615732deb30..3b02eb47575 100644
--- a/src/server/shared/Logging/Logger.cpp
+++ b/src/server/shared/Logging/Logger.cpp
@@ -50,9 +50,9 @@ void Logger::setLogLevel(LogLevel _level)
level = _level;
}
-void Logger::write(LogMessage& message) const
+void Logger::write(LogMessage* message) const
{
- if (!level || level > message.level || message.text.empty())
+ if (!level || level > message->level || message->text.empty())
{
//fprintf(stderr, "Logger::write: Logger %s, Level %u. Msg %s Level %u WRONG LEVEL MASK OR EMPTY MSG\n", getName().c_str(), getLogLevel(), message.text.c_str(), message.level);
return;
diff --git a/src/server/shared/Logging/Logger.h b/src/server/shared/Logging/Logger.h
index a81ee8d7bd2..1aee75c5d72 100644
--- a/src/server/shared/Logging/Logger.h
+++ b/src/server/shared/Logging/Logger.h
@@ -32,7 +32,7 @@ class Logger
std::string const& getName() const;
LogLevel getLogLevel() const;
void setLogLevel(LogLevel level);
- void write(LogMessage& message) const;
+ void write(LogMessage* message) const;
private:
std::string name;
diff --git a/src/server/shared/Networking/Socket.h b/src/server/shared/Networking/Socket.h
index f6bf3976b85..f7a1b954cb0 100644
--- a/src/server/shared/Networking/Socket.h
+++ b/src/server/shared/Networking/Socket.h
@@ -34,7 +34,9 @@
using boost::asio::ip::tcp;
#define READ_BLOCK_SIZE 4096
-#define TC_SOCKET_USE_IOCP BOOST_ASIO_HAS_IOCP
+#ifdef BOOST_ASIO_HAS_IOCP
+#define TC_SOCKET_USE_IOCP
+#endif
template<class T>
class Socket : public std::enable_shared_from_this<T>
diff --git a/src/server/shared/Networking/SocketMgr.h b/src/server/shared/Networking/SocketMgr.h
index df57baf257e..2078ae90c62 100644
--- a/src/server/shared/Networking/SocketMgr.h
+++ b/src/server/shared/Networking/SocketMgr.h
@@ -99,7 +99,7 @@ public:
}
catch (boost::system::system_error const& err)
{
- TC_LOG_INFO("network", "Failed to retrieve client's remote address %s", err.what());
+ TC_LOG_WARN("network", "Failed to retrieve client's remote address %s", err.what());
}
}
diff --git a/src/server/shared/Updater/DBUpdater.cpp b/src/server/shared/Updater/DBUpdater.cpp
new file mode 100644
index 00000000000..5918fe06b55
--- /dev/null
+++ b/src/server/shared/Updater/DBUpdater.cpp
@@ -0,0 +1,380 @@
+/*
+ * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "DBUpdater.h"
+#include "Log.h"
+#include "revision.h"
+#include "UpdateFetcher.h"
+#include "DatabaseLoader.h"
+#include "Config.h"
+
+#include <fstream>
+#include <iostream>
+#include <unordered_map>
+#include <boost/process.hpp>
+#include <boost/iostreams/device/file_descriptor.hpp>
+#include <boost/system/system_error.hpp>
+
+using namespace boost::process;
+using namespace boost::process::initializers;
+using namespace boost::iostreams;
+
+template<class T>
+std::string DBUpdater<T>::GetSourceDirectory()
+{
+ std::string const entry = sConfigMgr->GetStringDefault("Updates.SourcePath", "");
+ if (!entry.empty())
+ return entry;
+ else
+ return _SOURCE_DIRECTORY;
+}
+
+template<class T>
+std::string DBUpdater<T>::GetMySqlCli()
+{
+ std::string const entry = sConfigMgr->GetStringDefault("Updates.MySqlCLIPath", "");
+ if (!entry.empty())
+ return entry;
+ else
+ return _MYSQL_EXECUTABLE;
+}
+
+// Auth Database
+template<>
+std::string DBUpdater<LoginDatabaseConnection>::GetConfigEntry()
+{
+ return "Updates.Auth";
+}
+
+template<>
+std::string DBUpdater<LoginDatabaseConnection>::GetTableName()
+{
+ return "Auth";
+}
+
+template<>
+std::string DBUpdater<LoginDatabaseConnection>::GetBaseFile()
+{
+ return DBUpdater<LoginDatabaseConnection>::GetSourceDirectory() + "/sql/base/auth_database.sql";
+}
+
+template<>
+bool DBUpdater<LoginDatabaseConnection>::IsEnabled(uint32 const updateMask)
+{
+ // This way silences warnings under msvc
+ return (updateMask & DatabaseLoader::DATABASE_LOGIN) ? true : false;
+}
+
+// World Database
+template<>
+std::string DBUpdater<WorldDatabaseConnection>::GetConfigEntry()
+{
+ return "Updates.World";
+}
+
+template<>
+std::string DBUpdater<WorldDatabaseConnection>::GetTableName()
+{
+ return "World";
+}
+
+template<>
+std::string DBUpdater<WorldDatabaseConnection>::GetBaseFile()
+{
+ return _FULL_DATABASE;
+}
+
+template<>
+bool DBUpdater<WorldDatabaseConnection>::IsEnabled(uint32 const updateMask)
+{
+ // This way silences warnings under msvc
+ return (updateMask & DatabaseLoader::DATABASE_WORLD) ? true : false;
+}
+
+template<>
+BaseLocation DBUpdater<WorldDatabaseConnection>::GetBaseLocationType()
+{
+ return LOCATION_DOWNLOAD;
+}
+
+// Character Database
+template<>
+std::string DBUpdater<CharacterDatabaseConnection>::GetConfigEntry()
+{
+ return "Updates.Character";
+}
+
+template<>
+std::string DBUpdater<CharacterDatabaseConnection>::GetTableName()
+{
+ return "Character";
+}
+
+template<>
+std::string DBUpdater<CharacterDatabaseConnection>::GetBaseFile()
+{
+ return DBUpdater<CharacterDatabaseConnection>::GetSourceDirectory() + "/sql/base/characters_database.sql";
+}
+
+template<>
+bool DBUpdater<CharacterDatabaseConnection>::IsEnabled(uint32 const updateMask)
+{
+ // This way silences warnings under msvc
+ return (updateMask & DatabaseLoader::DATABASE_CHARACTER) ? true : false;
+}
+
+// All
+template<class T>
+BaseLocation DBUpdater<T>::GetBaseLocationType()
+{
+ return LOCATION_REPOSITORY;
+}
+
+template<class T>
+bool DBUpdater<T>::CheckExecutable()
+{
+ DBUpdater<T>::Path const exe(DBUpdater<T>::GetMySqlCli());
+ if (!exists(exe))
+ {
+ // Check for mysql in path
+ std::vector<std::string> args = {"--version"};
+ uint32 ret;
+ try
+ {
+ child c = execute(run_exe("mysql"), set_args(args), throw_on_error(), close_stdout());
+ ret = wait_for_exit(c);
+ }
+ catch (boost::system::system_error&)
+ {
+ ret = EXIT_FAILURE;
+ }
+
+ if (ret == EXIT_FAILURE)
+ {
+ TC_LOG_FATAL("sql.updates", "Didn't find executeable mysql binary at \'%s\', correct the path in the *.conf (\"Updates.MySqlCLIPath\").",
+ absolute(exe).generic_string().c_str());
+
+ return false;
+ }
+ }
+ return true;
+}
+
+template<class T>
+bool DBUpdater<T>::Create(DatabaseWorkerPool<T>& pool)
+{
+ TC_LOG_INFO("sql.updates", "Database \"%s\" does not exist, do you want to create it? [yes (default) / no]: ",
+ pool.GetConnectionInfo()->database.c_str());
+
+ std::string answer;
+ std::getline(std::cin, answer);
+ if (!answer.empty() && !(answer.substr(0, 1) == "y"))
+ return false;
+
+ TC_LOG_INFO("sql.updates", "Creating database \"%s\"...", pool.GetConnectionInfo()->database.c_str());
+
+ // Path of temp file
+ static Path const temp("create_table.sql");
+
+ // Create temporary query to use external mysql cli
+ std::ofstream file(temp.generic_string());
+ if (!file.is_open())
+ {
+ TC_LOG_FATAL("sql.updates", "Failed to create temporary query file \"%s\"!", temp.generic_string().c_str());
+ return false;
+ }
+
+ file << "CREATE DATABASE `" << pool.GetConnectionInfo()->database << "` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci\n\n";
+
+ file.close();
+
+ try
+ {
+ DBUpdater<T>::ApplyFile(pool, pool.GetConnectionInfo()->host, pool.GetConnectionInfo()->user, pool.GetConnectionInfo()->password,
+ pool.GetConnectionInfo()->port_or_socket, "", temp);
+ }
+ catch (UpdateException&)
+ {
+ TC_LOG_FATAL("sql.updates", "Failed to create database %s! Has the user `CREATE` priviliges?", pool.GetConnectionInfo()->database.c_str());
+ boost::filesystem::remove(temp);
+ return false;
+ }
+
+ TC_LOG_INFO("sql.updates", "Done.");
+ boost::filesystem::remove(temp);
+ return true;
+}
+
+template<class T>
+bool DBUpdater<T>::Update(DatabaseWorkerPool<T>& pool)
+{
+ if (!DBUpdater<T>::CheckExecutable())
+ return false;
+
+ TC_LOG_INFO("sql.updates", "Updating %s database...", DBUpdater<T>::GetTableName().c_str());
+
+ Path const sourceDirectory(GetSourceDirectory());
+
+ if (!is_directory(sourceDirectory))
+ {
+ TC_LOG_ERROR("sql.updates", "DBUpdater: Given source directory %s does not exist, skipped!", sourceDirectory.generic_string().c_str());
+ return false;
+ }
+
+ UpdateFetcher updateFetcher(sourceDirectory, [&](std::string const& query) { DBUpdater<T>::Apply(pool, query); },
+ [&](Path const& file) { DBUpdater<T>::ApplyFile(pool, file); },
+ [&](std::string const& query) -> QueryResult { return DBUpdater<T>::Retrieve(pool, query); });
+
+ uint32 const count = updateFetcher.Update(
+ sConfigMgr->GetBoolDefault("Updates.Redundancy", true),
+ sConfigMgr->GetBoolDefault("Updates.AllowRehash", true),
+ sConfigMgr->GetBoolDefault("Updates.ArchivedRedundancy", false),
+ sConfigMgr->GetIntDefault("Updates.CleanDeadRefMaxCount", 3));
+
+ if (!count)
+ TC_LOG_INFO("sql.updates", ">> %s database is up-to-date!", DBUpdater<T>::GetTableName().c_str());
+ else
+ TC_LOG_INFO("sql.updates", ">> Applied %d %s.", count, count == 1 ? "query" : "queries");
+
+ return true;
+}
+
+template<class T>
+bool DBUpdater<T>::Populate(DatabaseWorkerPool<T>& pool)
+{
+ {
+ QueryResult const result = Retrieve(pool, "SHOW TABLES");
+ if (result && (result->GetRowCount() > 0))
+ return true;
+ }
+
+ if (!DBUpdater<T>::CheckExecutable())
+ return false;
+
+ TC_LOG_INFO("sql.updates", "Database %s is empty, auto populating it...", DBUpdater<T>::GetTableName().c_str());
+
+ std::string const p = DBUpdater<T>::GetBaseFile();
+ if (p.empty())
+ {
+ TC_LOG_INFO("sql.updates", ">> No base file provided, skipped!");
+ return true;
+ }
+
+ Path const base(p);
+ if (!exists(base))
+ {
+ switch (DBUpdater<T>::GetBaseLocationType())
+ {
+ case LOCATION_REPOSITORY:
+ {
+ TC_LOG_ERROR("sql.updates", ">> Base file \"%s\" is missing, try to clone the source again.",
+ base.generic_string().c_str());
+
+ break;
+ }
+ case LOCATION_DOWNLOAD:
+ {
+ TC_LOG_ERROR("sql.updates", ">> File \"%s\" is missing, download it from \"http://www.trinitycore.org/f/files/category/1-database/\"" \
+ " and place it in your server directory.", base.filename().generic_string().c_str());
+ break;
+ }
+ }
+ return false;
+ }
+
+ // Update database
+ TC_LOG_INFO("sql.updates", ">> Applying \'%s\'...", base.generic_string().c_str());
+ ApplyFile(pool, base);
+
+ TC_LOG_INFO("sql.updates", ">> Done!");
+ return true;
+}
+
+template<class T>
+QueryResult DBUpdater<T>::Retrieve(DatabaseWorkerPool<T>& pool, std::string const& query)
+{
+ return pool.PQuery(query.c_str());
+}
+
+template<class T>
+void DBUpdater<T>::Apply(DatabaseWorkerPool<T>& pool, std::string const& query)
+{
+ pool.DirectExecute(query.c_str());
+}
+
+template<class T>
+void DBUpdater<T>::ApplyFile(DatabaseWorkerPool<T>& pool, Path const& path)
+{
+ DBUpdater<T>::ApplyFile(pool, pool.GetConnectionInfo()->host, pool.GetConnectionInfo()->user, pool.GetConnectionInfo()->password,
+ pool.GetConnectionInfo()->port_or_socket, pool.GetConnectionInfo()->database, path);
+}
+
+template<class T>
+void DBUpdater<T>::ApplyFile(DatabaseWorkerPool<T>& pool, std::string const& host, std::string const& user,
+ std::string const& password, std::string const& port_or_socket, std::string const& database, Path const& path)
+{
+ std::vector<std::string> args;
+ args.reserve(7);
+
+ // CLI Client connection info
+ args.push_back("-h" + host);
+ args.push_back("-u" + user);
+ args.push_back("-p" + password);
+ args.push_back("-P" + port_or_socket);
+
+ // Set the default charset to utf8
+ args.push_back("--default-character-set=utf8");
+
+ // Set max allowed packet to 1 GB
+ args.push_back("--max-allowed-packet=1GB");
+
+ // Database
+ if (!database.empty())
+ args.push_back(database);
+
+ // ToDo: use the existing query in memory as virtual file if possible
+ file_descriptor_source source(path);
+
+ uint32 ret;
+ try
+ {
+ child c = execute(run_exe(DBUpdater<T>::GetMySqlCli().empty() ? "mysql" :
+ boost::filesystem::absolute(DBUpdater<T>::GetMySqlCli()).generic_string()),
+ set_args(args), bind_stdin(source), throw_on_error());
+
+ ret = wait_for_exit(c);
+ }
+ catch (boost::system::system_error&)
+ {
+ ret = EXIT_FAILURE;
+ }
+
+ source.close();
+
+ 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.",
+ path.generic_string().c_str(), pool.GetConnectionInfo()->database.c_str());
+
+ throw UpdateException("update failed");
+ }
+}
+
+template class DBUpdater<LoginDatabaseConnection>;
+template class DBUpdater<WorldDatabaseConnection>;
+template class DBUpdater<CharacterDatabaseConnection>;
diff --git a/src/server/shared/Updater/DBUpdater.h b/src/server/shared/Updater/DBUpdater.h
new file mode 100644
index 00000000000..0caf8a438fb
--- /dev/null
+++ b/src/server/shared/Updater/DBUpdater.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef DBUpdater_h__
+#define DBUpdater_h__
+
+#include "DatabaseEnv.h"
+
+#include <string>
+#include <boost/filesystem.hpp>
+
+class UpdateException : public std::exception
+{
+public:
+ UpdateException(std::string const& msg) : _msg(msg) { }
+ ~UpdateException() throw() { }
+
+ char const* what() const throw() override { return _msg.c_str(); }
+
+private:
+ std::string const _msg;
+};
+
+enum BaseLocation
+{
+ LOCATION_REPOSITORY,
+ LOCATION_DOWNLOAD
+};
+
+template <class T>
+class DBUpdater
+{
+public:
+ using Path = boost::filesystem::path;
+
+ static std::string GetSourceDirectory();
+
+ static inline std::string GetConfigEntry();
+
+ static inline std::string GetTableName();
+
+ static std::string GetBaseFile();
+
+ static bool IsEnabled(uint32 const updateMask);
+
+ static BaseLocation GetBaseLocationType();
+
+ static bool Create(DatabaseWorkerPool<T>& pool);
+
+ static bool Update(DatabaseWorkerPool<T>& pool);
+
+ static bool Populate(DatabaseWorkerPool<T>& pool);
+
+private:
+ static std::string GetMySqlCli();
+ static bool CheckExecutable();
+
+ static QueryResult Retrieve(DatabaseWorkerPool<T>& pool, std::string const& query);
+ static void Apply(DatabaseWorkerPool<T>& pool, std::string const& query);
+ static void ApplyFile(DatabaseWorkerPool<T>& pool, Path const& path);
+ static void ApplyFile(DatabaseWorkerPool<T>& pool, std::string const& host, std::string const& user,
+ std::string const& password, std::string const& port_or_socket, std::string const& database, Path const& path);
+};
+
+#endif // DBUpdater_h__
diff --git a/src/server/shared/Updater/UpdateFetcher.cpp b/src/server/shared/Updater/UpdateFetcher.cpp
new file mode 100644
index 00000000000..2b12f39780c
--- /dev/null
+++ b/src/server/shared/Updater/UpdateFetcher.cpp
@@ -0,0 +1,401 @@
+/*
+ * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "UpdateFetcher.h"
+#include "Log.h"
+#include "Util.h"
+
+#include <fstream>
+#include <chrono>
+#include <vector>
+#include <sstream>
+#include <exception>
+#include <unordered_map>
+#include <openssl/sha.h>
+
+using namespace boost::filesystem;
+
+UpdateFetcher::UpdateFetcher(Path const& sourceDirectory,
+ std::function<void(std::string const&)> const& apply,
+ std::function<void(Path const& path)> const& applyFile,
+ std::function<QueryResult(std::string const&)> const& retrieve) :
+ _sourceDirectory(sourceDirectory), _apply(apply), _applyFile(applyFile),
+ _retrieve(retrieve)
+{
+}
+
+UpdateFetcher::LocaleFileStorage UpdateFetcher::GetFileList() const
+{
+ LocaleFileStorage files;
+ DirectoryStorage directories = ReceiveIncludedDirectories();
+ for (auto const& entry : directories)
+ FillFileListRecursively(entry.path, files, entry.state, 1);
+
+ return files;
+}
+
+void UpdateFetcher::FillFileListRecursively(Path const& path, LocaleFileStorage& storage, State const state, uint32 const depth) const
+{
+ static uint32 const MAX_DEPTH = 10;
+ static directory_iterator const end;
+
+ for (directory_iterator itr(path); itr != end; ++itr)
+ {
+ if (is_directory(itr->path()))
+ {
+ if (depth < MAX_DEPTH)
+ FillFileListRecursively(itr->path(), storage, state, depth + 1);
+ }
+ else if (itr->path().extension() == ".sql")
+ {
+ TC_LOG_TRACE("sql.updates", "Added locale file \"%s\".", itr->path().filename().generic_string().c_str());
+
+ LocaleFileEntry const entry = { itr->path(), state };
+
+ // Check for doubled filenames
+ // Since elements are only compared through their filenames this is ok
+ if (storage.find(entry) != storage.end())
+ {
+ TC_LOG_FATAL("sql.updates", "Duplicated filename occurred \"%s\", since updates are ordered " \
+ "through its filename every name needs to be unique!", itr->path().generic_string().c_str());
+
+ throw UpdateException("Updating failed, see the log for details.");
+ }
+
+ storage.insert(entry);
+ }
+ }
+}
+
+UpdateFetcher::DirectoryStorage UpdateFetcher::ReceiveIncludedDirectories() const
+{
+ DirectoryStorage directories;
+
+ QueryResult const result = _retrieve("SELECT `path`, `state` FROM `updates_include`");
+ if (!result)
+ return directories;
+
+ do
+ {
+ Field* fields = result->Fetch();
+
+ std::string path = fields[0].GetString();
+ if (path.substr(0, 1) == "$")
+ path = _sourceDirectory.generic_string() + path.substr(1);
+
+ Path const p(path);
+
+ if (!is_directory(p))
+ {
+ TC_LOG_WARN("sql.updates", "DBUpdater: Given update include directory \"%s\" isn't existing, skipped!", p.generic_string().c_str());
+ continue;
+ }
+
+ DirectoryEntry const entry = { p, AppliedFileEntry::StateConvert(fields[1].GetString()) };
+ directories.push_back(entry);
+
+ TC_LOG_TRACE("sql.updates", "Added applied file \"%s\" from remote.", p.filename().generic_string().c_str());
+
+ } while (result->NextRow());
+
+ return directories;
+}
+
+UpdateFetcher::AppliedFileStorage UpdateFetcher::ReceiveAppliedFiles() const
+{
+ AppliedFileStorage map;
+
+ QueryResult result = _retrieve("SELECT `name`, `hash`, `state`, UNIX_TIMESTAMP(`timestamp`) FROM `updates` ORDER BY `name` ASC");
+ if (!result)
+ return map;
+
+ do
+ {
+ Field* fields = result->Fetch();
+
+ AppliedFileEntry const entry = { fields[0].GetString(), fields[1].GetString(),
+ AppliedFileEntry::StateConvert(fields[2].GetString()), fields[3].GetUInt64() };
+
+ map.insert(std::make_pair(entry.name, entry));
+ }
+ while (result->NextRow());
+
+ return map;
+}
+
+UpdateFetcher::SQLUpdate UpdateFetcher::ReadSQLUpdate(boost::filesystem::path const& file) const
+{
+ std::ifstream in(file.c_str());
+ WPFatal(in.is_open(), "Could not read an update file.");
+
+ auto const start_pos = in.tellg();
+ in.ignore(std::numeric_limits<std::streamsize>::max());
+ auto const char_count = in.gcount();
+ in.seekg(start_pos);
+
+ SQLUpdate const update(new std::string(char_count, char{}));
+
+ in.read(&(*update)[0], update->size());
+ in.close();
+ return update;
+}
+
+uint32 UpdateFetcher::Update(bool const redundancyChecks, bool const allowRehash, bool const archivedRedundancy, int32 const cleanDeadReferencesMaxCount) const
+{
+ LocaleFileStorage const available = GetFileList();
+ AppliedFileStorage applied = ReceiveAppliedFiles();
+
+ // Fill hash to name cache
+ HashToFileNameStorage hashToName;
+ for (auto entry : applied)
+ hashToName.insert(std::make_pair(entry.second.hash, entry.first));
+
+ uint32 importedUpdates = 0;
+
+ for (auto const& availableQuery : available)
+ {
+ TC_LOG_DEBUG("sql.updates", "Checking update \"%s\"...", availableQuery.first.filename().generic_string().c_str());
+
+ AppliedFileStorage::const_iterator iter = applied.find(availableQuery.first.filename().string());
+ if (iter != applied.end())
+ {
+ // If redundancy is disabled skip it since the update is already applied.
+ if (!redundancyChecks)
+ {
+ TC_LOG_DEBUG("sql.updates", ">> Update is already applied, skipping redundancy checks.");
+ applied.erase(iter);
+ continue;
+ }
+
+ // If the update is in an archived directory and is marked as archived in our database skip redundancy checks (archived updates never change).
+ if (!archivedRedundancy && (iter->second.state == ARCHIVED) && (availableQuery.second == ARCHIVED))
+ {
+ TC_LOG_DEBUG("sql.updates", ">> Update is archived and marked as archived in database, skipping redundancy checks.");
+ applied.erase(iter);
+ continue;
+ }
+ }
+
+ // Read update from file
+ SQLUpdate const update = ReadSQLUpdate(availableQuery.first);
+
+ // Calculate hash
+ std::string const hash = CalculateHash(update);
+
+ UpdateMode mode = MODE_APPLY;
+
+ // Update is not in our applied list
+ if (iter == applied.end())
+ {
+ // Catch renames (different filename but same hash)
+ HashToFileNameStorage::const_iterator const hashIter = hashToName.find(hash);
+ if (hashIter != hashToName.end())
+ {
+ // Check if the original file was removed if not we've got a problem.
+ LocaleFileStorage::const_iterator localeIter;
+ // Push localeIter forward
+ for (localeIter = available.begin(); (localeIter != available.end()) &&
+ (localeIter->first.filename().string() != hashIter->second); ++localeIter);
+
+ // Conflict!
+ if (localeIter != available.end())
+ {
+ TC_LOG_WARN("sql.updates", ">> Seems like update \"%s\" \'%s\' was renamed, but the old file is still there! " \
+ "Trade it as a new file! (Probably its an unmodified copy of file \"%s\")",
+ availableQuery.first.filename().string().c_str(), hash.substr(0, 7).c_str(),
+ localeIter->first.filename().string().c_str());
+ }
+ // Its save to trade the file as renamed here
+ else
+ {
+ TC_LOG_INFO("sql.updates", ">> Renaming update \"%s\" to \"%s\" \'%s\'.",
+ hashIter->second.c_str(), availableQuery.first.filename().string().c_str(), hash.substr(0, 7).c_str());
+
+ RenameEntry(hashIter->second, availableQuery.first.filename().string());
+ applied.erase(hashIter->second);
+ continue;
+ }
+ }
+ // Apply the update if it was never seen before.
+ else
+ {
+ TC_LOG_INFO("sql.updates", ">> Applying update \"%s\" \'%s\'...",
+ availableQuery.first.filename().string().c_str(), hash.substr(0, 7).c_str());
+ }
+ }
+ // Rehash the update entry if it is contained in our database but with an empty hash.
+ else if (allowRehash && iter->second.hash.empty())
+ {
+ mode = MODE_REHASH;
+
+ TC_LOG_INFO("sql.updates", ">> Re-hashing update \"%s\" \'%s\'...", availableQuery.first.filename().string().c_str(),
+ hash.substr(0, 7).c_str());
+ }
+ else
+ {
+ // If the hash of the files differs from the one stored in our database reapply the update (because it was changed).
+ if (iter->second.hash != hash)
+ {
+ TC_LOG_INFO("sql.updates", ">> Reapplying update \"%s\" \'%s\' -> \'%s\' (it changed)...", availableQuery.first.filename().string().c_str(),
+ iter->second.hash.substr(0, 7).c_str(), hash.substr(0, 7).c_str());
+ }
+ else
+ {
+ // If the file wasn't changed and just moved update its state if necessary.
+ if (iter->second.state != availableQuery.second)
+ {
+ TC_LOG_DEBUG("sql.updates", ">> Updating state of \"%s\" to \'%s\'...",
+ availableQuery.first.filename().string().c_str(), AppliedFileEntry::StateConvert(availableQuery.second).c_str());
+
+ UpdateState(availableQuery.first.filename().string(), availableQuery.second);
+ }
+
+ TC_LOG_DEBUG("sql.updates", ">> Update is already applied and is matching hash \'%s\'.", hash.substr(0, 7).c_str());
+
+ applied.erase(iter);
+ continue;
+ }
+ }
+
+ uint32 speed = 0;
+ AppliedFileEntry const file = { availableQuery.first.filename().string(), hash, availableQuery.second, 0 };
+
+ switch (mode)
+ {
+ case MODE_APPLY:
+ speed = Apply(availableQuery.first);
+ /*no break*/
+ case MODE_REHASH:
+ UpdateEntry(file, speed);
+ break;
+ }
+
+ if (iter != applied.end())
+ applied.erase(iter);
+
+ if (mode == MODE_APPLY)
+ ++importedUpdates;
+ }
+
+ // Cleanup up orphaned entries if enabled
+ if (!applied.empty())
+ {
+ bool const doCleanup = (cleanDeadReferencesMaxCount < 0) || (applied.size() <= static_cast<size_t>(cleanDeadReferencesMaxCount));
+
+ for (auto const& entry : applied)
+ {
+ TC_LOG_WARN("sql.updates", ">> File \'%s\' was applied to the database but is missing in" \
+ " your update directory now!", entry.first.c_str());
+
+ if (doCleanup)
+ TC_LOG_INFO("sql.updates", "Deleting orphaned entry \'%s\'...", entry.first.c_str());
+ }
+
+ if (doCleanup)
+ CleanUp(applied);
+ else
+ {
+ TC_LOG_ERROR("sql.updates", "Cleanup is disabled! There are " SZFMTD " dirty files that were applied to your database " \
+ "but are now missing in your source directory!", applied.size());
+ }
+ }
+
+ return importedUpdates;
+}
+
+std::string UpdateFetcher::CalculateHash(SQLUpdate 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;
+ using ms = std::chrono::milliseconds;
+
+ // Benchmark query speed
+ auto const begin = Time::now();
+
+ // Update database
+ _applyFile(path);
+
+ // Return time the query took to apply
+ return std::chrono::duration_cast<ms>(Time::now() - begin).count();
+}
+
+void UpdateFetcher::UpdateEntry(AppliedFileEntry const& entry, uint32 const speed) const
+{
+ std::string const update = "REPLACE INTO `updates` (`name`, `hash`, `state`, `speed`) VALUES (\"" +
+ entry.name + "\", \"" + entry.hash + "\", \'" + entry.GetStateAsString() + "\', " + std::to_string(speed) + ")";
+
+ // Update database
+ _apply(update);
+}
+
+void UpdateFetcher::RenameEntry(std::string const& from, std::string const& to) const
+{
+ // Delete target if it exists
+ {
+ std::string const update = "DELETE FROM `updates` WHERE `name`=\"" + to + "\"";
+
+ // Update database
+ _apply(update);
+ }
+
+ // Rename
+ {
+ std::string const update = "UPDATE `updates` SET `name`=\"" + to + "\" WHERE `name`=\"" + from + "\"";
+
+ // Update database
+ _apply(update);
+ }
+}
+
+void UpdateFetcher::CleanUp(AppliedFileStorage const& storage) const
+{
+ if (storage.empty())
+ return;
+
+ std::stringstream update;
+ size_t remaining = storage.size();
+
+ update << "DELETE FROM `updates` WHERE `name` IN(";
+
+ for (auto const& entry : storage)
+ {
+ update << "\"" << entry.first << "\"";
+ if ((--remaining) > 0)
+ update << ", ";
+ }
+
+ update << ")";
+
+ // Update database
+ _apply(update.str());
+}
+
+void UpdateFetcher::UpdateState(std::string const& name, State const state) const
+{
+ std::string const update = "UPDATE `updates` SET `state`=\'" + AppliedFileEntry::StateConvert(state) + "\' WHERE `name`=\"" + name + "\"";
+
+ // Update database
+ _apply(update);
+}
diff --git a/src/server/shared/Updater/UpdateFetcher.h b/src/server/shared/Updater/UpdateFetcher.h
new file mode 100644
index 00000000000..094e353f274
--- /dev/null
+++ b/src/server/shared/Updater/UpdateFetcher.h
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef UpdateFetcher_h__
+#define UpdateFetcher_h__
+
+#include <DBUpdater.h>
+
+#include <functional>
+#include <string>
+#include <memory>
+#include <vector>
+
+class UpdateFetcher
+{
+ using Path = boost::filesystem::path;
+
+public:
+ UpdateFetcher(Path const& updateDirectory,
+ std::function<void(std::string const&)> const& apply,
+ std::function<void(Path const& path)> const& applyFile,
+ std::function<QueryResult(std::string const&)> const& retrieve);
+
+ uint32 Update(bool const redundancyChecks, bool const allowRehash,
+ bool const archivedRedundancy, int32 const cleanDeadReferencesMaxCount) const;
+
+private:
+ enum UpdateMode
+ {
+ MODE_APPLY,
+ MODE_REHASH
+ };
+
+ enum State
+ {
+ RELEASED,
+ ARCHIVED
+ };
+
+ struct AppliedFileEntry
+ {
+ std::string const name;
+
+ std::string const hash;
+
+ State const state;
+
+ uint64 const timestamp;
+
+ static inline State StateConvert(std::string const& state)
+ {
+ return (state == "RELEASED") ? RELEASED : ARCHIVED;
+ }
+
+ static inline std::string StateConvert(State const state)
+ {
+ return (state == RELEASED) ? "RELEASED" : "ARCHIVED";
+ }
+
+ std::string GetStateAsString() const
+ {
+ return StateConvert(state);
+ }
+ };
+
+ struct DirectoryEntry
+ {
+ Path const path;
+
+ State const state;
+ };
+
+ using LocaleFileEntry = std::pair<Path, State>;
+
+ struct PathCompare
+ {
+ inline bool operator() (LocaleFileEntry const& left, LocaleFileEntry const& right) const
+ {
+ return left.first.filename().string() < right.first.filename().string();
+ }
+ };
+
+ using LocaleFileStorage = std::set<LocaleFileEntry, PathCompare>;
+ using HashToFileNameStorage = std::unordered_map<std::string, std::string>;
+ using AppliedFileStorage = std::unordered_map<std::string, AppliedFileEntry>;
+ using DirectoryStorage = std::vector<UpdateFetcher::DirectoryEntry>;
+ using SQLUpdate = std::shared_ptr<std::string>;
+
+ LocaleFileStorage GetFileList() const;
+ void FillFileListRecursively(Path const& path, LocaleFileStorage& storage, State const state, uint32 const depth) const;
+
+ DirectoryStorage ReceiveIncludedDirectories() const;
+ AppliedFileStorage ReceiveAppliedFiles() const;
+
+ SQLUpdate ReadSQLUpdate(Path const& file) const;
+ std::string CalculateHash(SQLUpdate const& query) const;
+
+ uint32 Apply(Path const& path) const;
+
+ void UpdateEntry(AppliedFileEntry const& entry, uint32 const speed = 0) const;
+ void RenameEntry(std::string const& from, std::string const& to) const;
+ void CleanUp(AppliedFileStorage const& storage) const;
+
+ void UpdateState(std::string const& name, State const state) const;
+
+ Path const _sourceDirectory;
+
+ std::function<void(std::string const&)> const _apply;
+ std::function<void(Path const& path)> const _applyFile;
+ std::function<QueryResult(std::string const&)> const _retrieve;
+};
+
+#endif // UpdateFetcher_h__
diff --git a/src/server/shared/Utilities/StringFormat.h b/src/server/shared/Utilities/StringFormat.h
new file mode 100644
index 00000000000..70d9aefb14d
--- /dev/null
+++ b/src/server/shared/Utilities/StringFormat.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2008-2015 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 TRINITYCORE_STRING_FORMAT_H
+#define TRINITYCORE_STRING_FORMAT_H
+
+#include <format.h>
+
+namespace Trinity
+{
+ //! Default TC string format function
+ template<typename... Args>
+ inline std::string StringFormat(const char* fmt, Args const&... args)
+ {
+ return fmt::sprintf(fmt, args...);
+ }
+}
+
+#endif
diff --git a/src/server/worldserver/CMakeLists.txt b/src/server/worldserver/CMakeLists.txt
index 97180fb36a0..d3b2eba9698 100644
--- a/src/server/worldserver/CMakeLists.txt
+++ b/src/server/worldserver/CMakeLists.txt
@@ -47,6 +47,8 @@ include_directories(
${CMAKE_SOURCE_DIR}/dep/gsoap
${CMAKE_SOURCE_DIR}/dep/sockets/include
${CMAKE_SOURCE_DIR}/dep/SFMT
+ ${CMAKE_SOURCE_DIR}/dep/cppformat
+ ${CMAKE_SOURCE_DIR}/dep/process
${CMAKE_SOURCE_DIR}/src/server/collision
${CMAKE_SOURCE_DIR}/src/server/collision/Management
${CMAKE_SOURCE_DIR}/src/server/collision/Models
@@ -63,6 +65,7 @@ include_directories(
${CMAKE_SOURCE_DIR}/src/server/shared/Networking
${CMAKE_SOURCE_DIR}/src/server/shared/Packets
${CMAKE_SOURCE_DIR}/src/server/shared/Threading
+ ${CMAKE_SOURCE_DIR}/src/server/shared/Updater
${CMAKE_SOURCE_DIR}/src/server/shared/Utilities
${CMAKE_SOURCE_DIR}/src/server/game
${CMAKE_SOURCE_DIR}/src/server/game/Accounts
@@ -141,6 +144,8 @@ include_directories(
${VALGRIND_INCLUDE_DIR}
)
+GroupSources(${CMAKE_CURRENT_SOURCE_DIR})
+
add_executable(worldserver
${worldserver_SRCS}
${worldserver_PCH_SRC}
@@ -168,6 +173,7 @@ target_link_libraries(worldserver
g3dlib
gsoap
Detour
+ format
${JEMALLOC_LIBRARY}
${READLINE_LIBRARY}
${TERMCAP_LIBRARY}
diff --git a/src/server/worldserver/CommandLine/CliRunnable.cpp b/src/server/worldserver/CommandLine/CliRunnable.cpp
index 6e961922b0e..ad9ae28f712 100644
--- a/src/server/worldserver/CommandLine/CliRunnable.cpp
+++ b/src/server/worldserver/CommandLine/CliRunnable.cpp
@@ -23,21 +23,16 @@
#include "Common.h"
#include "ObjectMgr.h"
#include "World.h"
-#include "WorldSession.h"
#include "Configuration/Config.h"
-#include "AccountMgr.h"
-#include "Chat.h"
#include "CliRunnable.h"
-#include "Language.h"
#include "Log.h"
-#include "MapManager.h"
-#include "Player.h"
#include "Util.h"
#if PLATFORM != PLATFORM_WINDOWS
#include <readline/readline.h>
#include <readline/history.h>
+#include "Chat.h"
char* command_finder(const char* text, int state)
{
diff --git a/src/server/worldserver/Main.cpp b/src/server/worldserver/Main.cpp
index 7b47dba8759..fbf2c74ac0b 100644
--- a/src/server/worldserver/Main.cpp
+++ b/src/server/worldserver/Main.cpp
@@ -47,6 +47,7 @@
#include "SystemConfig.h"
#include "WorldSocket.h"
#include "WorldSocketMgr.h"
+#include "DatabaseLoader.h"
using namespace boost::program_options;
@@ -447,80 +448,15 @@ bool StartDB()
{
MySQL::Library_Init();
- std::string dbString;
- uint8 asyncThreads, synchThreads;
+ // Load databases
+ DatabaseLoader loader("server.worldserver", DatabaseLoader::DATABASE_NONE);
+ loader
+ .AddDatabase(WorldDatabase, "World")
+ .AddDatabase(CharacterDatabase, "Character")
+ .AddDatabase(LoginDatabase, "Login");
- dbString = sConfigMgr->GetStringDefault("WorldDatabaseInfo", "");
- if (dbString.empty())
- {
- TC_LOG_ERROR("server.worldserver", "World database not specified in configuration file");
- return false;
- }
-
- asyncThreads = uint8(sConfigMgr->GetIntDefault("WorldDatabase.WorkerThreads", 1));
- if (asyncThreads < 1 || asyncThreads > 32)
- {
- TC_LOG_ERROR("server.worldserver", "World database: invalid number of worker threads specified. "
- "Please pick a value between 1 and 32.");
- return false;
- }
-
- synchThreads = uint8(sConfigMgr->GetIntDefault("WorldDatabase.SynchThreads", 1));
- ///- Initialize the world database
- if (!WorldDatabase.Open(dbString, asyncThreads, synchThreads))
- {
- TC_LOG_ERROR("server.worldserver", "Cannot connect to world database %s", dbString.c_str());
+ if (!loader.Load())
return false;
- }
-
- ///- Get character database info from configuration file
- dbString = sConfigMgr->GetStringDefault("CharacterDatabaseInfo", "");
- if (dbString.empty())
- {
- TC_LOG_ERROR("server.worldserver", "Character database not specified in configuration file");
- return false;
- }
-
- asyncThreads = uint8(sConfigMgr->GetIntDefault("CharacterDatabase.WorkerThreads", 1));
- if (asyncThreads < 1 || asyncThreads > 32)
- {
- TC_LOG_ERROR("server.worldserver", "Character database: invalid number of worker threads specified. "
- "Please pick a value between 1 and 32.");
- return false;
- }
-
- synchThreads = uint8(sConfigMgr->GetIntDefault("CharacterDatabase.SynchThreads", 2));
-
- ///- Initialize the Character database
- if (!CharacterDatabase.Open(dbString, asyncThreads, synchThreads))
- {
- TC_LOG_ERROR("server.worldserver", "Cannot connect to Character database %s", dbString.c_str());
- return false;
- }
-
- ///- Get login database info from configuration file
- dbString = sConfigMgr->GetStringDefault("LoginDatabaseInfo", "");
- if (dbString.empty())
- {
- TC_LOG_ERROR("server.worldserver", "Login database not specified in configuration file");
- return false;
- }
-
- asyncThreads = uint8(sConfigMgr->GetIntDefault("LoginDatabase.WorkerThreads", 1));
- if (asyncThreads < 1 || asyncThreads > 32)
- {
- TC_LOG_ERROR("server.worldserver", "Login database: invalid number of worker threads specified. "
- "Please pick a value between 1 and 32.");
- return false;
- }
-
- synchThreads = uint8(sConfigMgr->GetIntDefault("LoginDatabase.SynchThreads", 1));
- ///- Initialise the login database
- if (!LoginDatabase.Open(dbString, asyncThreads, synchThreads))
- {
- TC_LOG_ERROR("server.worldserver", "Cannot connect to login database %s", dbString.c_str());
- return false;
- }
///- Get the realm Id from the configuration file
realmID = sConfigMgr->GetIntDefault("RealmID", 0);
diff --git a/src/server/worldserver/RemoteAccess/RASession.h b/src/server/worldserver/RemoteAccess/RASession.h
index d272f323c6a..efd2106fdd1 100644
--- a/src/server/worldserver/RemoteAccess/RASession.h
+++ b/src/server/worldserver/RemoteAccess/RASession.h
@@ -30,8 +30,6 @@ using boost::asio::ip::tcp;
const size_t bufferSize = 4096;
-#define BUFFER_SIZE 4096
-
class RASession : public std::enable_shared_from_this <RASession>
{
public:
diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist
index 010c73779bc..2758c8e39cd 100644
--- a/src/server/worldserver/worldserver.conf.dist
+++ b/src/server/worldserver/worldserver.conf.dist
@@ -11,6 +11,7 @@
# PERFORMANCE SETTINGS
# SERVER LOGGING
# SERVER SETTINGS
+# UPDATE SETTINGS
# WARDEN SETTINGS
# PLAYER INTERACTION
# CREATURE SETTINGS
@@ -1121,6 +1122,92 @@ BirthdayTime = 1222964635
###################################################################################################
###################################################################################################
+# UPDATE SETTINGS
+#
+# Updates.EnableDatabases
+# Description: A mask that describes which databases shall be updated.
+#
+# Following flags are available
+# DATABASE_LOGIN = 1, // Auth database
+# DATABASE_CHARACTER = 2, // Character database
+# DATABASE_WORLD = 4, // World database
+#
+# Default: 0 - (All Disabled)
+# 4 - (Enable world only)
+# 7 - (All enabled)
+
+Updates.EnableDatabases = 0
+
+#
+# Updates.SourcePath
+# Description: The path to your TrinityCore source directory.
+# If the path is left empty, built-in CMAKE_SOURCE_DIR is used.
+# Example: "../TrinityCore"
+# Default: ""
+
+Updates.SourcePath = ""
+
+#
+# Updates.SourcePath
+# Description: The path to your mysql cli binary.
+# If the path is left empty, built-in path from cmake is used.
+# Example: "C:/Program Files/MySQL/MySQL Server 5.6/bin/mysql.exe"
+# "mysql.exe"
+# "/usr/bin/mysql"
+# Default: ""
+
+Updates.MySqlCLIPath = ""
+
+#
+# Updates.AutoSetup
+# Description: Auto populate empty databases.
+# Default: 1 - (Enabled)
+# 0 - (Disabled)
+
+Updates.AutoSetup = 1
+
+#
+# Updates.Redundancy
+# Description: Perform data redundancy checks through hashing
+# to detect changes on sql updates and reapply it.
+# Default: 1 - (Enabled)
+# 0 - (Disabled)
+
+Updates.Redundancy = 1
+
+#
+# Updates.ArchivedRedundancy
+# Description: Check hashes of archived updates (slows down startup).
+# Default: 0 - (Disabled)
+# 1 - (Enabled)
+
+Updates.ArchivedRedundancy = 0
+
+#
+# Updates.AllowRehash
+# Description: Inserts the current file hash in the database if it is left empty.
+# Useful if you want to mark a file as applied but you don't know its hash.
+# Default: 1 - (Enabled)
+# 0 - (Disabled)
+
+Updates.AllowRehash = 1
+
+#
+# Updates.CleanDeadRefMaxCount
+# Description: Cleans dead/ orphaned references that occur if an update was removed or renamed and edited in one step.
+# It only starts the clean up if the count of the missing updates is below or equal the Updates.CleanDeadRefMaxCount value.
+# This way prevents erasing of the update history due to wrong source directory state (maybe wrong branch or bad revision).
+# Disable this if you want to know if the database is in a possible "dirty state".
+# Default: 3 - (Enabled)
+# 0 - (Disabled)
+# -1 - (Enabled - unlimited)
+
+Updates.CleanDeadRefMaxCount = 3
+
+#
+###################################################################################################
+
+###################################################################################################
# WARDEN SETTINGS
#
# Warden.Enabled
@@ -3173,8 +3260,10 @@ Logger.root=5,Console Server
Logger.server=3,Console Server
Logger.commands.gm=3,Console GM
Logger.sql.sql=5,Console DBErrors
+Logger.sql.updates=3,Console Server
#Logger.achievement=3,Console Server
+#Logger.addon=3,Console Server
#Logger.ahbot=3,Console Server
#Logger.auctionHouse=3,Console Server
#Logger.bg.arena=3,Console Server
@@ -3213,6 +3302,7 @@ Logger.sql.sql=5,Console DBErrors
#Logger.scripts.ai=3,Console Server
#Logger.server.authserver=3,Console Server
#Logger.spells=3,Console Server
+#Logger.spells.periodic=3,Console Server
#Logger.sql.dev=3,Console Server
#Logger.sql.driver=3,Console Server
#Logger.warden=3,Console Server