diff options
Diffstat (limited to 'src')
87 files changed, 2179 insertions, 1338 deletions
diff --git a/src/server/authserver/Main.cpp b/src/server/authserver/Main.cpp index c748e9d28a8..15ab1c38925 100644 --- a/src/server/authserver/Main.cpp +++ b/src/server/authserver/Main.cpp @@ -46,25 +46,52 @@ using namespace boost::program_options; # define _TRINITY_REALM_CONFIG "authserver.conf" #endif +#if PLATFORM == PLATFORM_WINDOWS +#include "ServiceWin32.h" +char serviceName[] = "authserver"; +char serviceLongName[] = "TrinityCore auth service"; +char serviceDescription[] = "TrinityCore World of Warcraft emulator auth service"; +/* +* -1 - not in service mode +* 0 - stopped +* 1 - running +* 2 - paused +*/ +int m_ServiceStatus = -1; + +boost::asio::deadline_timer* _serviceStatusWatchTimer; +void ServiceStatusWatcher(boost::system::error_code const& error); +#endif + bool StartDB(); void StopDB(); void SignalHandler(const boost::system::error_code& error, int signalNumber); void KeepDatabaseAliveHandler(const boost::system::error_code& error); -variables_map GetConsoleArguments(int argc, char** argv, std::string& configFile); +variables_map GetConsoleArguments(int argc, char** argv, std::string& configFile, std::string& configService); -boost::asio::io_service _ioService; -boost::asio::deadline_timer _dbPingTimer(_ioService); +boost::asio::io_service* _ioService; +boost::asio::deadline_timer* _dbPingTimer; uint32 _dbPingInterval; LoginDatabaseWorkerPool LoginDatabase; int main(int argc, char** argv) { std::string configFile = _TRINITY_REALM_CONFIG; - auto vm = GetConsoleArguments(argc, argv, configFile); + std::string configService; + auto vm = GetConsoleArguments(argc, argv, configFile, configService); // exit if help is enabled if (vm.count("help")) return 0; +#if PLATFORM == PLATFORM_WINDOWS + if (configService.compare("install") == 0) + return WinServiceInstall() == true ? 0 : 1; + else if (configService.compare("uninstall") == 0) + return WinServiceUninstall() == true ? 0 : 1; + else if (configService.compare("run") == 0) + return WinServiceRun() ? 0 : 1; +#endif + std::string configError; if (!sConfigMgr->LoadInitial(configFile, configError)) { @@ -95,13 +122,16 @@ int main(int argc, char** argv) if (!StartDB()) return 1; + _ioService = new boost::asio::io_service(); + // Get the list of realms for the server - sRealmList->Initialize(_ioService, sConfigMgr->GetIntDefault("RealmsStateUpdateDelay", 20)); + sRealmList->Initialize(*_ioService, sConfigMgr->GetIntDefault("RealmsStateUpdateDelay", 20)); if (sRealmList->size() == 0) { TC_LOG_ERROR("server.authserver", "No valid realms specified."); StopDB(); + delete _ioService; return 1; } @@ -111,15 +141,16 @@ int main(int argc, char** argv) { TC_LOG_ERROR("server.authserver", "Specified port out of allowed range (1-65535)"); StopDB(); + delete _ioService; return 1; } std::string bindIp = sConfigMgr->GetStringDefault("BindIP", "0.0.0.0"); - sAuthSocketMgr.StartNetwork(_ioService, bindIp, port); + sAuthSocketMgr.StartNetwork(*_ioService, bindIp, port); // Set signal handlers - boost::asio::signal_set signals(_ioService, SIGINT, SIGTERM); + boost::asio::signal_set signals(*_ioService, SIGINT, SIGTERM); #if PLATFORM == PLATFORM_WINDOWS signals.add(SIGBREAK); #endif @@ -130,20 +161,38 @@ int main(int argc, char** argv) // Enabled a timed callback for handling the database keep alive ping _dbPingInterval = sConfigMgr->GetIntDefault("MaxPingTime", 30); - _dbPingTimer.expires_from_now(boost::posix_time::minutes(_dbPingInterval)); - _dbPingTimer.async_wait(KeepDatabaseAliveHandler); + _dbPingTimer = new boost::asio::deadline_timer(*_ioService); + _dbPingTimer->expires_from_now(boost::posix_time::minutes(_dbPingInterval)); + _dbPingTimer->async_wait(KeepDatabaseAliveHandler); + +#if PLATFORM == PLATFORM_WINDOWS + if (m_ServiceStatus != -1) + { + _serviceStatusWatchTimer = new boost::asio::deadline_timer(*_ioService); + _serviceStatusWatchTimer->expires_from_now(boost::posix_time::seconds(1)); + _serviceStatusWatchTimer->async_wait(ServiceStatusWatcher); + } +#endif // Start the io service worker loop - _ioService.run(); + _ioService->run(); + + _dbPingTimer->cancel(); + + sAuthSocketMgr.StopNetwork(); // Close the Database Pool and library StopDB(); TC_LOG_INFO("server.authserver", "Halting process..."); + + signals.cancel(); + + delete _dbPingTimer; + delete _ioService; return 0; } - /// Initialize connection to the database bool StartDB() { @@ -174,7 +223,7 @@ void StopDB() void SignalHandler(const boost::system::error_code& error, int /*signalNumber*/) { if (!error) - _ioService.stop(); + _ioService->stop(); } void KeepDatabaseAliveHandler(const boost::system::error_code& error) @@ -184,31 +233,58 @@ void KeepDatabaseAliveHandler(const boost::system::error_code& error) TC_LOG_INFO("server.authserver", "Ping MySQL to keep connection alive"); LoginDatabase.KeepAlive(); - _dbPingTimer.expires_from_now(boost::posix_time::minutes(_dbPingInterval)); - _dbPingTimer.async_wait(KeepDatabaseAliveHandler); + _dbPingTimer->expires_from_now(boost::posix_time::minutes(_dbPingInterval)); + _dbPingTimer->async_wait(KeepDatabaseAliveHandler); } } -variables_map GetConsoleArguments(int argc, char** argv, std::string& configFile) +#if PLATFORM == PLATFORM_WINDOWS +void ServiceStatusWatcher(boost::system::error_code const& error) +{ + if (!error) + { + if (m_ServiceStatus == 0) + { + _ioService->stop(); + delete _serviceStatusWatchTimer; + } + else + { + _serviceStatusWatchTimer->expires_from_now(boost::posix_time::seconds(1)); + _serviceStatusWatchTimer->async_wait(ServiceStatusWatcher); + } + } +} +#endif + +variables_map GetConsoleArguments(int argc, char** argv, std::string& configFile, std::string& configService) { options_description all("Allowed options"); all.add_options() ("help,h", "print usage message") ("config,c", value<std::string>(&configFile)->default_value(_TRINITY_REALM_CONFIG), "use <arg> as configuration file") ; +#if PLATFORM == PLATFORM_WINDOWS + options_description win("Windows platform specific options"); + win.add_options() + ("service,s", value<std::string>(&configService)->default_value(""), "Windows service options: [install | uninstall]") + ; + + all.add(win); +#endif variables_map variablesMap; try { store(command_line_parser(argc, argv).options(all).allow_unregistered().run(), variablesMap); notify(variablesMap); } - catch (std::exception& e) { + catch (std::exception& e) + { std::cerr << e.what() << "\n"; } - if (variablesMap.count("help")) { + if (variablesMap.count("help")) std::cout << all << "\n"; - } return variablesMap; } diff --git a/src/server/game/AI/CoreAI/UnitAI.h b/src/server/game/AI/CoreAI/UnitAI.h index 9eafcc30c81..efe55830b1b 100644 --- a/src/server/game/AI/CoreAI/UnitAI.h +++ b/src/server/game/AI/CoreAI/UnitAI.h @@ -128,7 +128,7 @@ class UnitAI virtual void InitializeAI() { if (!me->isDead()) Reset(); } - virtual void Reset() { }; + virtual void Reset() { } // Called when unit is charmed virtual void OnCharmed(bool apply) = 0; diff --git a/src/server/game/AI/SmartScripts/SmartAI.cpp b/src/server/game/AI/SmartScripts/SmartAI.cpp index 20a7ca05d93..21a15fa4f99 100644 --- a/src/server/game/AI/SmartScripts/SmartAI.cpp +++ b/src/server/game/AI/SmartScripts/SmartAI.cpp @@ -581,7 +581,11 @@ void SmartAI::JustDied(Unit* killer) { GetScript()->ProcessEventsFor(SMART_EVENT_DEATH, killer); if (HasEscortState(SMART_ESCORT_ESCORTING)) + { EndPath(true); + me->StopMoving();//force stop + me->GetMotionMaster()->MoveIdle(); + } } void SmartAI::KilledUnit(Unit* victim) diff --git a/src/server/game/AI/SmartScripts/SmartScript.h b/src/server/game/AI/SmartScripts/SmartScript.h index a3d75f1889b..51628eded54 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.h +++ b/src/server/game/AI/SmartScripts/SmartScript.h @@ -247,7 +247,14 @@ class SmartScript DecPhase(abs(p)); } - void DecPhase(int32 p = 1) { mEventPhase -= (mEventPhase < (uint32)p ? (uint32)p - mEventPhase : (uint32)p); } + void DecPhase(int32 p = 1) + { + if(mEventPhase > (uint32)p) + mEventPhase -= (uint32)p; + else + mEventPhase = 0; + } + bool IsInPhase(uint32 p) const { return ((1 << (mEventPhase - 1)) & p) != 0; } void SetPhase(uint32 p = 0) { mEventPhase = p; } diff --git a/src/server/game/Accounts/RBAC.h b/src/server/game/Accounts/RBAC.h index 8f9db8d5a27..339788dee01 100644 --- a/src/server/game/Accounts/RBAC.h +++ b/src/server/game/Accounts/RBAC.h @@ -802,6 +802,7 @@ class RBACData * @return Success or failure (with reason) to grant the permission * * Example Usage: + * @code * // previously defined "RBACData* rbac" with proper initialization * uint32 permissionId = 2; * if (rbac->GrantRole(permissionId) == RBAC_IN_DENIED_LIST) @@ -825,6 +826,7 @@ class RBACData * @return Success or failure (with reason) to deny the permission * * Example Usage: + * @code * // previously defined "RBACData* rbac" with proper initialization * uint32 permissionId = 2; * if (rbac->DenyRole(permissionId) == RBAC_ID_DOES_NOT_EXISTS) @@ -849,6 +851,7 @@ class RBACData * @return Success or failure (with reason) to remove the permission * * Example Usage: + * @code * // previously defined "RBACData* rbac" with proper initialization * uint32 permissionId = 2; * if (rbac->RevokeRole(permissionId) == RBAC_OK) @@ -939,9 +942,6 @@ class RBACData * * Given a list of permissions, gets all the inherited permissions * @param permissions The list of permissions to expand - * - * @return new list of permissions containing original permissions and - * all other pemissions that are linked to the original ones */ void ExpandPermissions(RBACPermissionContainer& permissions); diff --git a/src/server/game/Battlegrounds/BattlegroundMgr.cpp b/src/server/game/Battlegrounds/BattlegroundMgr.cpp index 95a51f6d915..8e5766407f1 100644 --- a/src/server/game/Battlegrounds/BattlegroundMgr.cpp +++ b/src/server/game/Battlegrounds/BattlegroundMgr.cpp @@ -514,7 +514,7 @@ void BattlegroundMgr::LoadBattlegroundTemplates() _battlegroundTemplates.clear(); // 0 1 2 3 4 5 6 7 8 9 10 11 - QueryResult result = WorldDatabase.Query("SELECT id, MinPlayersPerTeam, MaxPlayersPerTeam, MinLvl, MaxLvl, AllianceStartLoc, AllianceStartO, HordeStartLoc, HordeStartO, StartMaxDist, Weight, ScriptName FROM battleground_template"); + QueryResult result = WorldDatabase.Query("SELECT ID, MinPlayersPerTeam, MaxPlayersPerTeam, MinLvl, MaxLvl, AllianceStartLoc, AllianceStartO, HordeStartLoc, HordeStartO, StartMaxDist, Weight, ScriptName FROM battleground_template"); if (!result) { TC_LOG_ERROR("server.loading", ">> Loaded 0 battlegrounds. DB table `battleground_template` is empty."); diff --git a/src/server/game/Battlegrounds/BattlegroundQueue.cpp b/src/server/game/Battlegrounds/BattlegroundQueue.cpp index d9db2a9b5d1..43b7acde925 100644 --- a/src/server/game/Battlegrounds/BattlegroundQueue.cpp +++ b/src/server/game/Battlegrounds/BattlegroundQueue.cpp @@ -889,7 +889,8 @@ void BattlegroundQueue::BattlegroundQueueUpdate(uint32 /*diff*/, BattlegroundTyp // (after what time the ratings aren't taken into account when making teams) then // the discard time is current_time - time_to_discard, teams that joined after that, will have their ratings taken into account // else leave the discard time on 0, this way all ratings will be discarded - uint32 discardTime = getMSTime() - sBattlegroundMgr->GetRatingDiscardTimer(); + // this has to be signed value - when the server starts, this value would be negative and thus overflow + int32 discardTime = getMSTime() - sBattlegroundMgr->GetRatingDiscardTimer(); // we need to find 2 teams which will play next game GroupsQueueType::iterator itr_teams[BG_TEAMS_COUNT]; @@ -905,7 +906,7 @@ void BattlegroundQueue::BattlegroundQueueUpdate(uint32 /*diff*/, BattlegroundTyp // if group match conditions, then add it to pool if (!(*itr2)->IsInvitedToBGInstanceGUID && (((*itr2)->ArenaMatchmakerRating >= arenaMinRating && (*itr2)->ArenaMatchmakerRating <= arenaMaxRating) - || (*itr2)->JoinTime < discardTime)) + || (int32)(*itr2)->JoinTime < discardTime)) { itr_teams[found++] = itr2; team = i; @@ -923,7 +924,7 @@ void BattlegroundQueue::BattlegroundQueueUpdate(uint32 /*diff*/, BattlegroundTyp { if (!(*itr3)->IsInvitedToBGInstanceGUID && (((*itr3)->ArenaMatchmakerRating >= arenaMinRating && (*itr3)->ArenaMatchmakerRating <= arenaMaxRating) - || (*itr3)->JoinTime < discardTime) + || (int32)(*itr3)->JoinTime < discardTime) && (*itr_teams[0])->ArenaTeamId != (*itr3)->ArenaTeamId) { itr_teams[found++] = itr3; diff --git a/src/server/game/Battlegrounds/BattlegroundQueue.h b/src/server/game/Battlegrounds/BattlegroundQueue.h index b0adaa4078d..7e8debfd24d 100644 --- a/src/server/game/Battlegrounds/BattlegroundQueue.h +++ b/src/server/game/Battlegrounds/BattlegroundQueue.h @@ -106,7 +106,7 @@ class BattlegroundQueue class SelectionPool { public: - SelectionPool(): PlayerCount(0) { }; + SelectionPool(): PlayerCount(0) { } void Init(); bool AddGroup(GroupQueueInfo* ginfo, uint32 desiredCount); bool KickGroup(uint32 size); diff --git a/src/server/game/Chat/Channels/Channel.h b/src/server/game/Chat/Channels/Channel.h index 9b9c2f1e514..0f2a940e3b4 100644 --- a/src/server/game/Chat/Channels/Channel.h +++ b/src/server/game/Chat/Channels/Channel.h @@ -184,7 +184,7 @@ class Channel void DeVoice(ObjectGuid guid1, ObjectGuid guid2); void JoinNotify(ObjectGuid guid); // invisible notify void LeaveNotify(ObjectGuid guid); // invisible notify - void SetOwnership(bool ownership) { _ownership = ownership; }; + void SetOwnership(bool ownership) { _ownership = ownership; } static void CleanOldChannelsInDB(); private: diff --git a/src/server/game/Chat/Chat.cpp b/src/server/game/Chat/Chat.cpp index 1716aa73525..3cbdcbcaff1 100644 --- a/src/server/game/Chat/Chat.cpp +++ b/src/server/game/Chat/Chat.cpp @@ -78,6 +78,7 @@ ChatCommand* ChatHandler::getCommandTable() // cache top-level commands size_t added = 0; + free(commandTableCache); commandTableCache = (ChatCommand*)malloc(sizeof(ChatCommand) * total); ASSERT(commandTableCache); memset(commandTableCache, 0, sizeof(ChatCommand) * total); diff --git a/src/server/game/Conditions/ConditionMgr.cpp b/src/server/game/Conditions/ConditionMgr.cpp index 25fbef2ca86..b05f9ac2a0d 100644 --- a/src/server/game/Conditions/ConditionMgr.cpp +++ b/src/server/game/Conditions/ConditionMgr.cpp @@ -1535,6 +1535,9 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) if (!((1 << i) & cond->SourceGroup)) continue; + if (spellInfo->Effects[i].ChainTarget > 0) + continue; + switch (spellInfo->Effects[i].TargetA.GetSelectionCategory()) { case TARGET_SELECT_CATEGORY_NEARBY: @@ -1555,7 +1558,7 @@ bool ConditionMgr::isSourceTypeValid(Condition* cond) break; } - TC_LOG_ERROR("sql.sql", "SourceEntry %u SourceGroup %u in `condition` table - spell %u does not have implicit targets of types: _AREA_, _CONE_, _NEARBY_ for effect %u, SourceGroup needs correction, ignoring.", cond->SourceEntry, origGroup, cond->SourceEntry, uint32(i)); + TC_LOG_ERROR("sql.sql", "SourceEntry %u SourceGroup %u in `condition` table - spell %u does not have implicit targets of types: _AREA_, _CONE_, _NEARBY_, __CHAIN__ for effect %u, SourceGroup needs correction, ignoring.", cond->SourceEntry, origGroup, cond->SourceEntry, uint32(i)); cond->SourceGroup &= ~(1 << i); } // all effects were removed, no need to add the condition at all diff --git a/src/server/game/DungeonFinding/LFGMgr.cpp b/src/server/game/DungeonFinding/LFGMgr.cpp index f07e4e7113f..59eedaaffed 100644 --- a/src/server/game/DungeonFinding/LFGMgr.cpp +++ b/src/server/game/DungeonFinding/LFGMgr.cpp @@ -194,11 +194,12 @@ void LFGMgr::LoadLFGDungeons(bool reload /* = false */) } // Fill teleport locations from DB - QueryResult result = WorldDatabase.Query("SELECT dungeonId, position_x, position_y, position_z, orientation FROM lfg_entrances"); + // 0 1 2 3 4 + QueryResult result = WorldDatabase.Query("SELECT dungeonId, position_x, position_y, position_z, orientation FROM lfg_dungeon_template"); if (!result) { - TC_LOG_ERROR("server.loading", ">> Loaded 0 lfg entrance positions. DB table `lfg_entrances` is empty!"); + TC_LOG_ERROR("server.loading", ">> Loaded 0 lfg entrance positions. DB table `lfg_dungeon_template` is empty!"); return; } @@ -211,7 +212,7 @@ void LFGMgr::LoadLFGDungeons(bool reload /* = false */) LFGDungeonContainer::iterator dungeonItr = LfgDungeonStore.find(dungeonId); if (dungeonItr == LfgDungeonStore.end()) { - TC_LOG_ERROR("sql.sql", "table `lfg_entrances` contains coordinates for wrong dungeon %u", dungeonId); + TC_LOG_ERROR("sql.sql", "table `lfg_dungeon_template` contains coordinates for wrong dungeon %u", dungeonId); continue; } @@ -410,6 +411,8 @@ void LFGMgr::JoinLfg(Player* player, uint8 roles, LfgDungeonSet& dungeons, const joinData.result = LFG_JOIN_RANDOM_COOLDOWN; else if (dungeons.empty()) joinData.result = LFG_JOIN_NOT_MEET_REQS; + else if (player->HasAura(9454)) // check Freeze debuff + joinData.result = LFG_JOIN_NOT_MEET_REQS; else if (grp) { if (grp->GetMembersCount() > MAXGROUPSIZE) @@ -429,6 +432,8 @@ void LFGMgr::JoinLfg(Player* player, uint8 roles, LfgDungeonSet& dungeons, const joinData.result = LFG_JOIN_PARTY_RANDOM_COOLDOWN; else if (plrg->InBattleground() || plrg->InArena() || plrg->InBattlegroundQueue()) joinData.result = LFG_JOIN_USING_BG_SYSTEM; + else if (plrg->HasAura(9454)) // check Freeze debuff + joinData.result = LFG_JOIN_PARTY_NOT_MEET_REQS; ++memberCount; players.insert(plrg->GetGUID()); } @@ -1281,6 +1286,8 @@ void LFGMgr::TeleportPlayer(Player* player, bool out, bool fromOpcode /*= false* error = LFG_TELEPORTERROR_IN_VEHICLE; else if (player->GetCharmGUID()) error = LFG_TELEPORTERROR_CHARMING; + else if (player->HasAura(9454)) // check Freeze debuff + error = LFG_TELEPORTERROR_INVALID_LOCATION; else if (player->GetMapId() != uint32(dungeon->map)) // Do not teleport players in dungeon to the entrance { uint32 mapid = dungeon->map; diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index 7f00fc7f9d8..a91bbf00735 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -1370,9 +1370,6 @@ bool Creature::CanStartAttack(Unit const* who, bool force) const if (IsCivilian()) return false; - if (HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_NPC)) - return false; - // Do not attack non-combat pets if (who->GetTypeId() == TYPEID_UNIT && who->GetCreatureType() == CREATURE_TYPE_NON_COMBAT_PET) return false; @@ -1510,11 +1507,11 @@ void Creature::setDeathState(DeathState s) SetUInt32Value(UNIT_NPC_FLAGS, cinfo->npcflag); ClearUnitState(uint32(UNIT_STATE_ALL_STATE & ~UNIT_STATE_IGNORE_PATHFINDING)); SetMeleeDamageSchool(SpellSchools(cinfo->dmgschool)); - LoadCreaturesAddon(true); Motion_Initialize(); if (GetCreatureData() && GetPhaseMask() != GetCreatureData()->phaseMask) SetPhaseMask(GetCreatureData()->phaseMask, false); Unit::setDeathState(ALIVE); + LoadCreaturesAddon(true); } } @@ -2415,7 +2412,7 @@ bool Creature::SetSwim(bool enable) return true; } -bool Creature::SetCanFly(bool enable) +bool Creature::SetCanFly(bool enable, bool /*packetOnly = false */) { if (!Unit::SetCanFly(enable)) return false; @@ -2638,3 +2635,29 @@ void Creature::StartPickPocketRefillTimer() _pickpocketLootRestore = time(NULL) + sWorld->getIntConfig(CONFIG_CREATURE_PICKPOCKET_REFILL); } +void Creature::SetTextRepeatId(uint8 textGroup, uint8 id) +{ + CreatureTextRepeatIds& repeats = m_textRepeat[textGroup]; + if (std::find(repeats.begin(), repeats.end(), id) == repeats.end()) + repeats.push_back(id); + else + TC_LOG_ERROR("sql.sql", "CreatureTextMgr: TextGroup %u for Creature(%s) GuidLow %u Entry %u, id %u already added", uint32(textGroup), GetName().c_str(), GetGUIDLow(), GetEntry(), uint32(id)); +} + +CreatureTextRepeatIds Creature::GetTextRepeatGroup(uint8 textGroup) +{ + CreatureTextRepeatIds ids; + + CreatureTextRepeatGroup::const_iterator groupItr = m_textRepeat.find(textGroup); + if (groupItr != m_textRepeat.end()) + ids = groupItr->second; + + return ids; +} + +void Creature::ClearTextRepeatGroup(uint8 textGroup) +{ + CreatureTextRepeatGroup::iterator groupItr = m_textRepeat.find(textGroup); + if (groupItr != m_textRepeat.end()) + groupItr->second.clear(); +} diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index 6f82d5dda4a..585bc137e0b 100644 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -409,6 +409,10 @@ struct TrainerSpellData #define MAX_VENDOR_ITEMS 150 // Limitation in 3.x.x item count in SMSG_LIST_INVENTORY +//used for handling non-repeatable random texts +typedef std::vector<uint8> CreatureTextRepeatIds; +typedef std::unordered_map<uint8, CreatureTextRepeatIds> CreatureTextRepeatGroup; + class Creature : public Unit, public GridObject<Creature>, public MapObject { public: @@ -472,7 +476,7 @@ class Creature : public Unit, public GridObject<Creature>, public MapObject bool SetWalk(bool enable) override; bool SetDisableGravity(bool disable, bool packetOnly = false) override; bool SetSwim(bool enable) override; - bool SetCanFly(bool enable) override; + bool SetCanFly(bool enable, bool packetOnly = false) override; bool SetWaterWalking(bool enable, bool packetOnly = false) override; bool SetFeatherFall(bool enable, bool packetOnly = false) override; bool SetHover(bool enable, bool packetOnly = false) override; @@ -656,6 +660,10 @@ class Creature : public Unit, public GridObject<Creature>, public MapObject void FocusTarget(Spell const* focusSpell, WorldObject const* target); void ReleaseFocus(Spell const* focusSpell); + CreatureTextRepeatIds GetTextRepeatGroup(uint8 textGroup); + void SetTextRepeatId(uint8 textGroup, uint8 id); + void ClearTextRepeatGroup(uint8 textGroup); + protected: bool CreateFromProto(uint32 guidlow, uint32 entry, CreatureData const* data = nullptr, uint32 vehId = 0); bool InitEntry(uint32 entry, CreatureData const* data = nullptr); @@ -720,6 +728,8 @@ class Creature : public Unit, public GridObject<Creature>, public MapObject bool TriggerJustRespawned; Spell const* _focusSpell; ///> Locks the target during spell cast for proper facing + + CreatureTextRepeatGroup m_textRepeat; }; class AssistDelayEvent : public BasicEvent diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 030c2a25110..275dbf92dca 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -26251,9 +26251,9 @@ bool Player::SetDisableGravity(bool disable, bool packetOnly /*= false*/) return true; } -bool Player::SetCanFly(bool apply) +bool Player::SetCanFly(bool apply, bool packetOnly /*= false*/) { - if (!Unit::SetCanFly(apply)) + if (!packetOnly && !Unit::SetCanFly(apply)) return false; WorldPacket data(apply ? SMSG_MOVE_SET_CAN_FLY : SMSG_MOVE_UNSET_CAN_FLY, 12); diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index af640e4c73c..98b9d8a3d07 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -346,9 +346,9 @@ struct Runes struct EnchantDuration { - EnchantDuration() : item(NULL), slot(MAX_ENCHANTMENT_SLOT), leftduration(0) { }; + EnchantDuration() : item(NULL), slot(MAX_ENCHANTMENT_SLOT), leftduration(0) { } EnchantDuration(Item* _item, EnchantmentSlot _slot, uint32 _leftduration) : item(_item), slot(_slot), - leftduration(_leftduration){ ASSERT(item); }; + leftduration(_leftduration){ ASSERT(item); } Item* item; EnchantmentSlot slot; @@ -1664,7 +1664,7 @@ class Player : public Unit, public GridObject<Player> void setResurrectRequestData(ObjectGuid guid, uint32 mapId, float X, float Y, float Z, uint32 health, uint32 mana); void clearResurrectRequestData() { setResurrectRequestData(ObjectGuid::Empty, 0, 0.0f, 0.0f, 0.0f, 0, 0); } - bool isResurrectRequestedBy(ObjectGuid guid) const { return m_resurrectGUID == guid; } + bool isResurrectRequestedBy(ObjectGuid guid) const { return !m_resurrectGUID.IsEmpty() && m_resurrectGUID == guid; } bool isResurrectRequested() const { return !m_resurrectGUID.IsEmpty(); } void ResurrectUsingRequestData(); @@ -1839,7 +1839,7 @@ class Player : public Unit, public GridObject<Player> bool UpdatePosition(const Position &pos, bool teleport = false) { return UpdatePosition(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation(), teleport); } void UpdateUnderwaterState(Map* m, float x, float y, float z) override; - void SendMessageToSet(WorldPacket* data, bool self) override {SendMessageToSetInRange(data, GetVisibilityRange(), self); };// overwrite Object::SendMessageToSet + void SendMessageToSet(WorldPacket* data, bool self) override {SendMessageToSetInRange(data, GetVisibilityRange(), self); }// overwrite Object::SendMessageToSet void SendMessageToSetInRange(WorldPacket* data, float fist, bool self) override;// overwrite Object::SendMessageToSetInRange void SendMessageToSetInRange(WorldPacket* data, float dist, bool self, bool own_team_only); void SendMessageToSet(WorldPacket* data, Player const* skipped_rcvr) override; @@ -2301,7 +2301,7 @@ class Player : public Unit, public GridObject<Player> void RemoveFromWhisperWhiteList(ObjectGuid guid) { WhisperList.remove(guid); } bool SetDisableGravity(bool disable, bool packetOnly /* = false */) override; - bool SetCanFly(bool apply) override; + bool SetCanFly(bool apply, bool packetOnly = false) override; bool SetWaterWalking(bool apply, bool packetOnly = false) override; bool SetFeatherFall(bool apply, bool packetOnly = false) override; bool SetHover(bool enable, bool packetOnly = false) override; diff --git a/src/server/game/Entities/Transport/Transport.cpp b/src/server/game/Entities/Transport/Transport.cpp index 85dccddf186..6d98a4c78b2 100644 --- a/src/server/game/Entities/Transport/Transport.cpp +++ b/src/server/game/Entities/Transport/Transport.cpp @@ -226,7 +226,7 @@ void Transport::Update(uint32 diff) sScriptMgr->OnTransportUpdate(this, diff); } -void Transport::DelayedUpdate(uint32 diff) +void Transport::DelayedUpdate(uint32 /*diff*/) { if (GetKeyFrames().size() <= 1) return; diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 219ee8b1002..9b0da57fa31 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -9949,11 +9949,15 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin DoneTotal += int32(DoneAdvertisedBenefit * coeff * factorMod); } - // Done Percentage for DOT is already calculated, no need to do it again. The percentage mod is applied in Aura::HandleAuraSpecificMods. - float tmpDamage = (int32(pdamage) + DoneTotal) * (damagetype == DOT ? 1.0f : SpellDamagePctDone(victim, spellProto, damagetype)); - // apply spellmod to Done damage (flat and pct) - if (Player* modOwner = GetSpellModOwner()) - modOwner->ApplySpellMod(spellProto->Id, damagetype == DOT ? SPELLMOD_DOT : SPELLMOD_DAMAGE, tmpDamage); + float tmpDamage = float(int32(pdamage) + DoneTotal); + // SPELLMOD_DOT will be applied in AuraEffect::HandlePeriodicDamageAurasTick. + if (damagetype != DOT) + { + tmpDamage *= SpellDamagePctDone(victim, spellProto, damagetype); + // apply spellmod to Done damage (flat and pct) + if (Player* modOwner = GetSpellModOwner()) + modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_DAMAGE, tmpDamage); + } return uint32(std::max(tmpDamage, 0.0f)); } @@ -10793,11 +10797,15 @@ uint32 Unit::SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, ui DoneTotal = 0; } - // Done Percentage for DOT is already calculated, no need to do it again. The percentage mod is applied in Aura::HandleAuraSpecificMods. - float heal = float(int32(healamount) + DoneTotal) * (damagetype == DOT ? 1.0f : SpellHealingPctDone(victim, spellProto)); - // apply spellmod to Done amount - if (Player* modOwner = GetSpellModOwner()) - modOwner->ApplySpellMod(spellProto->Id, damagetype == DOT ? SPELLMOD_DOT : SPELLMOD_DAMAGE, heal); + float heal = float(int32(healamount) + DoneTotal); + // SPELLMOD_DOT will be applied in AuraEffect::HandlePeriodicHealAurasTick. + if (damagetype != DOT) + { + heal *= SpellHealingPctDone(victim, spellProto); + // apply spellmod to Done amount + if (Player* modOwner = GetSpellModOwner()) + modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_DAMAGE, heal); + } return uint32(std::max(heal, 0.0f)); } @@ -12286,6 +12294,13 @@ void Unit::UpdateSpeed(UnitMoveType mtype, bool forced) /// @todo possible affect only on MOVE_RUN if (int32 normalization = GetMaxPositiveAuraModifier(SPELL_AURA_USE_NORMAL_MOVEMENT_SPEED)) { + if (Creature* creature = ToCreature()) + { + uint32 immuneMask = creature->GetCreatureTemplate()->MechanicImmuneMask; + if (immuneMask & (1 << MECHANIC_SNARE) || immuneMask & (1 << MECHANIC_DAZE)) + break; + } + // Use speed from aura float max_speed = normalization / (IsControlledByPlayer() ? playerBaseMoveSpeed[mtype] : baseMoveSpeed[mtype]); if (speed > max_speed) @@ -16440,7 +16455,7 @@ void Unit::KnockbackFrom(float x, float y, float speedXY, float speedZ) float vcos, vsin; GetSinCos(x, y, vsin, vcos); - WorldPacket data(SMSG_MOVE_KNOCK_BACK, (8+4+4+4+4+4)); + WorldPacket data(SMSG_MOVE_KNOCK_BACK, (8 + 4 + 4 + 4 + 4 + 4)); data << GetPackGUID(); data << uint32(0); // counter data << float(vcos); // x direction @@ -16449,6 +16464,9 @@ void Unit::KnockbackFrom(float x, float y, float speedXY, float speedZ) data << float(-speedZ); // Z Movement speed (vertical) player->GetSession()->SendPacket(&data); + + if (player->HasAuraType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED) || player->HasAuraType(SPELL_AURA_FLY)) + player->SetCanFly(true, true); } } @@ -17507,7 +17525,7 @@ bool Unit::SetSwim(bool enable) return true; } -bool Unit::SetCanFly(bool enable) +bool Unit::SetCanFly(bool enable, bool /*packetOnly = false */) { if (enable == HasUnitMovementFlag(MOVEMENTFLAG_CAN_FLY)) return false; diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 088a0bbdf73..2593ca2c728 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -273,13 +273,6 @@ enum UnitRename #define MAX_AGGRO_RESET_TIME 10 // in seconds #define MAX_AGGRO_RADIUS 45.0f // yards -enum Swing -{ - NOSWING = 0, - SINGLEHANDEDSWING = 1, - TWOHANDEDSWING = 2 -}; - enum VictimState { VICTIMSTATE_INTACT = 0, // set when attacker misses @@ -356,7 +349,7 @@ class TransportBase; class SpellCastTargets; typedef std::list<Unit*> UnitList; -typedef std::list< std::pair<Aura*, uint8> > DispelChargesList; +typedef std::list<std::pair<Aura*, uint8>> DispelChargesList; struct SpellImmune { @@ -381,13 +374,6 @@ enum WeaponDamageRange MAXDAMAGE }; -enum DamageTypeToSchool -{ - RESISTANCE, - DAMAGE_DEALT, - DAMAGE_TAKEN -}; - enum AuraRemoveMode { AURA_REMOVE_NONE = 0, @@ -1583,7 +1569,7 @@ class Unit : public WorldObject virtual bool SetWalk(bool enable); virtual bool SetDisableGravity(bool disable, bool packetOnly = false); virtual bool SetSwim(bool enable); - virtual bool SetCanFly(bool enable); + virtual bool SetCanFly(bool enable, bool packetOnly = false); virtual bool SetWaterWalking(bool enable, bool packetOnly = false); virtual bool SetFeatherFall(bool enable, bool packetOnly = false); virtual bool SetHover(bool enable, bool packetOnly = false); @@ -1896,7 +1882,7 @@ class Unit : public WorldObject void TauntApply(Unit* victim); void TauntFadeOut(Unit* taunter); ThreatManager& getThreatManager() { return m_ThreatManager; } - void addHatedBy(HostileReference* pHostileReference) { m_HostileRefManager.insertFirst(pHostileReference); }; + void addHatedBy(HostileReference* pHostileReference) { m_HostileRefManager.insertFirst(pHostileReference); } void removeHatedBy(HostileReference* /*pHostileReference*/) { /* nothing to do yet */ } HostileRefManager& getHostileRefManager() { return m_HostileRefManager; } diff --git a/src/server/game/Events/GameEventMgr.h b/src/server/game/Events/GameEventMgr.h index a47b6f29e80..eb29e463a4d 100644 --- a/src/server/game/Events/GameEventMgr.h +++ b/src/server/game/Events/GameEventMgr.h @@ -96,7 +96,7 @@ class GameEventMgr { private: GameEventMgr(); - ~GameEventMgr() { }; + ~GameEventMgr() { } public: static GameEventMgr* instance() diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index a3414c72613..b9d828b2dfd 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -1057,12 +1057,12 @@ void ObjectMgr::LoadGameObjectAddons() { Field* fields = result->Fetch(); - ObjectGuid::LowType guid = fields[0].GetUInt64(); + ObjectGuid::LowType guid = fields[0].GetUInt32(); const GameObjectData* goData = GetGOData(guid); if (!goData) { - TC_LOG_ERROR("sql.sql", "GameObject (GUID: " UI64FMTD ") does not exist but has a record in `gameobject_addon`", guid); + TC_LOG_ERROR("sql.sql", "GameObject (GUID: %u) does not exist but has a record in `gameobject_addon`", guid); continue; } @@ -1072,14 +1072,14 @@ void ObjectMgr::LoadGameObjectAddons() if (gameObjectAddon.invisibilityType >= TOTAL_INVISIBILITY_TYPES) { - TC_LOG_ERROR("sql.sql", "GameObject (GUID: " UI64FMTD ") has invalid InvisibilityType in `gameobject_addon`", guid); + TC_LOG_ERROR("sql.sql", "GameObject (GUID: %u) has invalid InvisibilityType in `gameobject_addon`", guid); gameObjectAddon.invisibilityType = INVISIBILITY_GENERAL; gameObjectAddon.InvisibilityValue = 0; } if (gameObjectAddon.invisibilityType && !gameObjectAddon.InvisibilityValue) { - TC_LOG_ERROR("sql.sql", "GameObject (GUID: " UI64FMTD ") has InvisibilityType set but has no InvisibilityValue in `gameobject_addon`, set to 1", guid); + TC_LOG_ERROR("sql.sql", "GameObject (GUID: %u) has InvisibilityType set but has no InvisibilityValue in `gameobject_addon`, set to 1", guid); gameObjectAddon.InvisibilityValue = 1; } @@ -1147,8 +1147,8 @@ void ObjectMgr::LoadEquipmentTemplates() { uint32 oldMSTime = getMSTime(); - // 0 1 2 3 4 - QueryResult result = WorldDatabase.Query("SELECT entry, id, itemEntry1, itemEntry2, itemEntry3 FROM creature_equip_template"); + // 0 1 2 3 4 + QueryResult result = WorldDatabase.Query("SELECT CreatureID, ID, ItemID1, ItemID2, ItemID3 FROM creature_equip_template"); if (!result) { @@ -1283,8 +1283,8 @@ CreatureModelInfo const* ObjectMgr::GetCreatureModelRandomGender(uint32* display void ObjectMgr::LoadCreatureModelInfo() { uint32 oldMSTime = getMSTime(); - - QueryResult result = WorldDatabase.Query("SELECT modelid, bounding_radius, combat_reach, gender, modelid_other_gender FROM creature_model_info"); + // 0 1 2 3 4 + QueryResult result = WorldDatabase.Query("SELECT DisplayID, BoundingRadius, CombatReach, Gender, DisplayID_Other_Gender FROM creature_model_info"); if (!result) { @@ -3800,8 +3800,8 @@ void ObjectMgr::LoadPlayerInfo() for (uint8 level = 0; level < sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL); ++level) _playerXPperLevel[level] = 0; - // 0 1 - QueryResult result = WorldDatabase.Query("SELECT lvl, xp_for_next_level FROM player_xp_for_level"); + // 0 1 + QueryResult result = WorldDatabase.Query("SELECT Level, Experience FROM player_xp_for_level"); if (!result) { @@ -3965,26 +3965,26 @@ void ObjectMgr::LoadQuests() mExclusiveQuestGroups.clear(); QueryResult result = WorldDatabase.Query("SELECT " - //0 1 2 3 4 5 6 7 8 9 10 11 12 - "Id, Method, Level, MinLevel, MaxLevel, ZoneOrSort, Type, SuggestedPlayers, LimitTime, RequiredClasses, RequiredRaces, RequiredSkillId, RequiredSkillPoints, " + //0 1 2 3 4 5 6 7 8 9 10 11 12 + "ID, Method, QuestLevel, MinLevel, MaxLevel, QuestSortID, QuestType, SuggestedGroupNum, LimitTime, RequiredClasses, RequiredRaces, RequiredSkillId, RequiredSkillPoints, " // 13 14 15 16 17 18 19 20 "RequiredFactionId1, RequiredFactionId2, RequiredFactionValue1, RequiredFactionValue2, RequiredMinRepFaction, RequiredMaxRepFaction, RequiredMinRepValue, RequiredMaxRepValue, " // 21 22 23 24 25 26 27 28 29 30 31 "PrevQuestId, NextQuestId, ExclusiveGroup, NextQuestIdChain, RewardXPId, RewardOrRequiredMoney, RewardMoneyMaxLevel, RewardSpell, RewardSpellCast, RewardHonor, RewardHonorMultiplier, " // 32 33 34 35 36 37 38 39 40 41 42 - "RewardMailTemplateId, RewardMailDelay, SourceItemId, SourceItemCount, SourceSpellId, Flags, SpecialFlags, RewardTitleId, RequiredPlayerKills, RewardTalents, RewardArenaPoints, " - // 43 44 45 46 47 48 49 50 - "RewardItemId1, RewardItemId2, RewardItemId3, RewardItemId4, RewardItemCount1, RewardItemCount2, RewardItemCount3, RewardItemCount4, " - // 51 52 53 54 55 56 57 58 59 60 61 62 - "RewardChoiceItemId1, RewardChoiceItemId2, RewardChoiceItemId3, RewardChoiceItemId4, RewardChoiceItemId5, RewardChoiceItemId6, RewardChoiceItemCount1, RewardChoiceItemCount2, RewardChoiceItemCount3, RewardChoiceItemCount4, RewardChoiceItemCount5, RewardChoiceItemCount6, " - // 63 64 65 66 67 68 69 70 71 72 - "RewardFactionId1, RewardFactionId2, RewardFactionId3, RewardFactionId4, RewardFactionId5, RewardFactionValueId1, RewardFactionValueId2, RewardFactionValueId3, RewardFactionValueId4, RewardFactionValueId5, " + "RewardMailTemplateId, RewardMailDelay, SourceItemId, SourceItemCount, SourceSpellId, Flags, SpecialFlags, RewardTitle, RequiredPlayerKills, RewardTalents, RewardArenaPoints, " + // 43 44 45 46 47 48 49 50 + "RewardItem1, RewardItem2, RewardItem3, RewardItem4, RewardAmount1, RewardAmount2, RewardAmount3, RewardAmount4, " + // 51 52 53 54 55 56 57 58 59 60 61 62 + "RewardChoiceItemID1, RewardChoiceItemID2, RewardChoiceItemID3, RewardChoiceItemID4, RewardChoiceItemID5, RewardChoiceItemID6, RewardChoiceItemQuantity1, RewardChoiceItemQuantity2, RewardChoiceItemQuantity3, RewardChoiceItemQuantity4, RewardChoiceItemQuantity5, RewardChoiceItemQuantity6, " + // 63 64 65 66 67 68 69 70 71 72 + "RewardFactionID1, RewardFactionID2, RewardFactionID3, RewardFactionID4, RewardFactionID5, RewardFactionValue1, RewardFactionValue2, RewardFactionValue3, RewardFactionValue4, RewardFactionValue5, " // 73 74 75 76 77 - "RewardFactionValueIdOverride1, RewardFactionValueIdOverride2, RewardFactionValueIdOverride3, RewardFactionValueIdOverride4, RewardFactionValueIdOverride5, " + "RewardFactionOverride1, RewardFactionOverride2, RewardFactionOverride3, RewardFactionOverride4, RewardFactionOverride5, " // 78 79 80 81 "PointMapId, PointX, PointY, PointOption, " - // 82 83 84 85 86 87 88 - "Title, Objectives, Details, EndText, OfferRewardText, RequestItemsText, CompletedText, " + // 82 83 84 85 86 87 88 + "LogTitle, LogDescription, QuestDescription, EndText, OfferRewardText, RequestItemsText, QuestCompletionLog, " // 89 90 91 92 93 94 95 96 "RequiredNpcOrGo1, RequiredNpcOrGo2, RequiredNpcOrGo3, RequiredNpcOrGo4, RequiredNpcOrGoCount1, RequiredNpcOrGoCount2, RequiredNpcOrGoCount3, RequiredNpcOrGoCount4, " // 97 98 99 100 101 102 103 104 @@ -5178,8 +5178,8 @@ void ObjectMgr::LoadPageTexts() { uint32 oldMSTime = getMSTime(); - // 0 1 2 - QueryResult result = WorldDatabase.Query("SELECT entry, text, next_page FROM page_text"); + // 0 1 2 + QueryResult result = WorldDatabase.Query("SELECT ID, Text, NextPageID FROM page_text"); if (!result) { @@ -5392,14 +5392,14 @@ void ObjectMgr::LoadGossipText() uint32 oldMSTime = getMSTime(); QueryResult result = WorldDatabase.Query("SELECT ID, " - "text0_0, text0_1, BroadcastTextID0, lang0, prob0, em0_0, em0_1, em0_2, em0_3, em0_4, em0_5, " - "text1_0, text1_1, BroadcastTextID1, lang1, prob1, em1_0, em1_1, em1_2, em1_3, em1_4, em1_5, " - "text2_0, text2_1, BroadcastTextID2, lang2, prob2, em2_0, em2_1, em2_2, em2_3, em2_4, em2_5, " - "text3_0, text3_1, BroadcastTextID3, lang3, prob3, em3_0, em3_1, em3_2, em3_3, em3_4, em3_5, " - "text4_0, text4_1, BroadcastTextID4, lang4, prob4, em4_0, em4_1, em4_2, em4_3, em4_4, em4_5, " - "text5_0, text5_1, BroadcastTextID5, lang5, prob5, em5_0, em5_1, em5_2, em5_3, em5_4, em5_5, " - "text6_0, text6_1, BroadcastTextID6, lang6, prob6, em6_0, em6_1, em6_2, em6_3, em6_4, em6_5, " - "text7_0, text7_1, BroadcastTextID7, lang7, prob7, em7_0, em7_1, em7_2, em7_3, em7_4, em7_5 " + "text0_0, text0_1, BroadcastTextID0, lang0, Probability0, em0_0, em0_1, em0_2, em0_3, em0_4, em0_5, " + "text1_0, text1_1, BroadcastTextID1, lang1, Probability1, em1_0, em1_1, em1_2, em1_3, em1_4, em1_5, " + "text2_0, text2_1, BroadcastTextID2, lang2, Probability2, em2_0, em2_1, em2_2, em2_3, em2_4, em2_5, " + "text3_0, text3_1, BroadcastTextID3, lang3, Probability3, em3_0, em3_1, em3_2, em3_3, em3_4, em3_5, " + "text4_0, text4_1, BroadcastTextID4, lang4, Probability4, em4_0, em4_1, em4_2, em4_3, em4_4, em4_5, " + "text5_0, text5_1, BroadcastTextID5, lang5, Probability5, em5_0, em5_1, em5_2, em5_3, em5_4, em5_5, " + "text6_0, text6_1, BroadcastTextID6, lang6, Probability6, em6_0, em6_1, em6_2, em6_3, em6_4, em6_5, " + "text7_0, text7_1, BroadcastTextID7, lang7, Probability7, em7_0, em7_1, em7_2, em7_3, em7_4, em7_5 " "FROM npc_text"); @@ -6158,8 +6158,8 @@ void ObjectMgr::LoadAreaTriggerTeleports() _areaTriggerStore.clear(); // need for reload case - // 0 1 2 3 4 5 - QueryResult result = WorldDatabase.Query("SELECT id, target_map, target_position_x, target_position_y, target_position_z, target_orientation FROM areatrigger_teleport"); + // 0 1 2 3 4 5 + QueryResult result = WorldDatabase.Query("SELECT ID, target_map, target_position_x, target_position_y, target_position_z, target_orientation FROM areatrigger_teleport"); if (!result) { TC_LOG_INFO("server.loading", ">> Loaded 0 area trigger teleport definitions. DB table `areatrigger_teleport` is empty."); @@ -6599,9 +6599,9 @@ void ObjectMgr::LoadGameObjectTemplate() // 0 1 2 3 4 5 6 7 8 9 10 11 12 QueryResult result = WorldDatabase.Query("SELECT entry, type, displayId, name, IconName, castBarCaption, unk1, faction, flags, size, questItem1, questItem2, questItem3, " // 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 - "questItem4, questItem5, questItem6, data0, data1, data2, data3, data4, data5, data6, data7, data8, data9, data10, data11, data12, " + "questItem4, questItem5, questItem6, Data0, Data1, Data2, Data3, Data4, Data5, Data6, Data7, Data8, Data9, Data10, Data11, Data12, " // 29 30 31 32 33 34 35 36 37 38 39 40 41 - "data13, data14, data15, data16, data17, data18, data19, data20, data21, data22, data23, AIName, ScriptName " + "Data13, Data14, Data15, Data16, Data17, Data18, Data19, Data20, Data21, Data22, Data23, AIName, ScriptName " "FROM gameobject_template"); if (!result) @@ -7188,8 +7188,8 @@ void ObjectMgr::LoadPointsOfInterest() uint32 count = 0; - // 0 1 2 3 4 5 6 - QueryResult result = WorldDatabase.Query("SELECT entry, x, y, icon, flags, data, icon_name FROM points_of_interest"); + // 0 1 2 3 4 5 6 + QueryResult result = WorldDatabase.Query("SELECT ID, PositionX, PositionY, Icon, Flags, Data, Name FROM points_of_interest"); if (!result) { @@ -7234,8 +7234,8 @@ void ObjectMgr::LoadQuestPOI() uint32 count = 0; - // 0 1 2 3 4 5 6 7 - QueryResult result = WorldDatabase.Query("SELECT questId, id, objIndex, mapid, WorldMapAreaId, FloorId, unk3, unk4 FROM quest_poi order by questId"); + // 0 1 2 3 4 5 6 7 + QueryResult result = WorldDatabase.Query("SELECT QuestID, id, ObjectiveIndex, MapID, WorldMapAreaId, Floor, Priority, Flags FROM quest_poi order by QuestID"); if (!result) { @@ -7243,8 +7243,8 @@ void ObjectMgr::LoadQuestPOI() return; } - // 0 1 2 3 - QueryResult points = WorldDatabase.Query("SELECT questId, id, x, y FROM quest_poi_points ORDER BY questId DESC, idx"); + // 0 1 2 3 + QueryResult points = WorldDatabase.Query("SELECT QuestID, Idx1, X, Y FROM quest_poi_points ORDER BY QuestID DESC, Idx2"); std::vector<std::vector<std::vector<QuestPOIPoint> > > POIs; @@ -8217,9 +8217,9 @@ void ObjectMgr::LoadTrainerSpell() // For reload case _cacheTrainerSpellStore.clear(); - QueryResult result = WorldDatabase.Query("SELECT b.entry, a.spell, a.spellcost, a.reqskill, a.reqskillvalue, a.reqlevel FROM npc_trainer AS a " - "INNER JOIN npc_trainer AS b ON a.entry = -(b.spell) " - "UNION SELECT * FROM npc_trainer WHERE spell > 0"); + QueryResult result = WorldDatabase.Query("SELECT b.ID, a.SpellID, a.MoneyCost, a.ReqSkillLine, a.ReqSkillRank, a.ReqLevel FROM npc_trainer AS a " + "INNER JOIN npc_trainer AS b ON a.ID = -(b.SpellID) " + "UNION SELECT * FROM npc_trainer WHERE SpellID > 0"); if (!result) { diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp index ae8712510c9..2e81bdd1af8 100644 --- a/src/server/game/Groups/Group.cpp +++ b/src/server/game/Groups/Group.cpp @@ -1857,6 +1857,9 @@ GroupJoinBattlegroundResult Group::CanJoinBattlegroundQueue(Battleground const* // check if someone in party is using dungeon system if (member->isUsingLfg()) return ERR_LFG_CANT_USE_BATTLEGROUND; + // check Freeze debuff + if (member->HasAura(9454)) + return ERR_BATTLEGROUND_JOIN_FAILED; } // only check for MinPlayerCount since MinPlayerCount == MaxPlayerCount for arenas... diff --git a/src/server/game/Groups/Group.h b/src/server/game/Groups/Group.h index 28e933bd08c..732afce9517 100644 --- a/src/server/game/Groups/Group.h +++ b/src/server/game/Groups/Group.h @@ -218,7 +218,7 @@ class Group ObjectGuid GetMasterLooterGuid() const; ItemQualities GetLootThreshold() const; - uint32 GetDbStoreId() const { return m_dbStoreId; }; + uint32 GetDbStoreId() const { return m_dbStoreId; } // member manipulation methods bool IsMember(ObjectGuid guid) const; diff --git a/src/server/game/Handlers/BattleGroundHandler.cpp b/src/server/game/Handlers/BattleGroundHandler.cpp index de23626eb25..2ec89ac2a26 100644 --- a/src/server/game/Handlers/BattleGroundHandler.cpp +++ b/src/server/game/Handlers/BattleGroundHandler.cpp @@ -178,6 +178,10 @@ void WorldSession::HandleBattlemasterJoinOpcode(WorldPacket& recvData) return; } + // check Freeze debuff + if (_player->HasAura(9454)) + return; + BattlegroundQueue& bgQueue = sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId); GroupQueueInfo* ginfo = bgQueue.AddGroup(_player, NULL, bgTypeId, bracketEntry, 0, false, isPremade, 0, 0); @@ -434,6 +438,10 @@ void WorldSession::HandleBattleFieldPortOpcode(WorldPacket &recvData) WorldPacket data; if (action) { + // check Freeze debuff + if (_player->HasAura(9454)) + return; + if (!_player->IsInvitedForBattlegroundQueueType(bgQueueTypeId)) return; // cheating? diff --git a/src/server/game/Maps/ZoneScript.h b/src/server/game/Maps/ZoneScript.h index d8dba57d438..fd52bdd4c14 100644 --- a/src/server/game/Maps/ZoneScript.h +++ b/src/server/game/Maps/ZoneScript.h @@ -29,8 +29,8 @@ class ZoneScript ZoneScript() { } virtual ~ZoneScript() { } - virtual uint32 GetCreatureEntry(uint32 /*guidlow*/, CreatureData const* data) { return data->id; } - virtual uint32 GetGameObjectEntry(uint32 /*guidlow*/, uint32 entry) { return entry; } + virtual uint32 GetCreatureEntry(ObjectGuid::LowType /*guidLow*/, CreatureData const* data) { return data->id; } + virtual uint32 GetGameObjectEntry(ObjectGuid::LowType /*guidLow*/, uint32 entry) { return entry; } virtual void OnCreatureCreate(Creature* ) { } virtual void OnCreatureRemove(Creature* ) { } diff --git a/src/server/game/Movement/MotionMaster.h b/src/server/game/Movement/MotionMaster.h index 0b547d96e7f..c8da50364ba 100644 --- a/src/server/game/Movement/MotionMaster.h +++ b/src/server/game/Movement/MotionMaster.h @@ -182,7 +182,7 @@ class MotionMaster //: private std::stack<MovementGenerator *> void MoveKnockbackFrom(float srcX, float srcY, float speedXY, float speedZ); void MoveJumpTo(float angle, float speedXY, float speedZ); 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); }; + { 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); diff --git a/src/server/game/Scripting/ScriptLoader.cpp b/src/server/game/Scripting/ScriptLoader.cpp index 8be5da91c32..f0ee013bcc2 100644 --- a/src/server/game/Scripting/ScriptLoader.cpp +++ b/src/server/game/Scripting/ScriptLoader.cpp @@ -622,6 +622,7 @@ void AddSC_instance_magtheridons_lair(); void AddSC_boss_grand_warlock_nethekurse(); //HC Shattered Halls void AddSC_boss_warbringer_omrogg(); void AddSC_boss_warchief_kargath_bladefist(); +void AddSC_shattered_halls(); void AddSC_instance_shattered_halls(); void AddSC_boss_watchkeeper_gargolmar(); //HC Ramparts void AddSC_boss_omor_the_unscarred(); @@ -1152,6 +1153,7 @@ void AddOutlandScripts() AddSC_boss_grand_warlock_nethekurse(); //HC Shattered Halls AddSC_boss_warbringer_omrogg(); AddSC_boss_warchief_kargath_bladefist(); + AddSC_shattered_halls(); AddSC_instance_shattered_halls(); AddSC_boss_watchkeeper_gargolmar(); //HC Ramparts AddSC_boss_omor_the_unscarred(); diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 378f5f0d622..918b000a557 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -5845,6 +5845,9 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const else damage = std::max(int32(damage * GetDonePct()), 0); + if (Player* modOwner = caster->GetSpellModOwner()) + modOwner->ApplySpellMod(GetSpellInfo()->Id, SPELLMOD_DOT, damage); + damage = target->SpellDamageBonusTaken(caster, GetSpellInfo(), damage, DOT, GetBase()->GetStackAmount()); // Calculate armor mitigation @@ -6148,6 +6151,9 @@ void AuraEffect::HandlePeriodicHealAurasTick(Unit* target, Unit* caster) const else damage = std::max(int32(damage * GetDonePct()), 0); + if (Player* modOwner = caster->GetSpellModOwner()) + modOwner->ApplySpellMod(GetSpellInfo()->Id, SPELLMOD_DOT, damage); + damage = target->SpellHealingBonusTaken(caster, GetSpellInfo(), damage, DOT, GetBase()->GetStackAmount()); } diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 94bb90487bc..ff7c6a86ae8 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -5060,12 +5060,12 @@ SpellCastResult Spell::CheckCast(bool strict) bool result = m_preGeneratedPath.CalculatePath(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ() + target->GetObjectSize(), false, true); if (m_preGeneratedPath.GetPathType() & PATHFIND_SHORT) return SPELL_FAILED_OUT_OF_RANGE; - else if (!result || m_preGeneratedPath.GetPathType() & PATHFIND_NOPATH) + else if (!result || m_preGeneratedPath.GetPathType() & (PATHFIND_NOPATH | PATHFIND_INCOMPLETE)) { result = m_preGeneratedPath.CalculatePath(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ() + target->GetObjectSize(), false, false); if (m_preGeneratedPath.GetPathType() & PATHFIND_SHORT) return SPELL_FAILED_OUT_OF_RANGE; - else if (!result || m_preGeneratedPath.GetPathType() & PATHFIND_NOPATH) + else if (!result || m_preGeneratedPath.GetPathType() & (PATHFIND_NOPATH | PATHFIND_INCOMPLETE)) return SPELL_FAILED_NOPATH; } diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp index 75a48e36ded..789b95e3e14 100644 --- a/src/server/game/Spells/SpellInfo.cpp +++ b/src/server/game/Spells/SpellInfo.cpp @@ -1614,7 +1614,7 @@ SpellCastResult SpellInfo::CheckTarget(Unit const* caster, WorldObject const* ta } // not allow casting on flying player - if (unitTarget->HasUnitState(UNIT_STATE_IN_FLIGHT)) + if (unitTarget->HasUnitState(UNIT_STATE_IN_FLIGHT) && !(AttributesCu & SPELL_ATTR0_CU_ALLOW_INFLIGHT_TARGET)) return SPELL_FAILED_BAD_TARGETS; /* TARGET_UNIT_MASTER gets blocked here for passengers, because the whole idea of this check is to diff --git a/src/server/game/Spells/SpellInfo.h b/src/server/game/Spells/SpellInfo.h index f2808a089e1..cfa9877405d 100644 --- a/src/server/game/Spells/SpellInfo.h +++ b/src/server/game/Spells/SpellInfo.h @@ -186,6 +186,7 @@ enum SpellCustomAttributes SPELL_ATTR0_CU_IGNORE_ARMOR = 0x00008000, SPELL_ATTR0_CU_REQ_TARGET_FACING_CASTER = 0x00010000, SPELL_ATTR0_CU_REQ_CASTER_BEHIND_TARGET = 0x00020000, + SPELL_ATTR0_CU_ALLOW_INFLIGHT_TARGET = 0x00040000, SPELL_ATTR0_CU_NEGATIVE = SPELL_ATTR0_CU_NEGATIVE_EFF0 | SPELL_ATTR0_CU_NEGATIVE_EFF1 | SPELL_ATTR0_CU_NEGATIVE_EFF2 }; diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index 13290320084..53b44fdd5cc 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -1609,8 +1609,8 @@ void SpellMgr::LoadSpellTargetPositions() mSpellTargetPositions.clear(); // need for reload case - // 0 1 2 3 4 5 6 - QueryResult result = WorldDatabase.Query("SELECT id, effIndex, target_map, target_position_x, target_position_y, target_position_z, target_orientation FROM spell_target_position"); + // 0 1 2 3 4 5 6 + QueryResult result = WorldDatabase.Query("SELECT ID, EffectIndex, MapID, PositionX, PositionY, PositionZ, Orientation FROM spell_target_position"); if (!result) { TC_LOG_INFO("server.loading", ">> Loaded 0 spell target coordinates. DB table `spell_target_position` is empty."); diff --git a/src/server/game/Spells/SpellScript.cpp b/src/server/game/Spells/SpellScript.cpp index b347a982132..09f557dc63b 100644 --- a/src/server/game/Spells/SpellScript.cpp +++ b/src/server/game/Spells/SpellScript.cpp @@ -641,8 +641,8 @@ SpellValue const* SpellScript::GetSpellValue() bool AuraScript::_Validate(SpellInfo const* entry) { for (std::list<CheckAreaTargetHandler>::iterator itr = DoCheckAreaTarget.begin(); itr != DoCheckAreaTarget.end(); ++itr) - if (!entry->HasAreaAuraEffect() && !entry->HasEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA)) - TC_LOG_ERROR("scripts", "Spell `%u` of script `%s` does not have area aura effect - handler bound to hook `DoCheckAreaTarget` of AuraScript won't be executed", entry->Id, m_scriptName->c_str()); + if (!entry->HasAreaAuraEffect() && !entry->HasEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA) && !entry->HasEffect(SPELL_EFFECT_APPLY_AURA)) + TC_LOG_ERROR("scripts", "Spell `%u` of script `%s` does not have apply aura effect - handler bound to hook `DoCheckAreaTarget` of AuraScript won't be executed", entry->Id, m_scriptName->c_str()); for (std::list<AuraDispelHandler>::iterator itr = OnDispel.begin(); itr != OnDispel.end(); ++itr) if (!entry->HasEffect(SPELL_EFFECT_APPLY_AURA) && !entry->HasAreaAuraEffect()) diff --git a/src/server/game/Texts/CreatureTextMgr.cpp b/src/server/game/Texts/CreatureTextMgr.cpp index 5fbc4b8ae1e..f9ccd2efd16 100644 --- a/src/server/game/Texts/CreatureTextMgr.cpp +++ b/src/server/game/Texts/CreatureTextMgr.cpp @@ -77,7 +77,7 @@ void CreatureTextMgr::LoadCreatureTexts() uint32 oldMSTime = getMSTime(); mTextMap.clear(); // for reload case - mTextRepeatMap.clear(); //reset all currently used temp texts + //all currently used temp texts are NOT reset PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_CREATURE_TEXT); PreparedQueryResult result = WorldDatabase.Query(stmt); @@ -224,13 +224,7 @@ uint32 CreatureTextMgr::SendChat(Creature* source, uint8 textGroup, WorldObject if (tempGroup.empty()) { - CreatureTextRepeatMap::iterator mapItr = mTextRepeatMap.find(source->GetGUID()); - if (mapItr != mTextRepeatMap.end()) - { - CreatureTextRepeatGroup::iterator groupItr = mapItr->second.find(textGroup); - groupItr->second.clear(); - } - + source->ClearTextRepeatGroup(textGroup); tempGroup = textGroupContainer; } @@ -426,26 +420,14 @@ void CreatureTextMgr::SetRepeatId(Creature* source, uint8 textGroup, uint8 id) if (!source) return; - CreatureTextRepeatIds& repeats = mTextRepeatMap[source->GetGUID()][textGroup]; - if (std::find(repeats.begin(), repeats.end(), id) == repeats.end()) - repeats.push_back(id); - else - TC_LOG_ERROR("sql.sql", "CreatureTextMgr: TextGroup %u for Creature(%s) GuidLow %u Entry %u, id %u already added", uint32(textGroup), source->GetName().c_str(), source->GetGUIDLow(), source->GetEntry(), uint32(id)); + source->SetTextRepeatId(textGroup, id); } CreatureTextRepeatIds CreatureTextMgr::GetRepeatGroup(Creature* source, uint8 textGroup) { ASSERT(source);//should never happen - CreatureTextRepeatIds ids; - CreatureTextRepeatMap::const_iterator mapItr = mTextRepeatMap.find(source->GetGUID()); - if (mapItr != mTextRepeatMap.end()) - { - CreatureTextRepeatGroup::const_iterator groupItr = (*mapItr).second.find(textGroup); - if (groupItr != mapItr->second.end()) - ids = groupItr->second; - } - return ids; + return source->GetTextRepeatGroup(textGroup); } bool CreatureTextMgr::TextExist(uint32 sourceEntry, uint8 textGroup) diff --git a/src/server/game/Texts/CreatureTextMgr.h b/src/server/game/Texts/CreatureTextMgr.h index 6ee1e82ce66..237aedd49d0 100644 --- a/src/server/game/Texts/CreatureTextMgr.h +++ b/src/server/game/Texts/CreatureTextMgr.h @@ -75,11 +75,6 @@ typedef std::unordered_map<uint32, CreatureTextHolder> CreatureTextMap; // a typedef std::map<CreatureTextId, CreatureTextLocale> LocaleCreatureTextMap; -//used for handling non-repeatable random texts -typedef std::vector<uint8> CreatureTextRepeatIds; -typedef std::unordered_map<uint8, CreatureTextRepeatIds> CreatureTextRepeatGroup; -typedef std::unordered_map<ObjectGuid, CreatureTextRepeatGroup> CreatureTextRepeatMap;//guid based - class CreatureTextMgr { private: @@ -115,7 +110,6 @@ class CreatureTextMgr float GetRangeForChatType(ChatMsg msgType) const; CreatureTextMap mTextMap; - CreatureTextRepeatMap mTextRepeatMap; LocaleCreatureTextMap mLocaleTextMap; }; diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 5f54154fab1..c4b2eb768c6 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -1711,6 +1711,9 @@ void World::SetInitialWorldSettings() TC_LOG_INFO("server.loading", "Loading faction change spell pairs..."); sObjectMgr->LoadFactionChangeSpells(); + TC_LOG_INFO("server.loading", "Loading faction change quest pairs..."); + sObjectMgr->LoadFactionChangeQuests(); + TC_LOG_INFO("server.loading", "Loading faction change item pairs..."); sObjectMgr->LoadFactionChangeItems(); diff --git a/src/server/scripts/Commands/cs_npc.cpp b/src/server/scripts/Commands/cs_npc.cpp index 390be999d9d..09a41fd82b5 100644 --- a/src/server/scripts/Commands/cs_npc.cpp +++ b/src/server/scripts/Commands/cs_npc.cpp @@ -370,28 +370,13 @@ public: uint32 lowGuid = atoi((char*)guidStr); - Creature* creature = NULL; - - /* FIXME: impossible without entry - if (lowguid) - creature = ObjectAccessor::GetCreature(*handler->GetSession()->GetPlayer(), MAKE_GUID(lowguid, HIGHGUID_UNIT)); - */ - // attempt check creature existence by DB data - if (!creature) - { - CreatureData const* data = sObjectMgr->GetCreatureData(lowGuid); - if (!data) - { - handler->PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowGuid); - handler->SetSentErrorMessage(true); - return false; - } - } - else + CreatureData const* data = sObjectMgr->GetCreatureData(lowGuid); + if (!data) { - // obtain real GUID for DB operations - lowGuid = creature->GetDBTableGUIDLow(); + handler->PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowGuid); + handler->SetSentErrorMessage(true); + return false; } int wait = waitStr ? atoi(waitStr) : 0; @@ -407,18 +392,6 @@ public: WorldDatabase.Execute(stmt); - if (creature && creature->GetWaypointPath()) - { - creature->SetDefaultMovementType(WAYPOINT_MOTION_TYPE); - creature->GetMotionMaster()->Initialize(); - if (creature->IsAlive()) // dead creature will reset movement generator at respawn - { - creature->setDeathState(JUST_DIED); - creature->Respawn(true); - } - creature->SaveToDB(); - } - handler->SendSysMessage(LANG_WAYPOINT_ADDED); return true; @@ -830,34 +803,22 @@ public: lowguid = atoi(cId); - /* FIXME: impossible without entry - if (lowguid) - creature = ObjectAccessor::GetCreature(*handler->GetSession()->GetPlayer(), MAKE_GUID(lowguid, HIGHGUID_UNIT)); - */ - // Attempting creature load from DB data - if (!creature) + CreatureData const* data = sObjectMgr->GetCreatureData(lowguid); + if (!data) { - CreatureData const* data = sObjectMgr->GetCreatureData(lowguid); - if (!data) - { - handler->PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid); - handler->SetSentErrorMessage(true); - return false; - } + handler->PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid); + handler->SetSentErrorMessage(true); + return false; + } - uint32 map_id = data->mapid; + uint32 map_id = data->mapid; - if (handler->GetSession()->GetPlayer()->GetMapId() != map_id) - { - handler->PSendSysMessage(LANG_COMMAND_CREATUREATSAMEMAP, lowguid); - handler->SetSentErrorMessage(true); - return false; - } - } - else + if (handler->GetSession()->GetPlayer()->GetMapId() != map_id) { - lowguid = creature->GetDBTableGUIDLow(); + handler->PSendSysMessage(LANG_COMMAND_CREATUREATSAMEMAP, lowguid); + handler->SetSentErrorMessage(true); + return false; } } else diff --git a/src/server/scripts/Commands/cs_tele.cpp b/src/server/scripts/Commands/cs_tele.cpp index e488aa0e607..8e82f9980d3 100644 --- a/src/server/scripts/Commands/cs_tele.cpp +++ b/src/server/scripts/Commands/cs_tele.cpp @@ -319,7 +319,7 @@ public: } MapEntry const* map = sMapStore.LookupEntry(tele->mapId); - if (!map || map->IsBattlegroundOrArena()) + if (!map || (map->IsBattlegroundOrArena() && (me->GetMapId() != tele->mapId || !me->IsGameMaster()))) { handler->SendSysMessage(LANG_CANNOT_TELE_TO_BG); handler->SetSentErrorMessage(true); diff --git a/src/server/scripts/EasternKingdoms/SunkenTemple/instance_sunken_temple.cpp b/src/server/scripts/EasternKingdoms/SunkenTemple/instance_sunken_temple.cpp index 1d7e1594d05..ca944f7037b 100644 --- a/src/server/scripts/EasternKingdoms/SunkenTemple/instance_sunken_temple.cpp +++ b/src/server/scripts/EasternKingdoms/SunkenTemple/instance_sunken_temple.cpp @@ -102,7 +102,7 @@ public: } } - virtual void Update(uint32 /*diff*/) // correct order goes form 1-6 + virtual void Update(uint32 /*diff*/) override // correct order goes form 1-6 { switch (State) { diff --git a/src/server/scripts/EasternKingdoms/Uldaman/boss_archaedas.cpp b/src/server/scripts/EasternKingdoms/Uldaman/boss_archaedas.cpp index cae26735568..29002460b2a 100644 --- a/src/server/scripts/EasternKingdoms/Uldaman/boss_archaedas.cpp +++ b/src/server/scripts/EasternKingdoms/Uldaman/boss_archaedas.cpp @@ -202,7 +202,7 @@ class boss_archaedas : public CreatureScript DoMeleeAttackIfReady(); } - void JustDied (Unit* /*killer*/) + void JustDied (Unit* /*killer*/) override { instance->SetData(DATA_ANCIENT_DOOR, DONE); // open the vault door instance->SetData(DATA_MINIONS, SPECIAL); // deactivate his minions diff --git a/src/server/scripts/Kalimdor/ZulFarrak/instance_zulfarrak.cpp b/src/server/scripts/Kalimdor/ZulFarrak/instance_zulfarrak.cpp index 46e831b0f83..7bd197774bc 100644 --- a/src/server/scripts/Kalimdor/ZulFarrak/instance_zulfarrak.cpp +++ b/src/server/scripts/Kalimdor/ZulFarrak/instance_zulfarrak.cpp @@ -111,6 +111,7 @@ public: instance_zulfarrak_InstanceMapScript(Map* map) : InstanceScript(map) { SetHeaders(DataHeader); + GahzRillaEncounter = NOT_STARTED; PyramidPhase = 0; major_wave_Timer = 0; minor_wave_Timer = 0; diff --git a/src/server/scripts/Kalimdor/zone_moonglade.cpp b/src/server/scripts/Kalimdor/zone_moonglade.cpp index 704fefe2678..163620230ef 100644 --- a/src/server/scripts/Kalimdor/zone_moonglade.cpp +++ b/src/server/scripts/Kalimdor/zone_moonglade.cpp @@ -384,6 +384,8 @@ public: } PlayerGUID = player->GetGUID(); Start(true, false, PlayerGUID); + me->SetDisplayId(me->GetCreatureTemplate()->Modelid1); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); } return; } diff --git a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/instance_halls_of_reflection.cpp b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/instance_halls_of_reflection.cpp index 660a639487f..fabe54303b8 100644 --- a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/instance_halls_of_reflection.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/instance_halls_of_reflection.cpp @@ -196,7 +196,7 @@ class instance_halls_of_reflection : public InstanceMapScript } } - uint32 GetGameObjectEntry(uint32 /*guidLow*/, uint32 entry) override + uint32 GetGameObjectEntry(ObjectGuid::LowType /*guidLow*/, uint32 entry) override { if (!_teamInInstance) { diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp index 63082808e03..d7a580800bc 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp @@ -1060,8 +1060,8 @@ class spell_putricide_ooze_eruption_searcher : public SpellScriptLoader uint32 adhesiveId = sSpellMgr->GetSpellIdForDifficulty(SPELL_VOLATILE_OOZE_ADHESIVE, GetCaster()); if (GetHitUnit()->HasAura(adhesiveId)) { - GetCaster()->CastSpell(GetHitUnit(), SPELL_OOZE_ERUPTION, true); GetHitUnit()->RemoveAurasDueToSpell(adhesiveId, GetCaster()->GetGUID(), 0, AURA_REMOVE_BY_ENEMY_SPELL); + GetCaster()->CastSpell(GetHitUnit(), SPELL_OOZE_ERUPTION, true); } } diff --git a/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp index 61848070170..1b823b4a452 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp @@ -317,7 +317,7 @@ class instance_icecrown_citadel : public InstanceMapScript } // Weekly quest spawn prevention - uint32 GetCreatureEntry(uint32 /*guidLow*/, CreatureData const* data) override + uint32 GetCreatureEntry(ObjectGuid::LowType /*guidLow*/, CreatureData const* data) override { uint32 entry = data->id; switch (entry) @@ -372,7 +372,7 @@ class instance_icecrown_citadel : public InstanceMapScript return entry; } - uint32 GetGameObjectEntry(uint32 /*guidLow*/, uint32 entry) override + uint32 GetGameObjectEntry(ObjectGuid::LowType /*guidLow*/, uint32 entry) override { switch (entry) { 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 181fb49ba2e..d0e4b7be63b 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp @@ -903,17 +903,15 @@ class boss_yogg_saron : public CreatureScript DoCast(me, SPELL_KNOCK_AWAY); me->ResetLootMode(); - switch (_instance->GetData(DATA_KEEPERS_COUNT)) - { - case 0: - me->AddLootMode(LOOT_MODE_HARD_MODE_4); - case 1: - me->AddLootMode(LOOT_MODE_HARD_MODE_3); - case 2: - me->AddLootMode(LOOT_MODE_HARD_MODE_2); - case 3: - me->AddLootMode(LOOT_MODE_HARD_MODE_1); - } + uint32 keepersCount = _instance->GetData(DATA_KEEPERS_COUNT); + if (keepersCount == 0) + me->AddLootMode(LOOT_MODE_HARD_MODE_4); + if (keepersCount <= 1) + me->AddLootMode(LOOT_MODE_HARD_MODE_3); + if (keepersCount <= 2) + me->AddLootMode(LOOT_MODE_HARD_MODE_2); + if (keepersCount <= 3) + me->AddLootMode(LOOT_MODE_HARD_MODE_1); } void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override diff --git a/src/server/scripts/Northrend/VioletHold/boss_cyanigosa.cpp b/src/server/scripts/Northrend/VioletHold/boss_cyanigosa.cpp index 36d2c5f8ed3..dc923e534b0 100644 --- a/src/server/scripts/Northrend/VioletHold/boss_cyanigosa.cpp +++ b/src/server/scripts/Northrend/VioletHold/boss_cyanigosa.cpp @@ -23,12 +23,9 @@ enum Spells { SPELL_ARCANE_VACUUM = 58694, SPELL_BLIZZARD = 58693, - H_SPELL_BLIZZARD = 59369, SPELL_MANA_DESTRUCTION = 59374, SPELL_TAIL_SWEEP = 58690, - H_SPELL_TAIL_SWEEP = 59283, SPELL_UNCONTROLLABLE_ENERGY = 58688, - H_SPELL_UNCONTROLLABLE_ENERGY = 59281, SPELL_TRANSFORM = 58668 }; @@ -48,17 +45,11 @@ class boss_cyanigosa : public CreatureScript public: boss_cyanigosa() : CreatureScript("boss_cyanigosa") { } - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI<boss_cyanigosaAI>(creature); - } - - struct boss_cyanigosaAI : public ScriptedAI + struct boss_cyanigosaAI : public BossAI { - boss_cyanigosaAI(Creature* creature) : ScriptedAI(creature) + boss_cyanigosaAI(Creature* creature) : BossAI(creature, DATA_CYANIGOSA) { Initialize(); - instance = creature->GetInstanceScript(); } void Initialize() @@ -76,24 +67,20 @@ public: uint32 uiTailSweepTimer; uint32 uiUncontrollableEnergyTimer; - InstanceScript* instance; - void Reset() override { Initialize(); - instance->SetData(DATA_CYANIGOSA_EVENT, NOT_STARTED); + BossAI::Reset(); } - void EnterCombat(Unit* /*who*/) override + void EnterCombat(Unit* who) override { + BossAI::EnterCombat(who); Talk(SAY_AGGRO); - - instance->SetData(DATA_CYANIGOSA_EVENT, IN_PROGRESS); } void MoveInLineOfSight(Unit* /*who*/) override { } - void UpdateAI(uint32 diff) override { if (instance->GetData(DATA_REMOVE_NPC) == 1) @@ -102,13 +89,12 @@ public: instance->SetData(DATA_REMOVE_NPC, 0); } - //Return since we have no target if (!UpdateVictim()) return; if (uiArcaneVacuumTimer <= diff) { - DoCast(SPELL_ARCANE_VACUUM); + DoCastAOE(SPELL_ARCANE_VACUUM); uiArcaneVacuumTimer = 10000; } else uiArcaneVacuumTimer -= diff; @@ -121,7 +107,7 @@ public: if (uiTailSweepTimer <= diff) { - DoCast(SPELL_TAIL_SWEEP); + DoCastVictim(SPELL_TAIL_SWEEP); uiTailSweepTimer = 20000; } else uiTailSweepTimer -= diff; @@ -144,22 +130,23 @@ public: DoMeleeAttackIfReady(); } - void JustDied(Unit* /*killer*/) override + void JustDied(Unit* killer) override { + BossAI::JustDied(killer); Talk(SAY_DEATH); - - instance->SetData(DATA_CYANIGOSA_EVENT, DONE); } void KilledUnit(Unit* victim) override { - if (victim->GetTypeId() != TYPEID_PLAYER) - return; - - Talk(SAY_SLAY); + if (victim->GetTypeId() == TYPEID_PLAYER) + Talk(SAY_SLAY); } }; + CreatureAI* GetAI(Creature* creature) const override + { + return GetInstanceAI<boss_cyanigosaAI>(creature); + } }; class achievement_defenseless : public AchievementCriteriaScript diff --git a/src/server/scripts/Northrend/VioletHold/boss_erekem.cpp b/src/server/scripts/Northrend/VioletHold/boss_erekem.cpp index e990b8796de..5c8d4b8691a 100644 --- a/src/server/scripts/Northrend/VioletHold/boss_erekem.cpp +++ b/src/server/scripts/Northrend/VioletHold/boss_erekem.cpp @@ -24,9 +24,7 @@ enum Spells SPELL_BLOODLUST = 54516, SPELL_BREAK_BONDS = 59463, SPELL_CHAIN_HEAL = 54481, - H_SPELL_CHAIN_HEAL = 59473, SPELL_EARTH_SHIELD = 54479, - H_SPELL_EARTH_SHIELD = 59471, SPELL_EARTH_SHOCK = 54511, SPELL_LIGHTNING_BOLT = 53044, SPELL_STORMSTRIKE = 51876 @@ -47,11 +45,6 @@ class boss_erekem : public CreatureScript public: boss_erekem() : CreatureScript("boss_erekem") { } - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI<boss_erekemAI>(creature); - } - struct boss_erekemAI : public ScriptedAI { boss_erekemAI(Creature* creature) : ScriptedAI(creature) @@ -81,9 +74,9 @@ public: { Initialize(); if (instance->GetData(DATA_WAVE_COUNT) == 6) - instance->SetData(DATA_1ST_BOSS_EVENT, NOT_STARTED); + instance->SetBossState(DATA_1ST_BOSS_EVENT, NOT_STARTED); else if (instance->GetData(DATA_WAVE_COUNT) == 12) - instance->SetData(DATA_2ND_BOSS_EVENT, NOT_STARTED); + instance->SetBossState(DATA_2ND_BOSS_EVENT, NOT_STARTED); if (Creature* pGuard1 = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_EREKEM_GUARD_1))) { @@ -129,25 +122,23 @@ public: Talk(SAY_AGGRO); DoCast(me, SPELL_EARTH_SHIELD); - if (GameObject* pDoor = instance->instance->GetGameObject(instance->GetGuidData(DATA_EREKEM_CELL))) - if (pDoor->GetGoState() == GO_STATE_READY) + if (GameObject* door = instance->GetGameObject(DATA_EREKEM_CELL)) + if (door->GetGoState() == GO_STATE_READY) { EnterEvadeMode(); return; } if (instance->GetData(DATA_WAVE_COUNT) == 6) - instance->SetData(DATA_1ST_BOSS_EVENT, IN_PROGRESS); + instance->SetBossState(DATA_1ST_BOSS_EVENT, IN_PROGRESS); else if (instance->GetData(DATA_WAVE_COUNT) == 12) - instance->SetData(DATA_2ND_BOSS_EVENT, IN_PROGRESS); + instance->SetBossState(DATA_2ND_BOSS_EVENT, IN_PROGRESS); } void MoveInLineOfSight(Unit* /*who*/) override { } - void UpdateAI(uint32 diff) override { - //Return since we have no target if (!UpdateVictim()) return; @@ -212,22 +203,20 @@ public: if (instance->GetData(DATA_WAVE_COUNT) == 6) { - instance->SetData(DATA_1ST_BOSS_EVENT, DONE); + instance->SetBossState(DATA_1ST_BOSS_EVENT, DONE); instance->SetData(DATA_WAVE_COUNT, 7); } else if (instance->GetData(DATA_WAVE_COUNT) == 12) { - instance->SetData(DATA_2ND_BOSS_EVENT, DONE); + instance->SetBossState(DATA_2ND_BOSS_EVENT, DONE); instance->SetData(DATA_WAVE_COUNT, 13); } } void KilledUnit(Unit* victim) override { - if (victim->GetTypeId() != TYPEID_PLAYER) - return; - - Talk(SAY_SLAY); + if (victim->GetTypeId() == TYPEID_PLAYER) + Talk(SAY_SLAY); } ObjectGuid GetChainHealTargetGUID() @@ -247,6 +236,10 @@ public: } }; + CreatureAI* GetAI(Creature* creature) const override + { + return GetInstanceAI<boss_erekemAI>(creature); + } }; enum GuardSpells @@ -261,11 +254,6 @@ class npc_erekem_guard : public CreatureScript public: npc_erekem_guard() : CreatureScript("npc_erekem_guard") { } - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI<npc_erekem_guardAI>(creature); - } - struct npc_erekem_guardAI : public ScriptedAI { npc_erekem_guardAI(Creature* creature) : ScriptedAI(creature) @@ -308,7 +296,6 @@ public: void MoveInLineOfSight(Unit* /*who*/) override { } - void UpdateAI(uint32 diff) override { if (!UpdateVictim()) @@ -336,6 +323,10 @@ public: } }; + CreatureAI* GetAI(Creature* creature) const override + { + return GetInstanceAI<npc_erekem_guardAI>(creature); + } }; void AddSC_boss_erekem() diff --git a/src/server/scripts/Northrend/VioletHold/boss_ichoron.cpp b/src/server/scripts/Northrend/VioletHold/boss_ichoron.cpp index 48fe8049d19..9be73febd52 100644 --- a/src/server/scripts/Northrend/VioletHold/boss_ichoron.cpp +++ b/src/server/scripts/Northrend/VioletHold/boss_ichoron.cpp @@ -23,19 +23,16 @@ enum Spells { SPELL_DRAINED = 59820, SPELL_FRENZY = 54312, - SPELL_FRENZY_H = 59522, SPELL_PROTECTIVE_BUBBLE = 54306, SPELL_WATER_BLAST = 54237, - SPELL_WATER_BLAST_H = 59520, SPELL_WATER_BOLT_VOLLEY = 54241, - SPELL_WATER_BOLT_VOLLEY_H = 59521, SPELL_SPLASH = 59516, SPELL_WATER_GLOBULE = 54268 }; enum IchoronCreatures { - NPC_ICHOR_GLOBULE = 29321, + NPC_ICHOR_GLOBULE = 29321 }; enum Yells @@ -52,18 +49,18 @@ enum Yells enum Actions { ACTION_WATER_ELEMENT_HIT = 1, - ACTION_WATER_ELEMENT_KILLED = 2, + ACTION_WATER_ELEMENT_KILLED = 2 }; /// @todo get those positions from spawn of creature 29326 #define MAX_SPAWN_LOC 5 -static Position SpawnLoc[MAX_SPAWN_LOC]= +static Position const SpawnLoc[MAX_SPAWN_LOC]= { {1840.64f, 795.407f, 44.079f, 1.676f}, {1886.24f, 757.733f, 47.750f, 5.201f}, {1877.91f, 845.915f, 43.417f, 3.560f}, {1918.97f, 850.645f, 47.225f, 4.136f}, - {1935.50f, 796.224f, 52.492f, 4.224f}, + {1935.50f, 796.224f, 52.492f, 4.224f} }; enum Misc @@ -76,11 +73,6 @@ class boss_ichoron : public CreatureScript public: boss_ichoron() : CreatureScript("boss_ichoron") { } - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI<boss_ichoronAI>(creature); - } - struct boss_ichoronAI : public ScriptedAI { boss_ichoronAI(Creature* creature) : ScriptedAI(creature), m_waterElements(creature) @@ -117,9 +109,9 @@ public: DespawnWaterElements(); if (instance->GetData(DATA_WAVE_COUNT) == 6) - instance->SetData(DATA_1ST_BOSS_EVENT, NOT_STARTED); + instance->SetBossState(DATA_1ST_BOSS_EVENT, NOT_STARTED); else if (instance->GetData(DATA_WAVE_COUNT) == 12) - instance->SetData(DATA_2ND_BOSS_EVENT, NOT_STARTED); + instance->SetBossState(DATA_2ND_BOSS_EVENT, NOT_STARTED); } void EnterCombat(Unit* /*who*/) override @@ -128,16 +120,17 @@ public: DoCast(me, SPELL_PROTECTIVE_BUBBLE); - if (GameObject* pDoor = instance->instance->GetGameObject(instance->GetGuidData(DATA_ICHORON_CELL))) - if (pDoor->GetGoState() == GO_STATE_READY) + if (GameObject* door = instance->GetGameObject(DATA_ICHORON_CELL)) + if (door->GetGoState() == GO_STATE_READY) { EnterEvadeMode(); return; } + if (instance->GetData(DATA_WAVE_COUNT) == 6) - instance->SetData(DATA_1ST_BOSS_EVENT, IN_PROGRESS); + instance->SetBossState(DATA_1ST_BOSS_EVENT, IN_PROGRESS); else if (instance->GetData(DATA_WAVE_COUNT) == 12) - instance->SetData(DATA_2ND_BOSS_EVENT, IN_PROGRESS); + instance->SetBossState(DATA_2ND_BOSS_EVENT, IN_PROGRESS); } void AttackStart(Unit* who) override @@ -208,7 +201,6 @@ public: void MoveInLineOfSight(Unit* /*who*/) override { } - void UpdateAI(uint32 uiDiff) override { if (!UpdateVictim()) @@ -230,7 +222,7 @@ public: if (!me->HasAura(SPELL_PROTECTIVE_BUBBLE)) { Talk(SAY_SHATTER); - DoCast(me, SPELL_WATER_BLAST); + DoCast(me, SPELL_WATER_BLAST); // wrong target DoCast(me, SPELL_DRAINED); bIsExploded = true; me->AttackStop(); @@ -291,12 +283,12 @@ public: if (instance->GetData(DATA_WAVE_COUNT) == 6) { - instance->SetData(DATA_1ST_BOSS_EVENT, DONE); + instance->SetBossState(DATA_1ST_BOSS_EVENT, DONE); instance->SetData(DATA_WAVE_COUNT, 7); } else if (instance->GetData(DATA_WAVE_COUNT) == 12) { - instance->SetData(DATA_2ND_BOSS_EVENT, DONE); + instance->SetBossState(DATA_2ND_BOSS_EVENT, DONE); instance->SetData(DATA_WAVE_COUNT, 13); } } @@ -323,13 +315,15 @@ public: void KilledUnit(Unit* victim) override { - if (victim->GetTypeId() != TYPEID_PLAYER) - return; - - Talk(SAY_SLAY); + if (victim->GetTypeId() == TYPEID_PLAYER) + Talk(SAY_SLAY); } }; + CreatureAI* GetAI(Creature* creature) const override + { + return GetInstanceAI<boss_ichoronAI>(creature); + } }; class npc_ichor_globule : public CreatureScript @@ -337,11 +331,6 @@ class npc_ichor_globule : public CreatureScript public: npc_ichor_globule() : CreatureScript("npc_ichor_globule") { } - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI<npc_ichor_globuleAI>(creature); - } - struct npc_ichor_globuleAI : public ScriptedAI { npc_ichor_globuleAI(Creature* creature) : ScriptedAI(creature) @@ -367,19 +356,18 @@ public: void AttackStart(Unit* /*who*/) override { - return; } void UpdateAI(uint32 uiDiff) override { if (uiRangeCheck_Timer < uiDiff) { - if (Creature* pIchoron = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_ICHORON))) + if (Creature* ichoron = instance->GetCreature(DATA_ICHORON)) { - if (me->IsWithinDist(pIchoron, 2.0f, false)) + if (me->IsWithinDist(ichoron, 2.0f, false)) { - if (pIchoron->AI()) - pIchoron->AI()->DoAction(ACTION_WATER_ELEMENT_HIT); + if (ichoron->AI()) + ichoron->AI()->DoAction(ACTION_WATER_ELEMENT_HIT); me->DespawnOrUnsummon(); } } @@ -391,12 +379,16 @@ public: void JustDied(Unit* /*killer*/) override { DoCast(me, SPELL_SPLASH); - if (Creature* pIchoron = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_ICHORON))) - if (pIchoron->AI()) - pIchoron->AI()->DoAction(ACTION_WATER_ELEMENT_KILLED); + if (Creature* ichoron = instance->GetCreature(DATA_ICHORON)) + if (ichoron->AI()) + ichoron->AI()->DoAction(ACTION_WATER_ELEMENT_KILLED); } }; + CreatureAI* GetAI(Creature* creature) const override + { + return GetInstanceAI<npc_ichor_globuleAI>(creature); + } }; class achievement_dehydration : public AchievementCriteriaScript diff --git a/src/server/scripts/Northrend/VioletHold/boss_lavanthor.cpp b/src/server/scripts/Northrend/VioletHold/boss_lavanthor.cpp index c3df7b71b83..5040dccfa36 100644 --- a/src/server/scripts/Northrend/VioletHold/boss_lavanthor.cpp +++ b/src/server/scripts/Northrend/VioletHold/boss_lavanthor.cpp @@ -21,13 +21,10 @@ enum Spells { - SPELL_CAUTERIZING_FLAMES = 59466, //Only in heroic - SPELL_FIREBOLT = 54235, - H_SPELL_FIREBOLT = 59468, - SPELL_FLAME_BREATH = 54282, - H_SPELL_FLAME_BREATH = 59469, - SPELL_LAVA_BURN = 54249, - H_SPELL_LAVA_BURN = 59594 + SPELL_CAUTERIZING_FLAMES = 59466, // Only in heroic + SPELL_FIREBOLT = 54235, + SPELL_FLAME_BREATH = 54282, + SPELL_LAVA_BURN = 54249 }; class boss_lavanthor : public CreatureScript @@ -35,11 +32,6 @@ class boss_lavanthor : public CreatureScript public: boss_lavanthor() : CreatureScript("boss_lavanthor") { } - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI<boss_lavanthorAI>(creature); - } - struct boss_lavanthorAI : public ScriptedAI { boss_lavanthorAI(Creature* creature) : ScriptedAI(creature) @@ -67,23 +59,24 @@ public: { Initialize(); if (instance->GetData(DATA_WAVE_COUNT) == 6) - instance->SetData(DATA_1ST_BOSS_EVENT, NOT_STARTED); + instance->SetBossState(DATA_1ST_BOSS_EVENT, NOT_STARTED); else if (instance->GetData(DATA_WAVE_COUNT) == 12) - instance->SetData(DATA_2ND_BOSS_EVENT, NOT_STARTED); + instance->SetBossState(DATA_2ND_BOSS_EVENT, NOT_STARTED); } void EnterCombat(Unit* /*who*/) override { - if (GameObject* pDoor = instance->instance->GetGameObject(instance->GetGuidData(DATA_LAVANTHOR_CELL))) - if (pDoor->GetGoState() == GO_STATE_READY) - { - EnterEvadeMode(); - return; - } - if (instance->GetData(DATA_WAVE_COUNT) == 6) - instance->SetData(DATA_1ST_BOSS_EVENT, IN_PROGRESS); - else if (instance->GetData(DATA_WAVE_COUNT) == 12) - instance->SetData(DATA_2ND_BOSS_EVENT, IN_PROGRESS); + if (GameObject* door = instance->GetGameObject(DATA_LAVANTHOR_CELL)) + if (door->GetGoState() == GO_STATE_READY) + { + EnterEvadeMode(); + return; + } + + if (instance->GetData(DATA_WAVE_COUNT) == 6) + instance->SetBossState(DATA_1ST_BOSS_EVENT, IN_PROGRESS); + else if (instance->GetData(DATA_WAVE_COUNT) == 12) + instance->SetBossState(DATA_2ND_BOSS_EVENT, IN_PROGRESS); } void AttackStart(Unit* who) override @@ -102,10 +95,8 @@ public: void MoveInLineOfSight(Unit* /*who*/) override { } - void UpdateAI(uint32 diff) override { - //Return since we have no target if (!UpdateVictim()) return; @@ -123,9 +114,10 @@ public: if (uiLavaBurnTimer <= diff) { - DoCastVictim(SPELL_LAVA_BURN); + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 50.0f, true)) + DoCast(target, SPELL_LAVA_BURN); uiLavaBurnTimer = urand(15000, 23000); - } + } else uiLavaBurnTimer -= diff; if (IsHeroic()) { @@ -143,17 +135,21 @@ public: { if (instance->GetData(DATA_WAVE_COUNT) == 6) { - instance->SetData(DATA_1ST_BOSS_EVENT, DONE); + instance->SetBossState(DATA_1ST_BOSS_EVENT, DONE); instance->SetData(DATA_WAVE_COUNT, 7); } else if (instance->GetData(DATA_WAVE_COUNT) == 12) { - instance->SetData(DATA_2ND_BOSS_EVENT, DONE); + instance->SetBossState(DATA_2ND_BOSS_EVENT, DONE); instance->SetData(DATA_WAVE_COUNT, 13); } } }; + CreatureAI* GetAI(Creature* creature) const override + { + return GetInstanceAI<boss_lavanthorAI>(creature); + } }; void AddSC_boss_lavanthor() diff --git a/src/server/scripts/Northrend/VioletHold/boss_moragg.cpp b/src/server/scripts/Northrend/VioletHold/boss_moragg.cpp index 9a6422dec32..1c98806b127 100644 --- a/src/server/scripts/Northrend/VioletHold/boss_moragg.cpp +++ b/src/server/scripts/Northrend/VioletHold/boss_moragg.cpp @@ -19,11 +19,12 @@ #include "ScriptedCreature.h" #include "violet_hold.h" -//Spells enum Spells { SPELL_CORROSIVE_SALIVA = 54527, - SPELL_OPTIC_LINK = 54396 + SPELL_OPTIC_LINK = 54396, + SPELL_RAY_OF_PAIN = 54438, // NYI missing spelldifficulty + SPELL_RAY_OF_SUFFERING = 54442 // NYI missing spelldifficulty }; class boss_moragg : public CreatureScript @@ -31,11 +32,6 @@ class boss_moragg : public CreatureScript public: boss_moragg() : CreatureScript("boss_moragg") { } - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI<boss_moraggAI>(creature); - } - struct boss_moraggAI : public ScriptedAI { boss_moraggAI(Creature* creature) : ScriptedAI(creature) @@ -60,23 +56,24 @@ public: Initialize(); if (instance->GetData(DATA_WAVE_COUNT) == 6) - instance->SetData(DATA_1ST_BOSS_EVENT, NOT_STARTED); + instance->SetBossState(DATA_1ST_BOSS_EVENT, NOT_STARTED); else if (instance->GetData(DATA_WAVE_COUNT) == 12) - instance->SetData(DATA_2ND_BOSS_EVENT, NOT_STARTED); + instance->SetBossState(DATA_2ND_BOSS_EVENT, NOT_STARTED); } void EnterCombat(Unit* /*who*/) override { - if (GameObject* pDoor = instance->instance->GetGameObject(instance->GetGuidData(DATA_MORAGG_CELL))) - if (pDoor->GetGoState() == GO_STATE_READY) + if (GameObject* door = instance->GetGameObject(DATA_MORAGG_CELL)) + if (door->GetGoState() == GO_STATE_READY) { EnterEvadeMode(); return; } + if (instance->GetData(DATA_WAVE_COUNT) == 6) - instance->SetData(DATA_1ST_BOSS_EVENT, IN_PROGRESS); + instance->SetBossState(DATA_1ST_BOSS_EVENT, IN_PROGRESS); else if (instance->GetData(DATA_WAVE_COUNT) == 12) - instance->SetData(DATA_2ND_BOSS_EVENT, IN_PROGRESS); + instance->SetBossState(DATA_2ND_BOSS_EVENT, IN_PROGRESS); } void AttackStart(Unit* who) override @@ -95,10 +92,8 @@ public: void MoveInLineOfSight(Unit* /*who*/) override { } - void UpdateAI(uint32 diff) override { - //Return since we have no target if (!UpdateVictim()) return; @@ -117,21 +112,26 @@ public: DoMeleeAttackIfReady(); } + void JustDied(Unit* /*killer*/) override { if (instance->GetData(DATA_WAVE_COUNT) == 6) { - instance->SetData(DATA_1ST_BOSS_EVENT, DONE); + instance->SetBossState(DATA_1ST_BOSS_EVENT, DONE); instance->SetData(DATA_WAVE_COUNT, 7); } else if (instance->GetData(DATA_WAVE_COUNT) == 12) { - instance->SetData(DATA_2ND_BOSS_EVENT, DONE); + instance->SetBossState(DATA_2ND_BOSS_EVENT, DONE); instance->SetData(DATA_WAVE_COUNT, 13); } } }; + CreatureAI* GetAI(Creature* creature) const override + { + return GetInstanceAI<boss_moraggAI>(creature); + } }; void AddSC_boss_moragg() diff --git a/src/server/scripts/Northrend/VioletHold/boss_xevozz.cpp b/src/server/scripts/Northrend/VioletHold/boss_xevozz.cpp index 833b06cfbff..d1efcb8ca7a 100644 --- a/src/server/scripts/Northrend/VioletHold/boss_xevozz.cpp +++ b/src/server/scripts/Northrend/VioletHold/boss_xevozz.cpp @@ -23,9 +23,7 @@ enum Spells { SPELL_ARCANE_BARRAGE_VOLLEY = 54202, - SPELL_ARCANE_BARRAGE_VOLLEY_H = 59483, SPELL_ARCANE_BUFFET = 54226, - SPELL_ARCANE_BUFFET_H = 59485, SPELL_SUMMON_ETHEREAL_SPHERE_1 = 54102, SPELL_SUMMON_ETHEREAL_SPHERE_2 = 54137, SPELL_SUMMON_ETHEREAL_SPHERE_3 = 54138 @@ -40,7 +38,6 @@ enum NPCs enum CreatureSpells { SPELL_ARCANE_POWER = 54160, - H_SPELL_ARCANE_POWER = 59474, SPELL_SUMMON_PLAYERS = 54164, SPELL_POWER_BALL_VISUAL = 54141 }; @@ -61,11 +58,6 @@ class boss_xevozz : public CreatureScript public: boss_xevozz() : CreatureScript("boss_xevozz") { } - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI<boss_xevozzAI>(creature); - } - struct boss_xevozzAI : public ScriptedAI { boss_xevozzAI(Creature* creature) : ScriptedAI(creature) @@ -90,9 +82,9 @@ public: void Reset() override { if (instance->GetData(DATA_WAVE_COUNT) == 6) - instance->SetData(DATA_1ST_BOSS_EVENT, NOT_STARTED); + instance->SetBossState(DATA_1ST_BOSS_EVENT, NOT_STARTED); else if (instance->GetData(DATA_WAVE_COUNT) == 12) - instance->SetData(DATA_2ND_BOSS_EVENT, NOT_STARTED); + instance->SetBossState(DATA_2ND_BOSS_EVENT, NOT_STARTED); Initialize(); DespawnSphere(); @@ -139,46 +131,46 @@ public: void EnterCombat(Unit* /*who*/) override { - Talk(SAY_AGGRO); - if (GameObject* pDoor = instance->instance->GetGameObject(instance->GetGuidData(DATA_XEVOZZ_CELL))) - if (pDoor->GetGoState() == GO_STATE_READY) + if (GameObject* door = instance->GetGameObject(DATA_XEVOZZ_CELL)) + if (door->GetGoState() == GO_STATE_READY) { EnterEvadeMode(); return; } + + Talk(SAY_AGGRO); + if (instance->GetData(DATA_WAVE_COUNT) == 6) - instance->SetData(DATA_1ST_BOSS_EVENT, IN_PROGRESS); + instance->SetBossState(DATA_1ST_BOSS_EVENT, IN_PROGRESS); else if (instance->GetData(DATA_WAVE_COUNT) == 12) - instance->SetData(DATA_2ND_BOSS_EVENT, IN_PROGRESS); + instance->SetBossState(DATA_2ND_BOSS_EVENT, IN_PROGRESS); } void MoveInLineOfSight(Unit* /*who*/) override { } - - void UpdateAI(uint32 uiDiff) override + void UpdateAI(uint32 diff) override { - //Return since we have no target if (!UpdateVictim()) return; - if (uiArcaneBarrageVolley_Timer < uiDiff) + if (uiArcaneBarrageVolley_Timer < diff) { DoCast(me, SPELL_ARCANE_BARRAGE_VOLLEY); uiArcaneBarrageVolley_Timer = urand(20000, 22000); } - else uiArcaneBarrageVolley_Timer -= uiDiff; + else uiArcaneBarrageVolley_Timer -= diff; if (uiArcaneBuffet_Timer) { - if (uiArcaneBuffet_Timer < uiDiff) + if (uiArcaneBuffet_Timer < diff) { DoCastVictim(SPELL_ARCANE_BUFFET); uiArcaneBuffet_Timer = 0; } - else uiArcaneBuffet_Timer -= uiDiff; + else uiArcaneBuffet_Timer -= diff; } - if (uiSummonEtherealSphere_Timer < uiDiff) + if (uiSummonEtherealSphere_Timer < diff) { Talk(SAY_SPAWN); DoCast(me, SPELL_SUMMON_ETHEREAL_SPHERE_1); @@ -188,7 +180,7 @@ public: uiSummonEtherealSphere_Timer = urand(45000, 47000); uiArcaneBuffet_Timer = urand(5000, 6000); } - else uiSummonEtherealSphere_Timer -= uiDiff; + else uiSummonEtherealSphere_Timer -= diff; DoMeleeAttackIfReady(); } @@ -201,24 +193,27 @@ public: if (instance->GetData(DATA_WAVE_COUNT) == 6) { - instance->SetData(DATA_1ST_BOSS_EVENT, DONE); + instance->SetBossState(DATA_1ST_BOSS_EVENT, DONE); instance->SetData(DATA_WAVE_COUNT, 7); } else if (instance->GetData(DATA_WAVE_COUNT) == 12) { - instance->SetData(DATA_2ND_BOSS_EVENT, NOT_STARTED); + instance->SetBossState(DATA_2ND_BOSS_EVENT, NOT_STARTED); instance->SetData(DATA_WAVE_COUNT, 13); } } + void KilledUnit(Unit* victim) override { - if (victim->GetTypeId() != TYPEID_PLAYER) - return; - - Talk(SAY_SLAY); + if (victim->GetTypeId() == TYPEID_PLAYER) + Talk(SAY_SLAY); } }; + CreatureAI* GetAI(Creature* creature) const override + { + return GetInstanceAI<boss_xevozzAI>(creature); + } }; class npc_ethereal_sphere : public CreatureScript @@ -226,11 +221,6 @@ class npc_ethereal_sphere : public CreatureScript public: npc_ethereal_sphere() : CreatureScript("npc_ethereal_sphere") { } - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI<npc_ethereal_sphereAI>(creature); - } - struct npc_ethereal_sphereAI : public ScriptedAI { npc_ethereal_sphereAI(Creature* creature) : ScriptedAI(creature) @@ -255,16 +245,15 @@ public: Initialize(); } - void UpdateAI(uint32 uiDiff) override + void UpdateAI(uint32 diff) override { - //Return since we have no target if (!UpdateVictim()) return; if (!me->HasAura(SPELL_POWER_BALL_VISUAL)) DoCast(me, SPELL_POWER_BALL_VISUAL); - if (uiRangeCheck_Timer < uiDiff) + if (uiRangeCheck_Timer < diff) { if (Creature* pXevozz = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_XEVOZZ))) { @@ -276,9 +265,9 @@ public: } uiRangeCheck_Timer = 1000; } - else uiRangeCheck_Timer -= uiDiff; + else uiRangeCheck_Timer -= diff; - if (uiSummonPlayers_Timer < uiDiff) + if (uiSummonPlayers_Timer < diff) { DoCast(me, SPELL_SUMMON_PLAYERS); // not working right @@ -295,10 +284,14 @@ public: uiSummonPlayers_Timer = urand(33000, 35000); } - else uiSummonPlayers_Timer -= uiDiff; + else uiSummonPlayers_Timer -= diff; } }; + CreatureAI* GetAI(Creature* creature) const override + { + return GetInstanceAI<npc_ethereal_sphereAI>(creature); + } }; void AddSC_boss_xevozz() diff --git a/src/server/scripts/Northrend/VioletHold/boss_zuramat.cpp b/src/server/scripts/Northrend/VioletHold/boss_zuramat.cpp index 90fd936e853..c29861f08a4 100644 --- a/src/server/scripts/Northrend/VioletHold/boss_zuramat.cpp +++ b/src/server/scripts/Northrend/VioletHold/boss_zuramat.cpp @@ -22,15 +22,13 @@ enum Spells { SPELL_SHROUD_OF_DARKNESS = 54524, - H_SPELL_SHROUD_OF_DARKNESS = 59745, SPELL_SUMMON_VOID_SENTRY = 54369, - SPELL_VOID_SHIFT = 54361, - H_SPELL_VOID_SHIFT = 59743, + SPELL_VOID_SHIFT = 54361 }; enum Creatures { - NPC_VOID_SENTRY = 29364 + NPC_VOID_SENTRY = 29364 }; enum Yells @@ -53,11 +51,6 @@ class boss_zuramat : public CreatureScript public: boss_zuramat() : CreatureScript("boss_zuramat") { } - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI<boss_zuramatAI>(creature); - } - struct boss_zuramatAI : public ScriptedAI { boss_zuramatAI(Creature* creature) : ScriptedAI(creature) @@ -107,25 +100,25 @@ public: void EnterCombat(Unit* /*who*/) override { - Talk(SAY_AGGRO); - if (GameObject* pDoor = instance->instance->GetGameObject(instance->GetGuidData(DATA_ZURAMAT_CELL))) - if (pDoor->GetGoState() == GO_STATE_READY) + if (GameObject* door = instance->GetGameObject(DATA_ZURAMAT_CELL)) + if (door->GetGoState() == GO_STATE_READY) { EnterEvadeMode(); return; } + + Talk(SAY_AGGRO); + if (instance->GetData(DATA_WAVE_COUNT) == 6) - instance->SetData(DATA_1ST_BOSS_EVENT, IN_PROGRESS); + instance->SetBossState(DATA_1ST_BOSS_EVENT, IN_PROGRESS); else if (instance->GetData(DATA_WAVE_COUNT) == 12) - instance->SetData(DATA_2ND_BOSS_EVENT, IN_PROGRESS); + instance->SetBossState(DATA_2ND_BOSS_EVENT, IN_PROGRESS); } void MoveInLineOfSight(Unit* /*who*/) override { } - void UpdateAI(uint32 diff) override { - //Return since we have no target if (!UpdateVictim()) return; @@ -171,26 +164,27 @@ public: if (instance->GetData(DATA_WAVE_COUNT) == 6) { - instance->SetData(DATA_1ST_BOSS_EVENT, DONE); + instance->SetBossState(DATA_1ST_BOSS_EVENT, DONE); instance->SetData(DATA_WAVE_COUNT, 7); } else if (instance->GetData(DATA_WAVE_COUNT) == 12) { - instance->SetData(DATA_2ND_BOSS_EVENT, DONE); + instance->SetBossState(DATA_2ND_BOSS_EVENT, DONE); instance->SetData(DATA_WAVE_COUNT, 13); } } void KilledUnit(Unit* victim) override { - if (victim->GetTypeId() != TYPEID_PLAYER) - return; - - Talk(SAY_SLAY); + if (victim->GetTypeId() == TYPEID_PLAYER) + Talk(SAY_SLAY); } - }; + CreatureAI* GetAI(Creature* creature) const override + { + return GetInstanceAI<boss_zuramatAI>(creature); + } }; class achievement_void_dance : public AchievementCriteriaScript diff --git a/src/server/scripts/Northrend/VioletHold/instance_violet_hold.cpp b/src/server/scripts/Northrend/VioletHold/instance_violet_hold.cpp index ef9ad806c89..28c56a02255 100644 --- a/src/server/scripts/Northrend/VioletHold/instance_violet_hold.cpp +++ b/src/server/scripts/Northrend/VioletHold/instance_violet_hold.cpp @@ -22,8 +22,6 @@ #include "Player.h" #include "TemporarySummon.h" -#define MAX_ENCOUNTER 3 - /* Violet Hold encounters: 0 - First boss 1 - Second boss @@ -38,21 +36,6 @@ 6 - Zuramat 7 - Cyanigosa */ -enum GameObjects -{ - GO_MAIN_DOOR = 191723, - GO_XEVOZZ_DOOR = 191556, - GO_LAVANTHOR_DOOR = 191566, - GO_ICHORON_DOOR = 191722, - GO_ZURAMAT_DOOR = 191565, - GO_EREKEM_DOOR = 191564, - GO_EREKEM_GUARD_1_DOOR = 191563, - GO_EREKEM_GUARD_2_DOOR = 191562, - GO_MORAGG_DOOR = 191606, - GO_INTRO_ACTIVATION_CRYSTAL = 193615, - GO_ACTIVATION_CRYSTAL = 193611 -}; - enum AzureSaboteurSpells { SABOTEUR_SHIELD_DISRUPTION = 58291, @@ -64,7 +47,7 @@ enum CrystalSpells SPELL_ARCANE_LIGHTNING = 57930 }; -const Position PortalLocation[] = +Position const PortalLocation[] = { {1877.51f, 850.104f, 44.6599f, 4.7822f }, // WP 1 {1918.37f, 853.437f, 47.1624f, 4.12294f}, // WP 2 @@ -74,21 +57,21 @@ const Position PortalLocation[] = {1908.31f, 809.657f, 38.7037f, 3.08701f} // WP 6 }; -const Position ArcaneSphere = {1887.060059f, 806.151001f, 61.321602f, 0.0f}; -const Position BossStartMove1 = {1894.684448f, 739.390503f, 47.668003f, 0.0f}; -const Position BossStartMove2 = {1875.173950f, 860.832703f, 43.333565f, 0.0f}; -const Position BossStartMove21 = {1858.854614f, 855.071411f, 43.333565f, 0.0f}; -const Position BossStartMove22 = {1891.926636f, 863.388977f, 43.333565f, 0.0f}; -const Position BossStartMove3 = {1916.138062f, 778.152222f, 35.772308f, 0.0f}; -const Position BossStartMove4 = {1853.618286f, 758.557617f, 38.657505f, 0.0f}; -const Position BossStartMove5 = {1906.683960f, 842.348022f, 38.637459f, 0.0f}; -const Position BossStartMove6 = {1928.207031f, 852.864441f, 47.200813f, 0.0f}; - -const Position CyanigosasSpawnLocation = {1930.281250f, 804.407715f, 52.410946f, 3.139621f}; -const Position MiddleRoomLocation = {1892.291260f, 805.696838f, 38.438862f, 3.139621f}; -const Position MiddleRoomPortalSaboLocation = {1896.622925f, 804.854126f, 38.504772f, 3.139621f}; - -//Cyanigosa's prefight event data +Position const ArcaneSphere = {1887.060059f, 806.151001f, 61.321602f, 0.0f}; +Position const BossStartMove1 = {1894.684448f, 739.390503f, 47.668003f, 0.0f}; +Position const BossStartMove2 = {1875.173950f, 860.832703f, 43.333565f, 0.0f}; +Position const BossStartMove21 = {1858.854614f, 855.071411f, 43.333565f, 0.0f}; +Position const BossStartMove22 = {1891.926636f, 863.388977f, 43.333565f, 0.0f}; +Position const BossStartMove3 = {1916.138062f, 778.152222f, 35.772308f, 0.0f}; +Position const BossStartMove4 = {1853.618286f, 758.557617f, 38.657505f, 0.0f}; +Position const BossStartMove5 = {1906.683960f, 842.348022f, 38.637459f, 0.0f}; +Position const BossStartMove6 = {1928.207031f, 852.864441f, 47.200813f, 0.0f}; + +Position const CyanigosasSpawnLocation = {1930.281250f, 804.407715f, 52.410946f, 3.139621f}; +Position const MiddleRoomLocation = {1892.291260f, 805.696838f, 38.438862f, 3.139621f}; +Position const MiddleRoomPortalSaboLocation = {1896.622925f, 804.854126f, 38.504772f, 3.139621f}; + +// Cyanigosa's prefight event data enum Yells { CYANIGOSA_SAY_SPAWN = 0 @@ -100,21 +83,45 @@ enum Spells CYANIGOSA_BLUE_AURA = 47759, }; +ObjectData const creatureData[] = +{ + { NPC_XEVOZZ, DATA_XEVOZZ }, + { NPC_LAVANTHOR, DATA_LAVANTHOR }, + { NPC_ICHORON, DATA_ICHORON }, + { NPC_ZURAMAT, DATA_ZURAMAT }, + { NPC_EREKEM, DATA_EREKEM }, + { NPC_MORAGG, DATA_MORAGG }, + { NPC_CYANIGOSA, DATA_CYANIGOSA }, + { NPC_SINCLARI, DATA_SINCLARI }, + { 0, 0 } // END +}; + +ObjectData const gameObjectData[] = +{ + { GO_EREKEM_GUARD_1_DOOR, DATA_EREKEM_LEFT_GUARD_CELL }, + { GO_EREKEM_GUARD_2_DOOR, DATA_EREKEM_RIGHT_GUARD_CELL }, + { GO_EREKEM_DOOR, DATA_EREKEM_CELL }, + { GO_ZURAMAT_DOOR, DATA_ZURAMAT_CELL }, + { GO_LAVANTHOR_DOOR, DATA_LAVANTHOR_CELL }, + { GO_MORAGG_DOOR, DATA_MORAGG_CELL }, + { GO_ICHORON_DOOR, DATA_ICHORON_CELL }, + { GO_XEVOZZ_DOOR, DATA_XEVOZZ_CELL }, + { GO_MAIN_DOOR, DATA_MAIN_DOOR }, + { 0, 0 } // END +}; + class instance_violet_hold : public InstanceMapScript { public: instance_violet_hold() : InstanceMapScript("instance_violet_hold", 608) { } - InstanceScript* GetInstanceScript(InstanceMap* map) const override - { - return new instance_violet_hold_InstanceMapScript(map); - } - struct instance_violet_hold_InstanceMapScript : public InstanceScript { instance_violet_hold_InstanceMapScript(Map* map) : InstanceScript(map) { SetHeaders(DataHeader); + SetBossNumber(EncounterCount); + LoadObjectData(creatureData, gameObjectData); uiRemoveNpc = 0; @@ -138,29 +145,10 @@ public: bCrystalActivated = false; defenseless = true; uiMainEventPhase = NOT_STARTED; - - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); } - ObjectGuid uiMoragg; - ObjectGuid uiErekem; ObjectGuid uiErekemGuard[2]; - ObjectGuid uiIchoron; - ObjectGuid uiLavanthor; - ObjectGuid uiXevozz; - ObjectGuid uiZuramat; - ObjectGuid uiCyanigosa; - ObjectGuid uiSinclari; - - ObjectGuid uiMoraggCell; - ObjectGuid uiErekemCell; - ObjectGuid uiErekemLeftGuardCell; - ObjectGuid uiErekemRightGuardCell; - ObjectGuid uiIchoronCell; - ObjectGuid uiLavanthorCell; - ObjectGuid uiXevozzCell; - ObjectGuid uiZuramatCell; - ObjectGuid uiMainDoor; + ObjectGuid uiTeleportationPortal; ObjectGuid uiSaboteurPortal; @@ -180,7 +168,6 @@ public: uint8 uiDoorIntegrity; - uint16 m_auiEncounter[MAX_ENCOUNTER]; uint8 uiCountErekemGuards; uint8 uiCountActivationCrystals; uint8 uiCyanigosaEventPhase; @@ -194,52 +181,23 @@ public: std::list<uint8> NpcAtDoorCastingList; - std::string str_data; - - bool IsEncounterInProgress() const override - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - return true; - - return false; - } - void OnCreatureCreate(Creature* creature) override { + InstanceScript::OnCreatureCreate(creature); + switch (creature->GetEntry()) { - case CREATURE_XEVOZZ: - uiXevozz = creature->GetGUID(); - break; - case CREATURE_LAVANTHOR: - uiLavanthor = creature->GetGUID(); - break; - case CREATURE_ICHORON: - uiIchoron = creature->GetGUID(); - break; - case CREATURE_ZURAMAT: - uiZuramat = creature->GetGUID(); - break; - case CREATURE_EREKEM: - uiErekem = creature->GetGUID(); - break; - case CREATURE_EREKEM_GUARD: + case NPC_EREKEM_GUARD: if (uiCountErekemGuards < 2) { uiErekemGuard[uiCountErekemGuards++] = creature->GetGUID(); - creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_NON_ATTACKABLE); + creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NON_ATTACKABLE); } break; - case CREATURE_MORAGG: - uiMoragg = creature->GetGUID(); + case NPC_CYANIGOSA: + creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NON_ATTACKABLE); break; - case CREATURE_CYANIGOSA: - uiCyanigosa = creature->GetGUID(); - creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_NON_ATTACKABLE); - break; - case CREATURE_SINCLARI: - uiSinclari = creature->GetGUID(); + default: break; } @@ -255,68 +213,53 @@ public: void OnGameObjectCreate(GameObject* go) override { + InstanceScript::OnGameObjectCreate(go); + switch (go->GetEntry()) { - case GO_EREKEM_GUARD_1_DOOR: - uiErekemLeftGuardCell = go->GetGUID(); - break; - case GO_EREKEM_GUARD_2_DOOR: - uiErekemRightGuardCell = go->GetGUID(); - break; - case GO_EREKEM_DOOR: - uiErekemCell = go->GetGUID(); - break; - case GO_ZURAMAT_DOOR: - uiZuramatCell = go->GetGUID(); - break; - case GO_LAVANTHOR_DOOR: - uiLavanthorCell = go->GetGUID(); - break; - case GO_MORAGG_DOOR: - uiMoraggCell = go->GetGUID(); - break; - case GO_ICHORON_DOOR: - uiIchoronCell = go->GetGUID(); - break; - case GO_XEVOZZ_DOOR: - uiXevozzCell = go->GetGUID(); - break; - case GO_MAIN_DOOR: - uiMainDoor = go->GetGUID(); - break; case GO_ACTIVATION_CRYSTAL: if (uiCountActivationCrystals < 4) uiActivationCrystal[uiCountActivationCrystals++] = go->GetGUID(); break; + default: + break; } } - void SetData(uint32 type, uint32 data) override + bool SetBossState(uint32 type, EncounterState state) override { + if (!InstanceScript::SetBossState(type, state)) + return false; + switch (type) { case DATA_1ST_BOSS_EVENT: - UpdateEncounterState(ENCOUNTER_CREDIT_KILL_CREATURE, CREATURE_EREKEM, NULL); - m_auiEncounter[0] = data; - if (data == DONE) - SaveToDB(); + if (state == DONE) + UpdateEncounterState(ENCOUNTER_CREDIT_KILL_CREATURE, NPC_EREKEM, nullptr); break; case DATA_2ND_BOSS_EVENT: - UpdateEncounterState(ENCOUNTER_CREDIT_KILL_CREATURE, CREATURE_MORAGG, NULL); - m_auiEncounter[1] = data; - if (data == DONE) - SaveToDB(); - break; - case DATA_CYANIGOSA_EVENT: - m_auiEncounter[2] = data; - if (data == DONE) + if (state == DONE) + UpdateEncounterState(ENCOUNTER_CREDIT_KILL_CREATURE, NPC_MORAGG, nullptr); + break; + case DATA_CYANIGOSA: + if (state == DONE) { - SaveToDB(); uiMainEventPhase = DONE; - if (GameObject* pMainDoor = instance->GetGameObject(uiMainDoor)) - pMainDoor->SetGoState(GO_STATE_ACTIVE); + if (GameObject* mainDoor = GetGameObject(DATA_MAIN_DOOR)) + mainDoor->SetGoState(GO_STATE_ACTIVE); } break; + default: + break; + } + + return true; + } + + void SetData(uint32 type, uint32 data) override + { + switch (type) + { case DATA_WAVE_COUNT: uiWaveCount = data; bActive = true; @@ -340,21 +283,8 @@ public: NpcAtDoorCastingList.pop_back(); break; case DATA_MAIN_DOOR: - if (GameObject* pMainDoor = instance->GetGameObject(uiMainDoor)) - { - switch (data) - { - case GO_STATE_ACTIVE: - pMainDoor->SetGoState(GO_STATE_ACTIVE); - break; - case GO_STATE_READY: - pMainDoor->SetGoState(GO_STATE_READY); - break; - case GO_STATE_ACTIVE_ALTERNATIVE: - pMainDoor->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE); - break; - } - } + if (GameObject* mainDoor = GetGameObject(type)) + mainDoor->SetGoState(GOState(data)); break; case DATA_START_BOSS_ENCOUNTER: switch (uiWaveCount) @@ -374,7 +304,7 @@ public: uiMainEventPhase = data; if (data == IN_PROGRESS) // Start event { - if (GameObject* mainDoor = instance->GetGameObject(uiMainDoor)) + if (GameObject* mainDoor = GetGameObject(DATA_MAIN_DOOR)) mainDoor->SetGoState(GO_STATE_READY); uiWaveCount = 1; bActive = true; @@ -404,9 +334,6 @@ public: { switch (type) { - case DATA_1ST_BOSS_EVENT: return m_auiEncounter[0]; - case DATA_2ND_BOSS_EVENT: return m_auiEncounter[1]; - case DATA_CYANIGOSA_EVENT: return m_auiEncounter[2]; case DATA_WAVE_COUNT: return uiWaveCount; case DATA_REMOVE_NPC: return uiRemoveNpc; case DATA_PORTAL_LOCATION: return uiLocation; @@ -421,125 +348,107 @@ public: return 0; } - ObjectGuid GetGuidData(uint32 identifier) const override + ObjectGuid GetGuidData(uint32 type) const override { - switch (identifier) + switch (type) { - case DATA_MORAGG: return uiMoragg; - case DATA_EREKEM: return uiErekem; case DATA_EREKEM_GUARD_1: return uiErekemGuard[0]; case DATA_EREKEM_GUARD_2: return uiErekemGuard[1]; - case DATA_ICHORON: return uiIchoron; - case DATA_LAVANTHOR: return uiLavanthor; - case DATA_XEVOZZ: return uiXevozz; - case DATA_ZURAMAT: return uiZuramat; - case DATA_CYANIGOSA: return uiCyanigosa; - case DATA_MORAGG_CELL: return uiMoraggCell; - case DATA_EREKEM_CELL: return uiErekemCell; - case DATA_EREKEM_RIGHT_GUARD_CELL: return uiErekemRightGuardCell; - case DATA_EREKEM_LEFT_GUARD_CELL: return uiErekemLeftGuardCell; - case DATA_ICHORON_CELL: return uiIchoronCell; - case DATA_LAVANTHOR_CELL: return uiLavanthorCell; - case DATA_XEVOZZ_CELL: return uiXevozzCell; - case DATA_ZURAMAT_CELL: return uiZuramatCell; - case DATA_MAIN_DOOR: return uiMainDoor; - case DATA_SINCLARI: return uiSinclari; case DATA_TELEPORTATION_PORTAL: return uiTeleportationPortal; case DATA_SABOTEUR_PORTAL: return uiSaboteurPortal; } - return ObjectGuid::Empty; + return InstanceScript::GetGuidData(type); } void SpawnPortal() { SetData(DATA_PORTAL_LOCATION, (GetData(DATA_PORTAL_LOCATION) + urand(1, 5))%6); - if (Creature* pSinclari = instance->GetCreature(uiSinclari)) - if (Creature* portal = pSinclari->SummonCreature(CREATURE_TELEPORTATION_PORTAL, PortalLocation[GetData(DATA_PORTAL_LOCATION)], TEMPSUMMON_CORPSE_DESPAWN)) + if (Creature* sinclari = GetCreature(DATA_SINCLARI)) + if (Creature* portal = sinclari->SummonCreature(NPC_TELEPORTATION_PORTAL, PortalLocation[GetData(DATA_PORTAL_LOCATION)], TEMPSUMMON_CORPSE_DESPAWN)) uiTeleportationPortal = portal->GetGUID(); } void StartBossEncounter(uint8 uiBoss, bool bForceRespawn = true) { - Creature* pBoss = NULL; + Creature* boss = nullptr; switch (uiBoss) { case BOSS_MORAGG: - HandleGameObject(uiMoraggCell, bForceRespawn); - pBoss = instance->GetCreature(uiMoragg); - if (pBoss) - pBoss->GetMotionMaster()->MovePoint(0, BossStartMove1); + HandleGameObject(GetObjectGuid(DATA_MORAGG_CELL), bForceRespawn); + boss = GetCreature(DATA_MORAGG); + if (boss) + boss->GetMotionMaster()->MovePoint(0, BossStartMove1); break; case BOSS_EREKEM: - HandleGameObject(uiErekemCell, bForceRespawn); - HandleGameObject(uiErekemRightGuardCell, bForceRespawn); - HandleGameObject(uiErekemLeftGuardCell, bForceRespawn); - - pBoss = instance->GetCreature(uiErekem); + HandleGameObject(GetObjectGuid(DATA_EREKEM_CELL), bForceRespawn); + HandleGameObject(GetObjectGuid(DATA_EREKEM_LEFT_GUARD_CELL), bForceRespawn); + HandleGameObject(GetObjectGuid(DATA_EREKEM_RIGHT_GUARD_CELL), bForceRespawn); - if (pBoss) - pBoss->GetMotionMaster()->MovePoint(0, BossStartMove2); + boss = GetCreature(DATA_EREKEM); + if (boss) + boss->GetMotionMaster()->MovePoint(0, BossStartMove2); if (Creature* pGuard1 = instance->GetCreature(uiErekemGuard[0])) { if (bForceRespawn) - pGuard1->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_NON_ATTACKABLE); + pGuard1->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NON_ATTACKABLE); else - pGuard1->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_NON_ATTACKABLE); + pGuard1->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NON_ATTACKABLE); pGuard1->GetMotionMaster()->MovePoint(0, BossStartMove21); } if (Creature* pGuard2 = instance->GetCreature(uiErekemGuard[1])) { if (bForceRespawn) - pGuard2->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_NON_ATTACKABLE); + pGuard2->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NON_ATTACKABLE); else - pGuard2->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_NON_ATTACKABLE); + pGuard2->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NON_ATTACKABLE); pGuard2->GetMotionMaster()->MovePoint(0, BossStartMove22); } break; case BOSS_ICHORON: - HandleGameObject(uiIchoronCell, bForceRespawn); - pBoss = instance->GetCreature(uiIchoron); - if (pBoss) - pBoss->GetMotionMaster()->MovePoint(0, BossStartMove3); + HandleGameObject(GetObjectGuid(DATA_ICHORON_CELL), bForceRespawn); + boss = GetCreature(DATA_ICHORON); + if (boss) + boss->GetMotionMaster()->MovePoint(0, BossStartMove3); break; case BOSS_LAVANTHOR: - HandleGameObject(uiLavanthorCell, bForceRespawn); - pBoss = instance->GetCreature(uiLavanthor); - if (pBoss) - pBoss->GetMotionMaster()->MovePoint(0, BossStartMove4); + HandleGameObject(GetObjectGuid(DATA_LAVANTHOR_CELL), bForceRespawn); + boss = GetCreature(DATA_LAVANTHOR); + if (boss) + boss->GetMotionMaster()->MovePoint(0, BossStartMove4); break; case BOSS_XEVOZZ: - HandleGameObject(uiXevozzCell, bForceRespawn); - pBoss = instance->GetCreature(uiXevozz); - if (pBoss) - pBoss->GetMotionMaster()->MovePoint(0, BossStartMove5); + HandleGameObject(GetObjectGuid(DATA_XEVOZZ_CELL), bForceRespawn); + boss = GetCreature(DATA_XEVOZZ); + if (boss) + boss->GetMotionMaster()->MovePoint(0, BossStartMove5); break; case BOSS_ZURAMAT: - HandleGameObject(uiZuramatCell, bForceRespawn); - pBoss = instance->GetCreature(uiZuramat); - if (pBoss) - pBoss->GetMotionMaster()->MovePoint(0, BossStartMove6); + HandleGameObject(GetObjectGuid(DATA_ZURAMAT_CELL), bForceRespawn); + boss = GetCreature(DATA_ZURAMAT); + if (boss) + boss->GetMotionMaster()->MovePoint(0, BossStartMove6); break; } // generic boss state changes - if (pBoss) + if (boss) { - pBoss->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_NON_ATTACKABLE); - pBoss->SetReactState(REACT_AGGRESSIVE); + boss->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_NON_ATTACKABLE); + boss->SetReactState(REACT_AGGRESSIVE); if (!bForceRespawn) { - if (pBoss->isDead()) + if (boss->isDead()) { // respawn but avoid to be looted again - pBoss->Respawn(); - pBoss->RemoveLootMode(1); + boss->Respawn(); + boss->RemoveLootMode(1); } - pBoss->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_NON_ATTACKABLE); + boss->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_NON_ATTACKABLE); uiWaveCount = 0; } } @@ -555,12 +464,12 @@ public: case 6: if (uiFirstBoss == 0) uiFirstBoss = urand(1, 6); - if (Creature* pSinclari = instance->GetCreature(uiSinclari)) + if (Creature* sinclari = GetCreature(DATA_SINCLARI)) { - if (Creature* pPortal = pSinclari->SummonCreature(CREATURE_TELEPORTATION_PORTAL, MiddleRoomPortalSaboLocation, TEMPSUMMON_CORPSE_DESPAWN)) - uiSaboteurPortal = pPortal->GetGUID(); - if (Creature* pAzureSaboteur = pSinclari->SummonCreature(CREATURE_SABOTEOUR, MiddleRoomLocation, TEMPSUMMON_DEAD_DESPAWN)) - pAzureSaboteur->CastSpell(pAzureSaboteur, SABOTEUR_SHIELD_EFFECT, false); + if (Creature* portal = sinclari->SummonCreature(NPC_TELEPORTATION_PORTAL, MiddleRoomPortalSaboLocation, TEMPSUMMON_CORPSE_DESPAWN)) + uiSaboteurPortal = portal->GetGUID(); + if (Creature* azureSaboteur = sinclari->SummonCreature(NPC_SABOTEOUR, MiddleRoomLocation, TEMPSUMMON_DEAD_DESPAWN)) + azureSaboteur->CastSpell(azureSaboteur, SABOTEUR_SHIELD_EFFECT, false); } break; case 12: @@ -569,25 +478,22 @@ public: { uiSecondBoss = urand(1, 6); } while (uiSecondBoss == uiFirstBoss); - if (Creature* pSinclari = instance->GetCreature(uiSinclari)) + if (Creature* sinclari = GetCreature(DATA_SINCLARI)) { - if (Creature* pPortal = pSinclari->SummonCreature(CREATURE_TELEPORTATION_PORTAL, MiddleRoomPortalSaboLocation, TEMPSUMMON_CORPSE_DESPAWN)) + if (Creature* pPortal = sinclari->SummonCreature(NPC_TELEPORTATION_PORTAL, MiddleRoomPortalSaboLocation, TEMPSUMMON_CORPSE_DESPAWN)) uiSaboteurPortal = pPortal->GetGUID(); - if (Creature* pAzureSaboteur = pSinclari->SummonCreature(CREATURE_SABOTEOUR, MiddleRoomLocation, TEMPSUMMON_DEAD_DESPAWN)) + if (Creature* pAzureSaboteur = sinclari->SummonCreature(NPC_SABOTEOUR, MiddleRoomLocation, TEMPSUMMON_DEAD_DESPAWN)) pAzureSaboteur->CastSpell(pAzureSaboteur, SABOTEUR_SHIELD_EFFECT, false); } break; case 18: - { - Creature* pSinclari = instance->GetCreature(uiSinclari); - if (pSinclari) - pSinclari->SummonCreature(CREATURE_CYANIGOSA, CyanigosasSpawnLocation, TEMPSUMMON_DEAD_DESPAWN); + if (Creature* sinclari = GetCreature(DATA_SINCLARI)) + sinclari->SummonCreature(NPC_CYANIGOSA, CyanigosasSpawnLocation, TEMPSUMMON_DEAD_DESPAWN); break; - } case 1: { - if (GameObject* pMainDoor = instance->GetGameObject(uiMainDoor)) - pMainDoor->SetGoState(GO_STATE_READY); + if (GameObject* mainDoor = GetGameObject(DATA_MAIN_DOOR)) + mainDoor->SetGoState(GO_STATE_READY); DoUpdateWorldState(WORLD_STATE_VH_PRISON_STATE, 100); // no break } @@ -597,54 +503,15 @@ public: } } - std::string GetSaveData() override + void WriteSaveDataMore(std::ostringstream& data) override { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << "V H " << (uint16)m_auiEncounter[0] - << ' ' << (uint16)m_auiEncounter[1] - << ' ' << (uint16)m_auiEncounter[2] - << ' ' << (uint16)uiFirstBoss - << ' ' << (uint16)uiSecondBoss; - - str_data = saveStream.str(); - - OUT_SAVE_INST_DATA_COMPLETE; - return str_data; + data << uiFirstBoss << ' ' << uiSecondBoss; } - void Load(const char* in) override + void ReadSaveDataMore(std::istringstream& data) override { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - - char dataHead1, dataHead2; - uint16 data0, data1, data2, data3, data4; - - std::istringstream loadStream(in); - loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3 >> data4; - - if (dataHead1 == 'V' && dataHead2 == 'H') - { - m_auiEncounter[0] = data0; - m_auiEncounter[1] = data1; - m_auiEncounter[2] = data2; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - m_auiEncounter[i] = NOT_STARTED; - - uiFirstBoss = uint8(data3); - uiSecondBoss = uint8(data4); - } else OUT_LOAD_INST_DATA_FAIL; - - OUT_LOAD_INST_DATA_COMPLETE; + data >> uiFirstBoss; + data >> uiSecondBoss; } bool CheckWipe() @@ -695,54 +562,51 @@ public: if (GameObject* crystal = instance->GetGameObject(uiActivationCrystal[i])) crystal->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); - if (Creature* pSinclari = instance->GetCreature(uiSinclari)) + if (Creature* sinclari = GetCreature(DATA_SINCLARI)) { - pSinclari->SetVisible(true); + sinclari->SetVisible(true); std::list<Creature*> GuardList; - pSinclari->GetCreatureListWithEntryInGrid(GuardList, NPC_VIOLET_HOLD_GUARD, 40.0f); + sinclari->GetCreatureListWithEntryInGrid(GuardList, NPC_VIOLET_HOLD_GUARD, 40.0f); if (!GuardList.empty()) { - for (std::list<Creature*>::const_iterator itr = GuardList.begin(); itr != GuardList.end(); ++itr) + for (Creature* guard : GuardList) { - if (Creature* pGuard = *itr) - { - pGuard->SetVisible(true); - pGuard->SetReactState(REACT_AGGRESSIVE); - pGuard->GetMotionMaster()->MovePoint(1, pGuard->GetHomePosition()); - } + guard->SetVisible(true); + guard->SetReactState(REACT_AGGRESSIVE); + guard->GetMotionMaster()->MovePoint(1, guard->GetHomePosition()); } } - pSinclari->GetMotionMaster()->MovePoint(1, pSinclari->GetHomePosition()); - pSinclari->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + sinclari->GetMotionMaster()->MovePoint(1, sinclari->GetHomePosition()); + sinclari->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); } } // Cyanigosa is spawned but not tranformed, prefight event - Creature* pCyanigosa = instance->GetCreature(uiCyanigosa); - if (pCyanigosa && !pCyanigosa->HasAura(CYANIGOSA_SPELL_TRANSFORM)) + Creature* cyanigosa = GetCreature(DATA_CYANIGOSA); + if (cyanigosa && !cyanigosa->HasAura(CYANIGOSA_SPELL_TRANSFORM)) { if (uiCyanigosaEventTimer <= diff) { switch (uiCyanigosaEventPhase) { case 1: - pCyanigosa->CastSpell(pCyanigosa, CYANIGOSA_BLUE_AURA, false); - pCyanigosa->AI()->Talk(CYANIGOSA_SAY_SPAWN); + cyanigosa->CastSpell(cyanigosa, CYANIGOSA_BLUE_AURA, false); + cyanigosa->AI()->Talk(CYANIGOSA_SAY_SPAWN); uiCyanigosaEventTimer = 7*IN_MILLISECONDS; ++uiCyanigosaEventPhase; break; case 2: - pCyanigosa->GetMotionMaster()->MoveJump(MiddleRoomLocation.GetPositionX(), MiddleRoomLocation.GetPositionY(), MiddleRoomLocation.GetPositionZ(), 10.0f, 20.0f); - pCyanigosa->CastSpell(pCyanigosa, CYANIGOSA_BLUE_AURA, false); + cyanigosa->GetMotionMaster()->MoveJump(MiddleRoomLocation.GetPositionX(), MiddleRoomLocation.GetPositionY(), MiddleRoomLocation.GetPositionZ(), 10.0f, 20.0f); + cyanigosa->CastSpell(cyanigosa, CYANIGOSA_BLUE_AURA, false); uiCyanigosaEventTimer = 7*IN_MILLISECONDS; ++uiCyanigosaEventPhase; break; case 3: - pCyanigosa->RemoveAurasDueToSpell(CYANIGOSA_BLUE_AURA); - pCyanigosa->CastSpell(pCyanigosa, CYANIGOSA_SPELL_TRANSFORM, 0); - pCyanigosa->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_NON_ATTACKABLE); - pCyanigosa->SetReactState(REACT_AGGRESSIVE); + cyanigosa->RemoveAurasDueToSpell(CYANIGOSA_BLUE_AURA); + cyanigosa->CastSpell(cyanigosa, CYANIGOSA_SPELL_TRANSFORM, 0); + cyanigosa->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_NON_ATTACKABLE); + cyanigosa->SetReactState(REACT_AGGRESSIVE); uiCyanigosaEventTimer = 2*IN_MILLISECONDS; ++uiCyanigosaEventPhase; break; @@ -815,6 +679,11 @@ public: } } }; + + InstanceScript* GetInstanceScript(InstanceMap* map) const override + { + return new instance_violet_hold_InstanceMapScript(map); + } }; void AddSC_instance_violet_hold() diff --git a/src/server/scripts/Northrend/VioletHold/violet_hold.cpp b/src/server/scripts/Northrend/VioletHold/violet_hold.cpp index 645a9da4764..8bcc80b5a84 100644 --- a/src/server/scripts/Northrend/VioletHold/violet_hold.cpp +++ b/src/server/scripts/Northrend/VioletHold/violet_hold.cpp @@ -32,18 +32,18 @@ enum PortalCreatures { - CREATURE_AZURE_INVADER_1 = 30661, - CREATURE_AZURE_INVADER_2 = 30961, - CREATURE_AZURE_SPELLBREAKER_1 = 30662, - CREATURE_AZURE_SPELLBREAKER_2 = 30962, - CREATURE_AZURE_BINDER_1 = 30663, - CREATURE_AZURE_BINDER_2 = 30918, - CREATURE_AZURE_MAGE_SLAYER_1 = 30664, - CREATURE_AZURE_MAGE_SLAYER_2 = 30963, - CREATURE_AZURE_CAPTAIN = 30666, - CREATURE_AZURE_SORCEROR = 30667, - CREATURE_AZURE_RAIDER = 30668, - CREATURE_AZURE_STALKER = 32191 + NPC_AZURE_INVADER_1 = 30661, + NPC_AZURE_INVADER_2 = 30961, + NPC_AZURE_SPELLBREAKER_1 = 30662, + NPC_AZURE_SPELLBREAKER_2 = 30962, + NPC_AZURE_BINDER_1 = 30663, + NPC_AZURE_BINDER_2 = 30918, + NPC_AZURE_MAGE_SLAYER_1 = 30664, + NPC_AZURE_MAGE_SLAYER_2 = 30963, + NPC_AZURE_CAPTAIN = 30666, + NPC_AZURE_SORCEROR = 30667, + NPC_AZURE_RAIDER = 30668, + NPC_AZURE_STALKER = 32191 }; enum AzureInvaderSpells @@ -258,7 +258,7 @@ public: { case GOSSIP_ACTION_INFO_DEF+1: player->CLOSE_GOSSIP_MENU(); - ENSURE_AI(npc_sinclari_vh::npc_sinclariAI, (creature->AI()))->uiPhase = 1; + ENSURE_AI(npc_sinclari_vh::npc_sinclariAI, creature->AI())->uiPhase = 1; if (InstanceScript* instance = creature->GetInstanceScript()) instance->SetData(DATA_MAIN_EVENT_PHASE, SPECIAL); break; @@ -296,17 +296,12 @@ public: return true; } - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI<npc_sinclariAI>(creature); - } - struct npc_sinclariAI : public ScriptedAI { npc_sinclariAI(Creature* creature) : ScriptedAI(creature) { Initialize(); - instance = creature->GetInstanceScript(); + instance = creature->GetInstanceScript(); } void Initialize() @@ -345,8 +340,6 @@ public: void UpdateAI(uint32 uiDiff) override { - ScriptedAI::UpdateAI(uiDiff); - if (uiPhase) { if (uiTimer <= uiDiff) @@ -415,6 +408,10 @@ public: } }; + CreatureAI* GetAI(Creature* creature) const override + { + return GetInstanceAI<npc_sinclariAI>(creature); + } }; class npc_azure_saboteur : public CreatureScript @@ -422,14 +419,9 @@ class npc_azure_saboteur : public CreatureScript public: npc_azure_saboteur() : CreatureScript("npc_azure_saboteur") { } - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI<npc_azure_saboteurAI>(creature); - } - struct npc_azure_saboteurAI : public npc_escortAI { - npc_azure_saboteurAI(Creature* creature):npc_escortAI(creature) + npc_azure_saboteurAI(Creature* creature) : npc_escortAI(creature) { instance = creature->GetInstanceScript(); bHasGotMovingPoints = false; @@ -532,13 +524,16 @@ public: { me->CastSpell(me, SABOTEUR_SHIELD_DISRUPTION, false); me->DisappearAndDie(); - Creature* pSaboPort = ObjectAccessor::GetCreature((*me), instance->GetGuidData(DATA_SABOTEUR_PORTAL)); - if (pSaboPort) + if (Creature* pSaboPort = ObjectAccessor::GetCreature((*me), instance->GetGuidData(DATA_SABOTEUR_PORTAL))) pSaboPort->DisappearAndDie(); instance->SetData(DATA_START_BOSS_ENCOUNTER, 1); } }; + CreatureAI* GetAI(Creature* creature) const override + { + return GetInstanceAI<npc_azure_saboteurAI>(creature); + } }; class npc_teleportation_portal_vh : public CreatureScript @@ -546,11 +541,6 @@ class npc_teleportation_portal_vh : public CreatureScript public: npc_teleportation_portal_vh() : CreatureScript("npc_teleportation_portal_vh") { } - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI<npc_teleportation_portalAI>(creature); - } - struct npc_teleportation_portalAI : public ScriptedAI { npc_teleportation_portalAI(Creature* creature) : ScriptedAI(creature), listOfMobs(me) @@ -583,7 +573,6 @@ public: void MoveInLineOfSight(Unit* /*who*/) override { } - void UpdateAI(uint32 diff) override { if (instance->GetData(DATA_REMOVE_NPC) == 1) @@ -608,7 +597,7 @@ public: uint8 k = uiWaveCount < 12 ? 2 : 3; for (uint8 i = 0; i < k; ++i) { - uint32 entry = RAND(CREATURE_AZURE_CAPTAIN, CREATURE_AZURE_RAIDER, CREATURE_AZURE_STALKER, CREATURE_AZURE_SORCEROR); + uint32 entry = RAND(NPC_AZURE_CAPTAIN, NPC_AZURE_RAIDER, NPC_AZURE_STALKER, NPC_AZURE_SORCEROR); DoSummon(entry, me, 2.0f, 20000, TEMPSUMMON_DEAD_DESPAWN); } me->SetVisible(false); @@ -633,14 +622,14 @@ public: uint8 k = instance->GetData(DATA_WAVE_COUNT) < 12 ? 3 : 4; for (uint8 i = 0; i < k; ++i) { - uint32 entry = RAND(CREATURE_AZURE_INVADER_1, CREATURE_AZURE_INVADER_2, CREATURE_AZURE_SPELLBREAKER_1, CREATURE_AZURE_SPELLBREAKER_2, CREATURE_AZURE_MAGE_SLAYER_1, CREATURE_AZURE_MAGE_SLAYER_2, CREATURE_AZURE_BINDER_1, CREATURE_AZURE_BINDER_2); + uint32 entry = RAND(NPC_AZURE_INVADER_1, NPC_AZURE_INVADER_2, NPC_AZURE_SPELLBREAKER_1, NPC_AZURE_SPELLBREAKER_2, NPC_AZURE_MAGE_SLAYER_1, NPC_AZURE_MAGE_SLAYER_2, NPC_AZURE_BINDER_1, NPC_AZURE_BINDER_2); DoSummon(entry, me, 2.0f, 20000, TEMPSUMMON_DEAD_DESPAWN); } } else { bPortalGuardianOrKeeperOrEliteSpawn = true; - uint32 entry = RAND(CREATURE_PORTAL_GUARDIAN, CREATURE_PORTAL_KEEPER); + uint32 entry = RAND(NPC_PORTAL_GUARDIAN, NPC_PORTAL_KEEPER); if (Creature* pPortalKeeper = DoSummon(entry, me, 2.0f, 0, TEMPSUMMON_DEAD_DESPAWN)) me->CastSpell(pPortalKeeper, SPELL_PORTAL_CHANNEL, false); } @@ -674,11 +663,15 @@ public: } }; + CreatureAI* GetAI(Creature* creature) const override + { + return GetInstanceAI<npc_teleportation_portalAI>(creature); + } }; struct violet_hold_trashAI : public npc_escortAI { - violet_hold_trashAI(Creature* creature):npc_escortAI(creature) + violet_hold_trashAI(Creature* creature) : npc_escortAI(creature) { instance = creature->GetInstanceScript(); bHasGotMovingPoints = false; @@ -723,7 +716,7 @@ struct violet_hold_trashAI : public npc_escortAI } } - void UpdateAI(uint32) override + void UpdateAI(uint32 diff) override { if (instance->GetData(DATA_MAIN_EVENT_PHASE) != IN_PROGRESS) me->CastStop(); @@ -778,6 +771,8 @@ struct violet_hold_trashAI : public npc_escortAI SetDespawnAtEnd(false); Start(true, true); } + + npc_escortAI::UpdateAI(diff); } void JustDied(Unit* /*killer*/) override @@ -791,7 +786,6 @@ struct violet_hold_trashAI : public npc_escortAI DoCast(SPELL_DESTROY_DOOR_SEAL); instance->SetData(DATA_NPC_PRESENCE_AT_DOOR_ADD, 1); } - }; class npc_azure_invader : public CreatureScript @@ -799,11 +793,6 @@ class npc_azure_invader : public CreatureScript public: npc_azure_invader() : CreatureScript("npc_azure_invader") { } - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI<npc_azure_invaderAI>(creature); - } - struct npc_azure_invaderAI : public violet_hold_trashAI { npc_azure_invaderAI(Creature* creature) : violet_hold_trashAI(creature) @@ -833,12 +822,11 @@ public: void UpdateAI(uint32 diff) override { violet_hold_trashAI::UpdateAI(diff); - npc_escortAI::UpdateAI(diff); if (!UpdateVictim()) return; - if (me->GetEntry() == CREATURE_AZURE_INVADER_1) + if (me->GetEntry() == NPC_AZURE_INVADER_1) { if (uiCleaveTimer <= diff) { @@ -848,14 +836,13 @@ public: if (uiImpaleTimer <= diff) { - Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); - if (target) + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) DoCast(target, SPELL_IMPALE); uiImpaleTimer = 4000; } else uiImpaleTimer -= diff; } - if (me->GetEntry() == CREATURE_AZURE_INVADER_2) + if (me->GetEntry() == NPC_AZURE_INVADER_2) { if (uiBrutalStrikeTimer <= diff) { @@ -876,6 +863,10 @@ public: } }; + CreatureAI* GetAI(Creature* creature) const override + { + return GetInstanceAI<npc_azure_invaderAI>(creature); + } }; class npc_azure_binder : public CreatureScript @@ -883,11 +874,6 @@ class npc_azure_binder : public CreatureScript public: npc_azure_binder() : CreatureScript("npc_azure_binder") { } - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI<npc_azure_binderAI>(creature); - } - struct npc_azure_binderAI : public violet_hold_trashAI { npc_azure_binderAI(Creature* creature) : violet_hold_trashAI(creature) @@ -917,12 +903,11 @@ public: void UpdateAI(uint32 diff) override { violet_hold_trashAI::UpdateAI(diff); - npc_escortAI::UpdateAI(diff); if (!UpdateVictim()) return; - if (me->GetEntry() == CREATURE_AZURE_BINDER_1) + if (me->GetEntry() == NPC_AZURE_BINDER_1) { if (uiArcaneExplosionTimer <= diff) { @@ -930,16 +915,15 @@ public: uiArcaneExplosionTimer = 5000; } else uiArcaneExplosionTimer -= diff; - if (uiArcainBarrageTimer <= diff) + if (uiArcainBarrageTimer <= diff) { - Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); - if (target) - DoCast(target, SPELL_ARCANE_BARRAGE); + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(target, SPELL_ARCANE_BARRAGE); uiArcainBarrageTimer = 6000; } else uiArcainBarrageTimer -= diff; } - if (me->GetEntry() == CREATURE_AZURE_BINDER_2) + if (me->GetEntry() == NPC_AZURE_BINDER_2) { if (uiFrostNovaTimer <= diff) { @@ -949,8 +933,7 @@ public: if (uiFrostboltTimer <= diff) { - Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); - if (target) + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) DoCast(target, SPELL_FROSTBOLT); uiFrostboltTimer = 6000; } else uiFrostboltTimer -= diff; @@ -960,6 +943,10 @@ public: } }; + CreatureAI* GetAI(Creature* creature) const override + { + return GetInstanceAI<npc_azure_binderAI>(creature); + } }; class npc_azure_mage_slayer : public CreatureScript @@ -967,11 +954,6 @@ class npc_azure_mage_slayer : public CreatureScript public: npc_azure_mage_slayer() : CreatureScript("npc_azure_mage_slayer") { } - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI<npc_azure_mage_slayerAI>(creature); - } - struct npc_azure_mage_slayerAI : public violet_hold_trashAI { npc_azure_mage_slayerAI(Creature* creature) : violet_hold_trashAI(creature) @@ -997,12 +979,11 @@ public: void UpdateAI(uint32 diff) override { violet_hold_trashAI::UpdateAI(diff); - npc_escortAI::UpdateAI(diff); if (!UpdateVictim()) return; - if (me->GetEntry() == CREATURE_AZURE_MAGE_SLAYER_1) + if (me->GetEntry() == NPC_AZURE_MAGE_SLAYER_1) { if (uiArcaneEmpowermentTimer <= diff) { @@ -1011,12 +992,11 @@ public: } else uiArcaneEmpowermentTimer -= diff; } - if (me->GetEntry() == CREATURE_AZURE_MAGE_SLAYER_2) + if (me->GetEntry() == NPC_AZURE_MAGE_SLAYER_2) { if (uiSpellLockTimer <= diff) { - Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); - if (target) + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) DoCast(target, SPELL_SPELL_LOCK); uiSpellLockTimer = 9000; } else uiSpellLockTimer -= diff; @@ -1026,6 +1006,10 @@ public: } }; + CreatureAI* GetAI(Creature* creature) const override + { + return GetInstanceAI<npc_azure_mage_slayerAI>(creature); + } }; class npc_azure_raider : public CreatureScript @@ -1033,11 +1017,6 @@ class npc_azure_raider : public CreatureScript public: npc_azure_raider() : CreatureScript("npc_azure_raider") { } - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI<npc_azure_raiderAI>(creature); - } - struct npc_azure_raiderAI : public violet_hold_trashAI { npc_azure_raiderAI(Creature* creature) : violet_hold_trashAI(creature) @@ -1063,7 +1042,6 @@ public: void UpdateAI(uint32 diff) override { violet_hold_trashAI::UpdateAI(diff); - npc_escortAI::UpdateAI(diff); if (!UpdateVictim()) return; @@ -1084,6 +1062,10 @@ public: } }; + CreatureAI* GetAI(Creature* creature) const override + { + return GetInstanceAI<npc_azure_raiderAI>(creature); + } }; class npc_azure_stalker : public CreatureScript @@ -1114,7 +1096,6 @@ public: void UpdateAI(uint32 diff) override { violet_hold_trashAI::UpdateAI(diff); - npc_escortAI::UpdateAI(diff); if (!UpdateVictim()) return; @@ -1123,8 +1104,7 @@ public: { if (_tacticalBlinkTimer <= diff) { - Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 40, true); - if (target) + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 40, true)) DoCast(target, SPELL_TACTICAL_BLINK); _tacticalBlinkTimer = 6000; _tacticalBlinkCast = true; @@ -1135,8 +1115,8 @@ public: { if (_backstabTimer <= diff) { - Unit* target = SelectTarget(SELECT_TARGET_NEAREST, 0, 10, true); - DoCast(target, SPELL_BACKSTAB); + if (Unit* target = SelectTarget(SELECT_TARGET_NEAREST, 0, 10, true)) + DoCast(target, SPELL_BACKSTAB); _tacticalBlinkCast = false; _backstabTimer =1300; } else _backstabTimer -= diff; @@ -1191,36 +1171,32 @@ public: void UpdateAI(uint32 diff) override { violet_hold_trashAI::UpdateAI(diff); - npc_escortAI::UpdateAI(diff); if (!UpdateVictim()) return; - if (me->GetEntry() == CREATURE_AZURE_SPELLBREAKER_1) + if (me->GetEntry() == NPC_AZURE_SPELLBREAKER_1) { if (uiArcaneBlastTimer <= diff) { - Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); - if (target) + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) DoCast(target, SPELL_ARCANE_BLAST); uiArcaneBlastTimer = 6000; } else uiArcaneBlastTimer -= diff; if (uiSlowTimer <= diff) { - Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); - if (target) + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) DoCast(target, SPELL_SLOW); uiSlowTimer = 5000; } else uiSlowTimer -= diff; } - if (me->GetEntry() == CREATURE_AZURE_SPELLBREAKER_2) + if (me->GetEntry() == NPC_AZURE_SPELLBREAKER_2) { if (uiChainsOfIceTimer <= diff) { - Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); - if (target) + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) DoCast(target, SPELL_CHAINS_OF_ICE); uiChainsOfIceTimer = 7000; } else uiChainsOfIceTimer -= diff; @@ -1247,11 +1223,6 @@ class npc_azure_captain : public CreatureScript public: npc_azure_captain() : CreatureScript("npc_azure_captain") { } - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI<npc_azure_captainAI>(creature); - } - struct npc_azure_captainAI : public violet_hold_trashAI { npc_azure_captainAI(Creature* creature) : violet_hold_trashAI(creature) @@ -1277,7 +1248,6 @@ public: void UpdateAI(uint32 diff) override { violet_hold_trashAI::UpdateAI(diff); - npc_escortAI::UpdateAI(diff); if (!UpdateVictim()) return; @@ -1298,6 +1268,10 @@ public: } }; + CreatureAI* GetAI(Creature* creature) const override + { + return GetInstanceAI<npc_azure_captainAI>(creature); + } }; class npc_azure_sorceror : public CreatureScript @@ -1305,11 +1279,6 @@ class npc_azure_sorceror : public CreatureScript public: npc_azure_sorceror() : CreatureScript("npc_azure_sorceror") { } - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI<npc_azure_sorcerorAI>(creature); - } - struct npc_azure_sorcerorAI : public violet_hold_trashAI { npc_azure_sorcerorAI(Creature* creature) : violet_hold_trashAI(creature) @@ -1337,15 +1306,13 @@ public: void UpdateAI(uint32 diff) override { violet_hold_trashAI::UpdateAI(diff); - npc_escortAI::UpdateAI(diff); if (!UpdateVictim()) return; if (uiArcaneStreamTimer <= diff) { - Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); - if (target) + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) DoCast(target, SPELL_ARCANE_STREAM); uiArcaneStreamTimer = urand(0, 5000)+5000; uiArcaneStreamTimerStartingValueHolder = uiArcaneStreamTimer; @@ -1360,6 +1327,11 @@ public: DoMeleeAttackIfReady(); } }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetInstanceAI<npc_azure_sorcerorAI>(creature); + } }; diff --git a/src/server/scripts/Northrend/VioletHold/violet_hold.h b/src/server/scripts/Northrend/VioletHold/violet_hold.h index 404d1f493e6..275a7467d83 100644 --- a/src/server/scripts/Northrend/VioletHold/violet_hold.h +++ b/src/server/scripts/Northrend/VioletHold/violet_hold.h @@ -18,13 +18,18 @@ #ifndef DEF_VIOLET_HOLD_H #define DEF_VIOLET_HOLD_H -#define DataHeader "VIO" +#define DataHeader "VH" + +uint32 const EncounterCount = 3; enum Data { + // Main encounters DATA_1ST_BOSS_EVENT, DATA_2ND_BOSS_EVENT, - DATA_CYANIGOSA_EVENT, + DATA_CYANIGOSA, + + // Misc DATA_WAVE_COUNT, DATA_REMOVE_NPC, DATA_PORTAL_LOCATION, @@ -38,10 +43,8 @@ enum Data DATA_ACTIVATE_CRYSTAL, DATA_MAIN_EVENT_PHASE, DATA_DEFENSELESS, -}; -enum Data64 -{ + // Bosses DATA_MORAGG, DATA_EREKEM, DATA_EREKEM_GUARD_1, @@ -50,7 +53,8 @@ enum Data64 DATA_LAVANTHOR, DATA_XEVOZZ, DATA_ZURAMAT, - DATA_CYANIGOSA, + + // Cells DATA_MORAGG_CELL, DATA_EREKEM_CELL, DATA_EREKEM_LEFT_GUARD_CELL, @@ -59,6 +63,8 @@ enum Data64 DATA_LAVANTHOR_CELL, DATA_XEVOZZ_CELL, DATA_ZURAMAT_CELL, + + // Misc DATA_MAIN_DOOR, DATA_SINCLARI, DATA_TELEPORTATION_PORTAL, @@ -81,33 +87,48 @@ enum Bosses enum CreaturesIds { - CREATURE_TELEPORTATION_PORTAL = 31011, - CREATURE_PORTAL_GUARDIAN = 30660, - CREATURE_PORTAL_KEEPER = 30695, - CREATURE_XEVOZZ = 29266, - CREATURE_LAVANTHOR = 29312, - CREATURE_ICHORON = 29313, - CREATURE_ZURAMAT = 29314, - CREATURE_EREKEM = 29315, - CREATURE_EREKEM_GUARD = 29395, - CREATURE_MORAGG = 29316, - CREATURE_CYANIGOSA = 31134, - CREATURE_SINCLARI = 30658, - CREATURE_SABOTEOUR = 31079, - NPC_VIOLET_HOLD_GUARD = 30659, - NPC_DEFENSE_SYSTEM = 30837 + NPC_TELEPORTATION_PORTAL = 31011, + NPC_PORTAL_GUARDIAN = 30660, + NPC_PORTAL_KEEPER = 30695, + NPC_XEVOZZ = 29266, + NPC_LAVANTHOR = 29312, + NPC_ICHORON = 29313, + NPC_ZURAMAT = 29314, + NPC_EREKEM = 29315, + NPC_EREKEM_GUARD = 29395, + NPC_MORAGG = 29316, + NPC_CYANIGOSA = 31134, + NPC_SINCLARI = 30658, + NPC_SABOTEOUR = 31079, + NPC_VIOLET_HOLD_GUARD = 30659, + NPC_DEFENSE_SYSTEM = 30837 +}; + +enum GameObjectIds +{ + GO_MAIN_DOOR = 191723, + GO_XEVOZZ_DOOR = 191556, + GO_LAVANTHOR_DOOR = 191566, + GO_ICHORON_DOOR = 191722, + GO_ZURAMAT_DOOR = 191565, + GO_EREKEM_DOOR = 191564, + GO_EREKEM_GUARD_1_DOOR = 191563, + GO_EREKEM_GUARD_2_DOOR = 191562, + GO_MORAGG_DOOR = 191606, + GO_INTRO_ACTIVATION_CRYSTAL = 193615, + GO_ACTIVATION_CRYSTAL = 193611 }; enum WorldStateIds { - WORLD_STATE_VH = 3816, - WORLD_STATE_VH_PRISON_STATE = 3815, - WORLD_STATE_VH_WAVE_COUNT = 3810, + WORLD_STATE_VH = 3816, + WORLD_STATE_VH_PRISON_STATE = 3815, + WORLD_STATE_VH_WAVE_COUNT = 3810, }; enum Events { - EVENT_ACTIVATE_CRYSTAL = 20001 + EVENT_ACTIVATE_CRYSTAL = 20001 }; #endif diff --git a/src/server/scripts/OutdoorPvP/OutdoorPvPNA.h b/src/server/scripts/OutdoorPvP/OutdoorPvPNA.h index 80c8041bc6d..fac9d8fa357 100644 --- a/src/server/scripts/OutdoorPvP/OutdoorPvPNA.h +++ b/src/server/scripts/OutdoorPvP/OutdoorPvPNA.h @@ -261,13 +261,13 @@ class OPvPCapturePointNA : public OPvPCapturePoint public: OPvPCapturePointNA(OutdoorPvP* pvp); - bool Update(uint32 diff); + bool Update(uint32 diff) override; - void ChangeState(); + void ChangeState() override; - void FillInitialWorldStates(WorldPacket & data); + void FillInitialWorldStates(WorldPacket & data) override; - bool HandleCustomSpell(Player* player, uint32 spellId, GameObject* go); + bool HandleCustomSpell(Player* player, uint32 spellId, GameObject* go) override; int32 HandleOpenGo(Player* player, ObjectGuid guid) override; diff --git a/src/server/scripts/Outland/Auchindoun/AuchenaiCrypts/boss_shirrak_the_dead_watcher.cpp b/src/server/scripts/Outland/Auchindoun/AuchenaiCrypts/boss_shirrak_the_dead_watcher.cpp index 662bad46162..263fd8340b9 100644 --- a/src/server/scripts/Outland/Auchindoun/AuchenaiCrypts/boss_shirrak_the_dead_watcher.cpp +++ b/src/server/scripts/Outland/Auchindoun/AuchenaiCrypts/boss_shirrak_the_dead_watcher.cpp @@ -113,7 +113,7 @@ public: Map::PlayerList const &PlayerList = map->GetPlayers(); for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) if (Player* i_pl = i->GetSource()) - if (i_pl->IsAlive() && (dist = i_pl->IsWithinDist(me, 45))) + if (i_pl->IsAlive() && (dist = i_pl->GetDistance(me)) < 45) { i_pl->RemoveAurasDueToSpell(SPELL_INHIBITMAGIC); me->AddAura(SPELL_INHIBITMAGIC, i_pl); diff --git a/src/server/scripts/Outland/CMakeLists.txt b/src/server/scripts/Outland/CMakeLists.txt index 24658dbc21f..42621b76941 100644 --- a/src/server/scripts/Outland/CMakeLists.txt +++ b/src/server/scripts/Outland/CMakeLists.txt @@ -27,6 +27,7 @@ set(scripts_STAT_SRCS Outland/HellfireCitadel/ShatteredHalls/shattered_halls.h Outland/HellfireCitadel/ShatteredHalls/boss_warchief_kargath_bladefist.cpp Outland/HellfireCitadel/ShatteredHalls/boss_nethekurse.cpp + Outland/HellfireCitadel/ShatteredHalls/shattered_halls.cpp Outland/HellfireCitadel/ShatteredHalls/instance_shattered_halls.cpp Outland/HellfireCitadel/ShatteredHalls/boss_warbringer_omrogg.cpp Outland/CoilfangReservoir/SteamVault/boss_mekgineer_steamrigger.cpp diff --git a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warchief_kargath_bladefist.cpp b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warchief_kargath_bladefist.cpp index 21ed710f4d8..7f2e08b39ca 100644 --- a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warchief_kargath_bladefist.cpp +++ b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warchief_kargath_bladefist.cpp @@ -87,11 +87,11 @@ class boss_warchief_kargath_bladefist : public CreatureScript resetcheck_timer = 5000; } - void SetData(uint32 type, uint32 data) override + void DoAction(int32 action) override { - if (type == 1) + if (action == ACTION_EXECUTIONER_TAUNT) { - switch (data) + switch (instance->GetData(DATA_TEAM_IN_INSTANCE)) { case ALLIANCE: Talk(SAY_CALL_EXECUTIONER_A); diff --git a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/instance_shattered_halls.cpp b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/instance_shattered_halls.cpp index 6939b15585a..5cfae286f9b 100644 --- a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/instance_shattered_halls.cpp +++ b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/instance_shattered_halls.cpp @@ -32,20 +32,11 @@ EndScriptData */ #include "SpellAuras.h" #include "shattered_halls.h" -enum Spells -{ - SPELL_CLEAVE = 15284, - - SPELL_EXECUTE_1 = 39288, - SPELL_EXECUTE_2, - SPELL_EXECUTE_3 -}; - DoorData const doorData[] = { - {GO_GRAND_WARLOCK_CHAMBER_DOOR_1, DATA_NETHEKURSE, DOOR_TYPE_PASSAGE, BOUNDARY_S }, - {GO_GRAND_WARLOCK_CHAMBER_DOOR_2, DATA_NETHEKURSE, DOOR_TYPE_PASSAGE, BOUNDARY_N }, - {0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE} + { GO_GRAND_WARLOCK_CHAMBER_DOOR_1, DATA_NETHEKURSE, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, + { GO_GRAND_WARLOCK_CHAMBER_DOOR_2, DATA_NETHEKURSE, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, + { 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE } }; class instance_shattered_halls : public InstanceMapScript @@ -77,9 +68,7 @@ class instance_shattered_halls : public InstanceMapScript if (!_team) _team = player->GetTeam(); - player->RemoveAurasDueToSpell(SPELL_EXECUTE_1); - player->RemoveAurasDueToSpell(SPELL_EXECUTE_2); - player->RemoveAurasDueToSpell(SPELL_EXECUTE_3); + player->CastSpell(player, SPELL_REMOVE_KARGATH_EXECUTIONER, true); if (!executionTimer || executionerGUID.IsEmpty()) return; @@ -87,13 +76,13 @@ class instance_shattered_halls : public InstanceMapScript switch (executed) { case 0: - ex = player->AddAura(SPELL_EXECUTE_1, player); + ex = player->AddAura(SPELL_KARGATH_EXECUTIONER_1, player); break; case 1: - ex = player->AddAura(SPELL_EXECUTE_2, player); + ex = player->AddAura(SPELL_KARGATH_EXECUTIONER_2, player); break; case 2: - ex = player->AddAura(SPELL_EXECUTE_3, player); + ex = player->AddAura(SPELL_KARGATH_EXECUTIONER_3, player); break; default: break; @@ -151,10 +140,22 @@ class instance_shattered_halls : public InstanceMapScript break; case NPC_SHATTERED_EXECUTIONER: executionTimer = 55 * MINUTE * IN_MILLISECONDS; - DoCastSpellOnPlayers(SPELL_EXECUTE_1); + DoCastSpellOnPlayers(SPELL_KARGATH_EXECUTIONER_1); executionerGUID = creature->GetGUID(); SaveToDB(); break; + case NPC_CAPTAIN_ALINA: + case NPC_CAPTAIN_BONESHATTER: + victimsGUID[0] = creature->GetGUID(); + break; + case NPC_ALLIANCE_VICTIM_1: + case NPC_HORDE_VICTIM_1: + victimsGUID[1] = creature->GetGUID(); + break; + case NPC_ALLIANCE_VICTIM_2: + case NPC_HORDE_VICTIM_2: + victimsGUID[2] = creature->GetGUID(); + break; } } @@ -168,16 +169,14 @@ class instance_shattered_halls : public InstanceMapScript case DATA_SHATTERED_EXECUTIONER: if (state == DONE) { - DoRemoveAurasDueToSpellOnPlayers(SPELL_EXECUTE_1); - DoRemoveAurasDueToSpellOnPlayers(SPELL_EXECUTE_2); - DoRemoveAurasDueToSpellOnPlayers(SPELL_EXECUTE_3); + DoCastSpellOnPlayers(SPELL_REMOVE_KARGATH_EXECUTIONER); executionTimer = 0; SaveToDB(); } break; case DATA_KARGATH: if (Creature* executioner = instance->GetCreature(executionerGUID)) - executioner->AI()->Reset(); + executioner->AI()->Reset(); // trigger removal of IMMUNE_TO_PC flag break; case DATA_OMROGG: break; @@ -191,16 +190,16 @@ class instance_shattered_halls : public InstanceMapScript { case NPC_GRAND_WARLOCK_NETHEKURSE: return nethekurseGUID; - break; case NPC_KARGATH_BLADEFIST: return kargathGUID; - break; case NPC_SHATTERED_EXECUTIONER: return executionerGUID; - break; + case DATA_FIRST_PRISONER: + case DATA_SECOND_PRISONER: + case DATA_THIRD_PRISONER: + return victimsGUID[data - DATA_FIRST_PRISONER]; default: return ObjectGuid::Empty; - break; } } @@ -253,13 +252,10 @@ class instance_shattered_halls : public InstanceMapScript { case DATA_PRISONERS_EXECUTED: return executed; - break; case DATA_TEAM_IN_INSTANCE: return _team; - break; default: return 0; - break; } } @@ -269,27 +265,25 @@ class instance_shattered_halls : public InstanceMapScript return; if (executionTimer <= diff) - { + { + DoCastSpellOnPlayers(SPELL_REMOVE_KARGATH_EXECUTIONER); switch (++executed) { case 1: - DoRemoveAurasDueToSpellOnPlayers(SPELL_EXECUTE_1); - DoCastSpellOnPlayers(SPELL_EXECUTE_2); + DoCastSpellOnPlayers(SPELL_KARGATH_EXECUTIONER_2); executionTimer = 10 * MINUTE * IN_MILLISECONDS; break; case 2: - DoRemoveAurasDueToSpellOnPlayers(SPELL_EXECUTE_2); - DoCastSpellOnPlayers(SPELL_EXECUTE_3); + DoCastSpellOnPlayers(SPELL_KARGATH_EXECUTIONER_3); executionTimer = 15 * MINUTE * IN_MILLISECONDS; break; default: - DoRemoveAurasDueToSpellOnPlayers(SPELL_EXECUTE_3); executionTimer = 0; break; } if (Creature* executioner = instance->GetCreature(executionerGUID)) - executioner->AI()->SetData(1, executed); + executioner->AI()->SetData(DATA_PRISONERS_EXECUTED, executed); SaveToDB(); } @@ -297,10 +291,11 @@ class instance_shattered_halls : public InstanceMapScript executionTimer -= diff; } - protected: + private: ObjectGuid nethekurseGUID; ObjectGuid kargathGUID; ObjectGuid executionerGUID; + ObjectGuid victimsGUID[3]; uint8 executed; uint32 executionTimer; @@ -308,189 +303,7 @@ class instance_shattered_halls : public InstanceMapScript }; }; -class at_nethekurse_exit : public AreaTriggerScript -{ - public: - at_nethekurse_exit() : AreaTriggerScript("at_nethekurse_exit") { }; - - bool OnTrigger(Player* player, AreaTriggerEntry const*) override - { - if (InstanceScript* is = player->GetInstanceScript()) - { - if (is->instance->IsHeroic()) - { - Creature* executioner = nullptr; - - is->instance->LoadGrid(Executioner.GetPositionX(), Executioner.GetPositionY()); - if (Creature* kargath = ObjectAccessor::GetCreature(*player, is->GetGuidData(NPC_KARGATH_BLADEFIST))) - { - if (is->GetGuidData(NPC_SHATTERED_EXECUTIONER).IsEmpty()) - { - executioner = kargath->SummonCreature(NPC_SHATTERED_EXECUTIONER, Executioner); - kargath->AI()->SetData(1, is->GetData(DATA_TEAM_IN_INSTANCE)); - } - } - - if (executioner) - for (uint8 i = 0; i < VictimCount; ++i) - executioner->SummonCreature(executionerVictims[i](is->GetData(DATA_TEAM_IN_INSTANCE)), executionerVictims[i].GetPos()); - } - } - - return false; - } -}; - -class boss_shattered_executioner : public CreatureScript -{ - public: - boss_shattered_executioner() : CreatureScript("boss_shattered_executioner") { } - - struct boss_shattered_executionerAI : public BossAI - { - boss_shattered_executionerAI(Creature* creature) : BossAI(creature, DATA_SHATTERED_EXECUTIONER) - { - Initialize(); - }; - - void Initialize() - { - cleaveTimer = 500; - me->ResetLootMode(); - switch (instance->GetData(DATA_PRISONERS_EXECUTED)) - { - case 0: - me->AddLootMode(LOOT_MODE_HARD_MODE_3); - case 1: - me->AddLootMode(LOOT_MODE_HARD_MODE_2); - case 2: - me->AddLootMode(LOOT_MODE_HARD_MODE_1); - } - } - - void Reset() override - { - _Reset(); - if (instance->GetBossState(DATA_KARGATH) == DONE) - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); - else - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); - - Initialize(); - } - - void JustSummoned(Creature*) override { } - - void JustDied(Unit*) override - { - _JustDied(); - Map::PlayerList const &players = instance->instance->GetPlayers(); - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - { - Player* pl = itr->GetSource(); - uint32 qId = pl->GetTeam() == ALLIANCE ? QUEST_IMPRISONED_A : QUEST_IMPRISONED_H; - if (pl->GetQuestStatus(qId) != QUEST_STATUS_NONE && pl->GetQuestStatus(qId) != QUEST_STATUS_FAILED) - pl->CompleteQuest(qId); - } - } - - void SetData(uint32 type, uint32 data) override - { - if (type == 1) - { - uint32 entry = executionerVictims[data - 1](instance->GetData(DATA_TEAM_IN_INSTANCE)); - if (Creature* victim = me->FindNearestCreature(entry, 30.0f, true)) - me->Kill(victim); - - if (data == 1) - { - Map::PlayerList const &players = instance->instance->GetPlayers(); - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - { - Player* pl = itr->GetSource(); - uint32 qId = pl->GetTeam() == ALLIANCE ? QUEST_IMPRISONED_A : QUEST_IMPRISONED_H; - if (pl->GetQuestStatus(qId) == QUEST_STATUS_INCOMPLETE) - pl->FailQuest(qId); - } - } - - switch (data) - { - case 3: - me->RemoveLootMode(LOOT_MODE_HARD_MODE_1); - case 2: - me->RemoveLootMode(LOOT_MODE_HARD_MODE_2); - case 1: - me->RemoveLootMode(LOOT_MODE_HARD_MODE_3); - default: - break; - } - } - } - - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim()) - return; - - if (cleaveTimer <= diff) - { - DoCast(SPELL_CLEAVE); - cleaveTimer = urand(5000, 7000); - } - else - cleaveTimer -= diff; - - DoMeleeAttackIfReady(); - } - private: - uint32 cleaveTimer; - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI<boss_shattered_executionerAI>(creature); - } -}; - -class spell_kargath_executioner : public SpellScriptLoader -{ - public: - spell_kargath_executioner() : SpellScriptLoader("spell_kargath_executioner") { } - - class spell_kargath_executioner_AuraScript : public AuraScript - { - PrepareAuraScript(spell_kargath_executioner_AuraScript); - - bool AreaCheck(Unit* target) - { - if (target->GetMap()->GetId() != 540) - return false; - - return true; - } - - bool Load() override - { - return GetCaster()->GetTypeId() == TYPEID_PLAYER; - } - - void Register() override - { - DoCheckAreaTarget += AuraCheckAreaTargetFn(spell_kargath_executioner_AuraScript::AreaCheck); - } - }; - - AuraScript* GetAuraScript() const override - { - return new spell_kargath_executioner_AuraScript(); - } -}; - void AddSC_instance_shattered_halls() { new instance_shattered_halls(); - new at_nethekurse_exit(); - new boss_shattered_executioner(); - new spell_kargath_executioner(); } diff --git a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/shattered_halls.cpp b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/shattered_halls.cpp new file mode 100644 index 00000000000..500b0ae4bcb --- /dev/null +++ b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/shattered_halls.cpp @@ -0,0 +1,255 @@ +/* + * 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 "SpellScript.h" +#include "SpellAuraEffects.h" +#include "InstanceScript.h" +#include "Player.h" +#include "SpellAuras.h" +#include "shattered_halls.h" + +class at_nethekurse_exit : public AreaTriggerScript +{ + public: + at_nethekurse_exit() : AreaTriggerScript("at_nethekurse_exit") { }; + + bool OnTrigger(Player* player, AreaTriggerEntry const*) override + { + if (InstanceScript* is = player->GetInstanceScript()) + { + if (is->instance->IsHeroic()) + { + Creature* executioner = nullptr; + + is->instance->LoadGrid(Executioner.GetPositionX(), Executioner.GetPositionY()); + if (Creature* kargath = ObjectAccessor::GetCreature(*player, is->GetGuidData(NPC_KARGATH_BLADEFIST))) + { + if (is->GetGuidData(NPC_SHATTERED_EXECUTIONER).IsEmpty()) + { + executioner = kargath->SummonCreature(NPC_SHATTERED_EXECUTIONER, Executioner); + kargath->AI()->DoAction(ACTION_EXECUTIONER_TAUNT); + } + } + + if (executioner) + for (uint8 i = 0; i < VictimCount; ++i) + executioner->SummonCreature(executionerVictims[i](is->GetData(DATA_TEAM_IN_INSTANCE)), executionerVictims[i].GetPos()); + } + } + + return false; + } +}; + +enum Spells +{ + SPELL_CLEAVE = 15284 +}; + +class boss_shattered_executioner : public CreatureScript +{ + public: + boss_shattered_executioner() : CreatureScript("boss_shattered_executioner") { } + + struct boss_shattered_executionerAI : public BossAI + { + boss_shattered_executionerAI(Creature* creature) : BossAI(creature, DATA_SHATTERED_EXECUTIONER) + { + Initialize(); + }; + + void Initialize() + { + cleaveTimer = 500; + } + + void Reset() override + { + _Reset(); + + // _Reset() resets the loot mode, so we add them again, if any + uint32 prisonersExecuted = instance->GetData(DATA_PRISONERS_EXECUTED); + if (prisonersExecuted == 0) + me->AddLootMode(LOOT_MODE_HARD_MODE_3); + if (prisonersExecuted <= 1) + me->AddLootMode(LOOT_MODE_HARD_MODE_2); + if (prisonersExecuted <= 2) + me->AddLootMode(LOOT_MODE_HARD_MODE_1); + + if (instance->GetBossState(DATA_KARGATH) == DONE) + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); + else + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); + + Initialize(); + } + + void JustSummoned(Creature*) override { } // avoid despawn of prisoners on death/reset + + void JustDied(Unit*) override + { + _JustDied(); + + if (instance->GetData(DATA_PRISONERS_EXECUTED) > 0) + return; + + Map::PlayerList const &players = instance->instance->GetPlayers(); + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + { + Player* pl = itr->GetSource(); + uint32 qId = pl->GetTeam() == ALLIANCE ? QUEST_IMPRISONED_A : QUEST_IMPRISONED_H; + if (pl->GetQuestStatus(qId) == QUEST_STATUS_INCOMPLETE) + pl->CompleteQuest(qId); + } + } + + void SetData(uint32 type, uint32 data) override + { + if (type == DATA_PRISONERS_EXECUTED && data <= 3) + { + if (Creature* victim = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FIRST_PRISONER + data - 1))) + me->Kill(victim); + + if (data == 1) + { + Map::PlayerList const &players = instance->instance->GetPlayers(); + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + { + Player* pl = itr->GetSource(); + uint32 qId = pl->GetTeam() == ALLIANCE ? QUEST_IMPRISONED_A : QUEST_IMPRISONED_H; + if (pl->GetQuestStatus(qId) == QUEST_STATUS_INCOMPLETE) + pl->FailQuest(qId); + } + } + + switch (data) + { + case 3: + me->RemoveLootMode(LOOT_MODE_HARD_MODE_1); + case 2: + me->RemoveLootMode(LOOT_MODE_HARD_MODE_2); + case 1: + me->RemoveLootMode(LOOT_MODE_HARD_MODE_3); + default: + break; + } + } + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + if (cleaveTimer <= diff) + { + DoCast(SPELL_CLEAVE); + cleaveTimer = urand(5000, 7000); + } + else + cleaveTimer -= diff; + + DoMeleeAttackIfReady(); + } + private: + uint32 cleaveTimer; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetInstanceAI<boss_shattered_executionerAI>(creature); + } +}; + +class spell_kargath_executioner : public SpellScriptLoader +{ + public: + spell_kargath_executioner() : SpellScriptLoader("spell_kargath_executioner") { } + + class spell_kargath_executioner_AuraScript : public AuraScript + { + PrepareAuraScript(spell_kargath_executioner_AuraScript); + + bool AreaCheck(Unit* target) + { + if (target->GetMap()->GetId() != 540) + return false; + + return true; + } + + bool Load() override + { + return GetCaster()->GetTypeId() == TYPEID_PLAYER; + } + + void Register() override + { + DoCheckAreaTarget += AuraCheckAreaTargetFn(spell_kargath_executioner_AuraScript::AreaCheck); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_kargath_executioner_AuraScript(); + } +}; + +class spell_remove_kargath_executioner : public SpellScriptLoader +{ + public: + spell_remove_kargath_executioner() : SpellScriptLoader("spell_remove_kargath_executioner") { } + + class spell_remove_kargath_executioner_SpellScript : public SpellScript + { + PrepareSpellScript(spell_remove_kargath_executioner_SpellScript); + + void HandleScript(SpellEffIndex /*effIndex*/) + { + Unit* target = GetCaster(); + + target->RemoveAurasDueToSpell(SPELL_KARGATH_EXECUTIONER_1); + target->RemoveAurasDueToSpell(SPELL_KARGATH_EXECUTIONER_2); + target->RemoveAurasDueToSpell(SPELL_KARGATH_EXECUTIONER_3); + } + + bool Load() override + { + return GetCaster()->GetTypeId() == TYPEID_PLAYER; + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_remove_kargath_executioner_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_remove_kargath_executioner_SpellScript(); + } +}; + +void AddSC_shattered_halls() +{ + new at_nethekurse_exit(); + new boss_shattered_executioner(); + new spell_kargath_executioner(); + new spell_remove_kargath_executioner(); +} diff --git a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/shattered_halls.h b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/shattered_halls.h index adc07bec2ff..894cc9c40a6 100644 --- a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/shattered_halls.h +++ b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/shattered_halls.h @@ -33,7 +33,11 @@ enum DataTypes DATA_SHATTERED_EXECUTIONER = 3, DATA_PRISONERS_EXECUTED = 4, - DATA_TEAM_IN_INSTANCE = 5 + DATA_TEAM_IN_INSTANCE = 5, + + DATA_FIRST_PRISONER, + DATA_SECOND_PRISONER, + DATA_THIRD_PRISONER }; enum CreatureIds @@ -70,6 +74,20 @@ enum QuestIds QUEST_IMPRISONED_H = 9525 }; +enum InstanceSpells +{ + SPELL_KARGATH_EXECUTIONER_1 = 39288, + SPELL_KARGATH_EXECUTIONER_2 = 39289, + SPELL_KARGATH_EXECUTIONER_3 = 39290, + + SPELL_REMOVE_KARGATH_EXECUTIONER = 39291 +}; + +enum Actions +{ + ACTION_EXECUTIONER_TAUNT = 1 +}; + const Position Executioner = { 152.8524f, -83.63912f, 2.021005f, 0.06981317f }; struct FactionSpawnerHelper @@ -77,7 +95,7 @@ struct FactionSpawnerHelper FactionSpawnerHelper(uint32 allianceEntry, uint32 hordeEntry, const Position& pos) : _allianceNPC(allianceEntry), _hordeNPC(hordeEntry), _spawnPos(pos) { } inline uint32 operator()(uint32 teamID) const { return teamID == ALLIANCE ? _allianceNPC : _hordeNPC; } - inline const Position GetPos() const { return _spawnPos; } + inline Position const& GetPos() const { return _spawnPos; } private: const uint32 _allianceNPC; diff --git a/src/server/scripts/Outland/TempestKeep/Eye/boss_alar.cpp b/src/server/scripts/Outland/TempestKeep/Eye/boss_alar.cpp index cc825afd3a0..48508aa4790 100644 --- a/src/server/scripts/Outland/TempestKeep/Eye/boss_alar.cpp +++ b/src/server/scripts/Outland/TempestKeep/Eye/boss_alar.cpp @@ -77,12 +77,11 @@ class boss_alar : public CreatureScript public: boss_alar() : CreatureScript("boss_alar") { } - struct boss_alarAI : public ScriptedAI + struct boss_alarAI : public BossAI { - boss_alarAI(Creature* creature) : ScriptedAI(creature) + boss_alarAI(Creature* creature) : BossAI(creature, DATA_ALAR) { Initialize(); - instance = creature->GetInstanceScript(); DefaultMoveSpeedRate = creature->GetSpeedRate(MOVE_RUN); DiveBomb_Timer = 0; MeltArmor_Timer = 0; @@ -105,8 +104,6 @@ class boss_alar : public CreatureScript cur_wp = 4; } - InstanceScript* instance; - WaitEventType WaitEvent; uint32 WaitTimer; @@ -129,9 +126,8 @@ class boss_alar : public CreatureScript void Reset() override { - instance->SetData(DATA_ALAREVENT, NOT_STARTED); - Initialize(); + _Reset(); me->SetDisplayId(me->GetNativeDisplayId()); me->SetSpeed(MOVE_RUN, DefaultMoveSpeedRate); @@ -145,18 +141,11 @@ class boss_alar : public CreatureScript void EnterCombat(Unit* /*who*/) override { - instance->SetData(DATA_ALAREVENT, IN_PROGRESS); - + _EnterCombat(); me->SetDisableGravity(true); // after enterevademode will be set walk movement - DoZoneInCombat(); me->setActive(true); } - void JustDied(Unit* /*killer*/) override - { - instance->SetData(DATA_ALAREVENT, DONE); - } - void JustSummoned(Creature* summon) override { if (summon->GetEntry() == CREATURE_EMBER_OF_ALAR) @@ -508,7 +497,7 @@ class npc_ember_of_alar : public CreatureScript DoCast(me, SPELL_EMBER_BLAST, true); me->SetDisplayId(11686); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - if (instance->GetData(DATA_ALAREVENT) == 2) + if (instance->GetBossState(DATA_ALAR) == IN_PROGRESS) { if (Unit* Alar = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_ALAR))) { diff --git a/src/server/scripts/Outland/TempestKeep/Eye/boss_astromancer.cpp b/src/server/scripts/Outland/TempestKeep/Eye/boss_astromancer.cpp index 6021e38d3cf..ff9bdf15276 100644 --- a/src/server/scripts/Outland/TempestKeep/Eye/boss_astromancer.cpp +++ b/src/server/scripts/Outland/TempestKeep/Eye/boss_astromancer.cpp @@ -92,17 +92,13 @@ class boss_high_astromancer_solarian : public CreatureScript { public: - boss_high_astromancer_solarian() - : CreatureScript("boss_high_astromancer_solarian") - { - } + boss_high_astromancer_solarian() : CreatureScript("boss_high_astromancer_solarian") { } - struct boss_high_astromancer_solarianAI : public ScriptedAI + struct boss_high_astromancer_solarianAI : public BossAI { - boss_high_astromancer_solarianAI(Creature* creature) : ScriptedAI(creature), Summons(me) + boss_high_astromancer_solarianAI(Creature* creature) : BossAI(creature, DATA_HIGH_ASTROMANCER_SOLARIAN) { Initialize(); - instance = creature->GetInstanceScript(); defaultarmor = creature->GetArmor(); defaultsize = creature->GetObjectScale(); @@ -126,9 +122,6 @@ class boss_high_astromancer_solarian : public CreatureScript Phase = 1; } - InstanceScript* instance; - SummonList Summons; - uint8 Phase; uint32 ArcaneMissiles_Timer; @@ -152,16 +145,13 @@ class boss_high_astromancer_solarian : public CreatureScript void Reset() override { Initialize(); - - instance->SetData(DATA_HIGHASTROMANCERSOLARIANEVENT, NOT_STARTED); - + _Reset(); me->SetArmor(defaultarmor); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); me->SetVisible(true); me->SetObjectScale(defaultsize); me->SetDisplayId(MODEL_HUMAN); - Summons.DespawnAll(); } void KilledUnit(Unit* /*victim*/) override @@ -174,15 +164,13 @@ class boss_high_astromancer_solarian : public CreatureScript me->SetObjectScale(defaultsize); me->SetDisplayId(MODEL_HUMAN); Talk(SAY_DEATH); - instance->SetData(DATA_HIGHASTROMANCERSOLARIANEVENT, DONE); + _JustDied(); } void EnterCombat(Unit* /*who*/) override { Talk(SAY_AGGRO); - DoZoneInCombat(); - - instance->SetData(DATA_HIGHASTROMANCERSOLARIANEVENT, IN_PROGRESS); + _EnterCombat(); } void SummonMinion(uint32 entry, float x, float y, float z) @@ -193,7 +181,7 @@ class boss_high_astromancer_solarian : public CreatureScript if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) Summoned->AI()->AttackStart(target); - Summons.Summon(Summoned); + summons.Summon(Summoned); } } @@ -431,10 +419,7 @@ class npc_solarium_priest : public CreatureScript { public: - npc_solarium_priest() - : CreatureScript("npc_solarium_priest") - { - } + npc_solarium_priest() : CreatureScript("npc_solarium_priest") { } struct npc_solarium_priestAI : public ScriptedAI { @@ -462,9 +447,7 @@ class npc_solarium_priest : public CreatureScript Initialize(); } - void EnterCombat(Unit* /*who*/) override - { - } + void EnterCombat(Unit* /*who*/) override { } void UpdateAI(uint32 diff) override { diff --git a/src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp b/src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp index 9aa1981eabb..f5583c0bc53 100644 --- a/src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp +++ b/src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp @@ -286,17 +286,13 @@ class boss_kaelthas : public CreatureScript { public: - boss_kaelthas() - : CreatureScript("boss_kaelthas") - { - } - //Kael'thas AI - struct boss_kaelthasAI : public ScriptedAI + boss_kaelthas() : CreatureScript("boss_kaelthas") { } + + struct boss_kaelthasAI : public BossAI { - boss_kaelthasAI(Creature* creature) : ScriptedAI(creature), summons(me) + boss_kaelthasAI(Creature* creature) : BossAI(creature, DATA_KAELTHAS) { Initialize(); - instance = creature->GetInstanceScript(); PhaseSubphase = 0; Phase_Timer = 0; } @@ -320,8 +316,6 @@ class boss_kaelthas : public CreatureScript ChainPyros = false; } - InstanceScript* instance; - uint32 Fireball_Timer; uint32 ArcaneDisruption_Timer; uint32 Phoenix_Timer; @@ -341,8 +335,6 @@ class boss_kaelthas : public CreatureScript bool IsCastingFireball; bool ChainPyros; - SummonList summons; - ObjectGuid m_auiAdvisorGuid[MAX_ADVISORS]; void Reset() override @@ -351,8 +343,8 @@ class boss_kaelthas : public CreatureScript if (me->IsInCombat()) PrepareAdvisors(); - - summons.DespawnAll(); + + _Reset(); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); @@ -413,7 +405,6 @@ class boss_kaelthas : public CreatureScript } void MoveInLineOfSight(Unit* who) override - { if (!me->HasUnitState(UNIT_STATE_STUNNED) && me->CanCreatureAttack(who)) { @@ -444,6 +435,8 @@ class boss_kaelthas : public CreatureScript { if (!instance->GetData(DATA_KAELTHASEVENT) && !Phase) StartEvent(); + + instance->SetBossState(DATA_KAELTHAS, IN_PROGRESS); } void KilledUnit(Unit* /*victim*/) override @@ -463,11 +456,6 @@ class boss_kaelthas : public CreatureScript } } - void SummonedCreatureDespawn(Creature* summon) override - { - summons.Despawn(summon); - } - void JustDied(Unit* /*killer*/) override { me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); @@ -475,8 +463,6 @@ class boss_kaelthas : public CreatureScript Talk(SAY_DEATH); - summons.DespawnAll(); - instance->SetData(DATA_KAELTHASEVENT, 0); for (uint8 i = 0; i < MAX_ADVISORS; ++i) @@ -484,6 +470,7 @@ class boss_kaelthas : public CreatureScript if (Unit* pAdvisor = ObjectAccessor::GetUnit(*me, m_auiAdvisorGuid[i])) pAdvisor->Kill(pAdvisor); } + _JustDied(); } void UpdateAI(uint32 diff) override @@ -1024,10 +1011,8 @@ class boss_thaladred_the_darkener : public CreatureScript { public: - boss_thaladred_the_darkener() - : CreatureScript("boss_thaladred_the_darkener") - { - } + boss_thaladred_the_darkener() : CreatureScript("boss_thaladred_the_darkener") { } + struct boss_thaladred_the_darkenerAI : public advisorbase_ai { boss_thaladred_the_darkenerAI(Creature* creature) : advisorbase_ai(creature) @@ -1130,10 +1115,8 @@ class boss_lord_sanguinar : public CreatureScript { public: - boss_lord_sanguinar() - : CreatureScript("boss_lord_sanguinar") - { - } + boss_lord_sanguinar() : CreatureScript("boss_lord_sanguinar") { } + struct boss_lord_sanguinarAI : public advisorbase_ai { boss_lord_sanguinarAI(Creature* creature) : advisorbase_ai(creature) @@ -1205,10 +1188,8 @@ class boss_grand_astromancer_capernian : public CreatureScript { public: - boss_grand_astromancer_capernian() - : CreatureScript("boss_grand_astromancer_capernian") - { - } + boss_grand_astromancer_capernian() : CreatureScript("boss_grand_astromancer_capernian") { } + struct boss_grand_astromancer_capernianAI : public advisorbase_ai { boss_grand_astromancer_capernianAI(Creature* creature) : advisorbase_ai(creature) @@ -1358,10 +1339,8 @@ class boss_master_engineer_telonicus : public CreatureScript { public: - boss_master_engineer_telonicus() - : CreatureScript("boss_master_engineer_telonicus") - { - } + boss_master_engineer_telonicus() : CreatureScript("boss_master_engineer_telonicus") { } + struct boss_master_engineer_telonicusAI : public advisorbase_ai { boss_master_engineer_telonicusAI(Creature* creature) : advisorbase_ai(creature) @@ -1449,10 +1428,8 @@ class npc_kael_flamestrike : public CreatureScript { public: - npc_kael_flamestrike() - : CreatureScript("npc_kael_flamestrike") - { - } + npc_kael_flamestrike() : CreatureScript("npc_kael_flamestrike") { } + struct npc_kael_flamestrikeAI : public ScriptedAI { npc_kael_flamestrikeAI(Creature* creature) : ScriptedAI(creature) @@ -1482,7 +1459,6 @@ class npc_kael_flamestrike : public CreatureScript void MoveInLineOfSight(Unit* /*who*/) override { } - void EnterCombat(Unit* /*who*/) override { } void UpdateAI(uint32 diff) override @@ -1523,10 +1499,8 @@ class npc_phoenix_tk : public CreatureScript { public: - npc_phoenix_tk() - : CreatureScript("npc_phoenix_tk") - { - } + npc_phoenix_tk() : CreatureScript("npc_phoenix_tk") { } + struct npc_phoenix_tkAI : public ScriptedAI { npc_phoenix_tkAI(Creature* creature) : ScriptedAI(creature) @@ -1585,10 +1559,8 @@ class npc_phoenix_egg_tk : public CreatureScript { public: - npc_phoenix_egg_tk() - : CreatureScript("npc_phoenix_egg_tk") - { - } + npc_phoenix_egg_tk() : CreatureScript("npc_phoenix_egg_tk") { } + struct npc_phoenix_egg_tkAI : public ScriptedAI { npc_phoenix_egg_tkAI(Creature* creature) : ScriptedAI(creature) @@ -1611,7 +1583,6 @@ class npc_phoenix_egg_tk : public CreatureScript //ignore any void MoveInLineOfSight(Unit* /*who*/) override { } - void AttackStart(Unit* who) override { if (me->Attack(who, false)) diff --git a/src/server/scripts/Outland/TempestKeep/Eye/boss_void_reaver.cpp b/src/server/scripts/Outland/TempestKeep/Eye/boss_void_reaver.cpp index 9186b491fa4..1aa7d5298e5 100644 --- a/src/server/scripts/Outland/TempestKeep/Eye/boss_void_reaver.cpp +++ b/src/server/scripts/Outland/TempestKeep/Eye/boss_void_reaver.cpp @@ -47,17 +47,13 @@ class boss_void_reaver : public CreatureScript { public: - boss_void_reaver() - : CreatureScript("boss_void_reaver") - { - } + boss_void_reaver() : CreatureScript("boss_void_reaver") { } - struct boss_void_reaverAI : public ScriptedAI + struct boss_void_reaverAI : public BossAI { - boss_void_reaverAI(Creature* creature) : ScriptedAI(creature) + boss_void_reaverAI(Creature* creature) : BossAI(creature, DATA_VOID_REAVER) { Initialize(); - instance = creature->GetInstanceScript(); } void Initialize() @@ -70,8 +66,6 @@ class boss_void_reaver : public CreatureScript Enraged = false; } - InstanceScript* instance; - uint32 Pounding_Timer; uint32 ArcaneOrb_Timer; uint32 KnockAway_Timer; @@ -82,9 +76,7 @@ class boss_void_reaver : public CreatureScript void Reset() override { Initialize(); - - if (me->IsAlive()) - instance->SetData(DATA_VOIDREAVEREVENT, NOT_STARTED); + _Reset(); } void KilledUnit(Unit* /*victim*/) override @@ -96,15 +88,13 @@ class boss_void_reaver : public CreatureScript { Talk(SAY_DEATH); DoZoneInCombat(); - - instance->SetData(DATA_VOIDREAVEREVENT, DONE); + _JustDied(); } void EnterCombat(Unit* /*who*/) override { Talk(SAY_AGGRO); - - instance->SetData(DATA_VOIDREAVEREVENT, IN_PROGRESS); + _EnterCombat(); } void UpdateAI(uint32 diff) override diff --git a/src/server/scripts/Outland/TempestKeep/Eye/instance_the_eye.cpp b/src/server/scripts/Outland/TempestKeep/Eye/instance_the_eye.cpp index 38c9cdd487c..c421b9974ce 100644 --- a/src/server/scripts/Outland/TempestKeep/Eye/instance_the_eye.cpp +++ b/src/server/scripts/Outland/TempestKeep/Eye/instance_the_eye.cpp @@ -27,8 +27,6 @@ EndScriptData */ #include "InstanceScript.h" #include "the_eye.h" -#define MAX_ENCOUNTER 5 - /* The Eye encounters: 0 - Kael'thas event 1 - Al' ar event @@ -39,20 +37,16 @@ EndScriptData */ class instance_the_eye : public InstanceMapScript { public: - instance_the_eye() - : InstanceMapScript("instance_the_eye", 550) - { - } + instance_the_eye() : InstanceMapScript("instance_the_eye", 550) { } struct instance_the_eye_InstanceMapScript : public InstanceScript { instance_the_eye_InstanceMapScript(Map* map) : InstanceScript(map) { SetHeaders(DataHeader); - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + SetBossNumber(EncounterCount); KaelthasEventPhase = 0; - AlarEventPhase = 0; } ObjectGuid ThaladredTheDarkener; @@ -63,44 +57,34 @@ class instance_the_eye : public InstanceMapScript ObjectGuid Astromancer; ObjectGuid Alar; uint8 KaelthasEventPhase; - uint8 AlarEventPhase; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - - bool IsEncounterInProgress() const override - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - return true; - - return false; - } void OnCreatureCreate(Creature* creature) override { switch (creature->GetEntry()) { - case 20064: - ThaladredTheDarkener = creature->GetGUID(); - break; - case 20063: - MasterEngineerTelonicus = creature->GetGUID(); - break; - case 20062: - GrandAstromancerCapernian = creature->GetGUID(); - break; - case 20060: - LordSanguinar = creature->GetGUID(); - break; - case 19622: - Kaelthas = creature->GetGUID(); - break; - case 18805: - Astromancer = creature->GetGUID(); - break; - case 19514: - Alar = creature->GetGUID(); - break; + case NPC_SANGUINAR: + LordSanguinar = creature->GetGUID(); + break; + case NPC_CAPERNIAN: + GrandAstromancerCapernian = creature->GetGUID(); + break; + case NPC_TELONICUS: + MasterEngineerTelonicus = creature->GetGUID(); + break; + case NPC_THALADRED: + ThaladredTheDarkener = creature->GetGUID(); + break; + case NPC_KAELTHAS: + Kaelthas = creature->GetGUID(); + break; + case NPC_HIGH_ASTROMANCER_SOLARIAN: + Astromancer = creature->GetGUID(); + break; + case NPC_ALAR: + Alar = creature->GetGUID(); + break; + default: + break; } } @@ -113,7 +97,7 @@ class instance_the_eye : public InstanceMapScript case DATA_GRANDASTROMANCERCAPERNIAN: return GrandAstromancerCapernian; case DATA_MASTERENGINEERTELONICUS: return MasterEngineerTelonicus; case DATA_KAELTHAS: return Kaelthas; - case DATA_ASTROMANCER: return Astromancer; + case DATA_HIGH_ASTROMANCER_SOLARIAN: return Astromancer; case DATA_ALAR: return Alar; } return ObjectGuid::Empty; @@ -123,64 +107,23 @@ class instance_the_eye : public InstanceMapScript { switch (type) { - case DATA_ALAREVENT: - AlarEventPhase = data; - m_auiEncounter[0] = data; - break; - case DATA_HIGHASTROMANCERSOLARIANEVENT: - m_auiEncounter[1] = data; - break; - case DATA_VOIDREAVEREVENT: - m_auiEncounter[2] = data; - break; - case DATA_KAELTHASEVENT: - KaelthasEventPhase = data; - m_auiEncounter[3] = data; - break; + case DATA_KAELTHASEVENT: + KaelthasEventPhase = data; + break; + default: + break; } - if (data == DONE) - SaveToDB(); } uint32 GetData(uint32 type) const override { switch (type) { - case DATA_ALAREVENT: return AlarEventPhase; - case DATA_HIGHASTROMANCERSOLARIANEVENT: return m_auiEncounter[1]; - case DATA_VOIDREAVEREVENT: return m_auiEncounter[2]; - case DATA_KAELTHASEVENT: return KaelthasEventPhase; + case DATA_KAELTHASEVENT: + return KaelthasEventPhase; } return 0; } - - std::string GetSaveData() override - { - OUT_SAVE_INST_DATA; - - std::ostringstream stream; - stream << m_auiEncounter[0] << ' ' << m_auiEncounter[1] << ' ' << m_auiEncounter[2] << ' ' << m_auiEncounter[3]; - - OUT_SAVE_INST_DATA_COMPLETE; - return stream.str(); - } - - void Load(const char* in) override - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - OUT_LOAD_INST_DATA(in); - - std::istringstream stream(in); - stream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3]; - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) // Do not load an encounter as "In Progress" - reset it instead. - m_auiEncounter[i] = NOT_STARTED; - OUT_LOAD_INST_DATA_COMPLETE; - } }; InstanceScript* GetInstanceScript(InstanceMap* map) const override diff --git a/src/server/scripts/Outland/TempestKeep/Eye/the_eye.h b/src/server/scripts/Outland/TempestKeep/Eye/the_eye.h index 718f37861d9..c46fe408274 100644 --- a/src/server/scripts/Outland/TempestKeep/Eye/the_eye.h +++ b/src/server/scripts/Outland/TempestKeep/Eye/the_eye.h @@ -21,19 +21,33 @@ #define DataHeader "TE" +uint32 const EncounterCount = 4; + enum DataTypes { - DATA_ALAREVENT = 1, - DATA_ASTROMANCER = 2, - DATA_GRANDASTROMANCERCAPERNIAN = 3, - DATA_HIGHASTROMANCERSOLARIANEVENT = 4, - DATA_KAELTHAS = 5, + // Encounter States/Boss GUIDs + DATA_KAELTHAS = 0, + DATA_ALAR = 1, + DATA_HIGH_ASTROMANCER_SOLARIAN = 2, + DATA_VOID_REAVER = 3, + + DATA_ASTROMANCER = 4, + DATA_GRANDASTROMANCERCAPERNIAN = 5, DATA_KAELTHASEVENT = 6, DATA_LORDSANGUINAR = 7, DATA_MASTERENGINEERTELONICUS = 8, - DATA_THALADREDTHEDARKENER = 10, - DATA_VOIDREAVEREVENT = 11, - DATA_ALAR = 12 + DATA_THALADREDTHEDARKENER = 9 +}; + +enum CreatureIds +{ + NPC_SANGUINAR = 20060, + NPC_CAPERNIAN = 20062, + NPC_TELONICUS = 20063, + NPC_THALADRED = 20064, + NPC_KAELTHAS = 19622, + NPC_HIGH_ASTROMANCER_SOLARIAN = 18805, + NPC_ALAR = 19514 }; #endif diff --git a/src/server/scripts/Outland/zone_hellfire_peninsula.cpp b/src/server/scripts/Outland/zone_hellfire_peninsula.cpp index 471c776d54b..d1a31906d58 100644 --- a/src/server/scripts/Outland/zone_hellfire_peninsula.cpp +++ b/src/server/scripts/Outland/zone_hellfire_peninsula.cpp @@ -770,7 +770,8 @@ public: void Initialize() { circleRounds = 0; - point = 0; + point = 3; + wpreached = false; } void Reset() override @@ -778,9 +779,7 @@ public: events.Reset(); summons.DespawnAll(); - circleRounds = 0; - point = 3; - wpreached = false; + Initialize(); } void DoAction(int32 action) override diff --git a/src/server/scripts/Spells/spell_quest.cpp b/src/server/scripts/Spells/spell_quest.cpp index 0ec8bfc3a9c..60ff67d74c0 100644 --- a/src/server/scripts/Spells/spell_quest.cpp +++ b/src/server/scripts/Spells/spell_quest.cpp @@ -339,7 +339,7 @@ class spell_q11396_11399_scourging_crystal_controller : public SpellScriptLoader SpellScript* GetSpellScript() const override { return new spell_q11396_11399_scourging_crystal_controller_SpellScript(); - }; + } }; // 43882 Scourging Crystal Controller Dummy @@ -375,7 +375,7 @@ class spell_q11396_11399_scourging_crystal_controller_dummy : public SpellScript SpellScript* GetSpellScript() const override { return new spell_q11396_11399_scourging_crystal_controller_dummy_SpellScript(); - }; + } }; // http://www.wowhead.com/quest=11515 Blood for Blood @@ -856,7 +856,7 @@ class spell_symbol_of_life_dummy : public SpellScriptLoader SpellScript* GetSpellScript() const override { return new spell_symbol_of_life_dummy_SpellScript(); - }; + } }; // http://www.wowhead.com/quest=12659 Scalps! @@ -899,7 +899,7 @@ class spell_q12659_ahunaes_knife : public SpellScriptLoader SpellScript* GetSpellScript() const override { return new spell_q12659_ahunaes_knife_SpellScript(); - }; + } }; enum StoppingTheSpread @@ -945,7 +945,7 @@ class spell_q9874_liquid_fire : public SpellScriptLoader SpellScript* GetSpellScript() const override { return new spell_q9874_liquid_fire_SpellScript(); - }; + } }; enum SalvagingLifesStength @@ -989,7 +989,7 @@ class spell_q12805_lifeblood_dummy : public SpellScriptLoader SpellScript* GetSpellScript() const override { return new spell_q12805_lifeblood_dummy_SpellScript(); - }; + } }; /* diff --git a/src/server/shared/Cryptography/SHA1.h b/src/server/shared/Cryptography/SHA1.h index ebd9f721d4a..f59bdc25556 100644 --- a/src/server/shared/Cryptography/SHA1.h +++ b/src/server/shared/Cryptography/SHA1.h @@ -39,8 +39,8 @@ class SHA1Hash void Initialize(); void Finalize(); - uint8 *GetDigest(void) { return mDigest; }; - int GetLength(void) const { return SHA_DIGEST_LENGTH; }; + uint8 *GetDigest(void) { return mDigest; } + int GetLength(void) const { return SHA_DIGEST_LENGTH; } private: SHA_CTX mC; diff --git a/src/server/shared/Database/DatabaseLoader.cpp b/src/server/shared/Database/DatabaseLoader.cpp index 36ee4b12c83..a3e2083fff4 100644 --- a/src/server/shared/Database/DatabaseLoader.cpp +++ b/src/server/shared/Database/DatabaseLoader.cpp @@ -117,6 +117,9 @@ DatabaseLoader& DatabaseLoader::AddDatabase(DatabaseWorkerPool<T>& pool, std::st bool DatabaseLoader::Load() { + if (!_updateFlags) + TC_LOG_INFO("sql.updates", "Automatic database updates are disabled for all databases!"); + if (!OpenDatabases()) return false; diff --git a/src/server/shared/Debugging/WheatyExceptionReport.cpp b/src/server/shared/Debugging/WheatyExceptionReport.cpp index e50cf42e439..e9f888f280d 100644 --- a/src/server/shared/Debugging/WheatyExceptionReport.cpp +++ b/src/server/shared/Debugging/WheatyExceptionReport.cpp @@ -62,6 +62,8 @@ HANDLE WheatyExceptionReport::m_hProcess; SymbolPairs WheatyExceptionReport::symbols; std::stack<SymbolDetail> WheatyExceptionReport::symbolDetails; bool WheatyExceptionReport::stackOverflowException; +bool WheatyExceptionReport::alreadyCrashed; +std::mutex WheatyExceptionReport::alreadyCrashedLock; // Declare global instance of class WheatyExceptionReport g_WheatyExceptionReport; @@ -74,6 +76,7 @@ WheatyExceptionReport::WheatyExceptionReport() // Constructor m_previousFilter = SetUnhandledExceptionFilter(WheatyUnhandledExceptionFilter); m_hProcess = GetCurrentProcess(); stackOverflowException = false; + alreadyCrashed = false; if (!IsDebuggerPresent()) { _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE); @@ -99,6 +102,13 @@ WheatyExceptionReport::~WheatyExceptionReport() LONG WINAPI WheatyExceptionReport::WheatyUnhandledExceptionFilter( PEXCEPTION_POINTERS pExceptionInfo) { + std::unique_lock<std::mutex> guard(alreadyCrashedLock); + // Handle only 1 exception in the whole process lifetime + if (alreadyCrashed) + return EXCEPTION_EXECUTE_HANDLER; + + alreadyCrashed = true; + if (pExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_STACK_OVERFLOW) stackOverflowException = true; diff --git a/src/server/shared/Debugging/WheatyExceptionReport.h b/src/server/shared/Debugging/WheatyExceptionReport.h index 101b6187f2b..ef6334add16 100644 --- a/src/server/shared/Debugging/WheatyExceptionReport.h +++ b/src/server/shared/Debugging/WheatyExceptionReport.h @@ -194,6 +194,8 @@ class WheatyExceptionReport static SymbolPairs symbols; static std::stack<SymbolDetail> symbolDetails; static bool stackOverflowException; + static bool alreadyCrashed; + static std::mutex alreadyCrashedLock; static char* PushSymbolDetail(char* pszCurrBuffer); static char* PopSymbolDetail(char* pszCurrBuffer); diff --git a/src/server/shared/PrecompiledHeaders/sharedPCH.h b/src/server/shared/PrecompiledHeaders/sharedPCH.h index d0c15b17f0c..87af9f44eb7 100644 --- a/src/server/shared/PrecompiledHeaders/sharedPCH.h +++ b/src/server/shared/PrecompiledHeaders/sharedPCH.h @@ -6,3 +6,4 @@ #include "SQLOperation.h" #include "Errors.h" #include "TypeList.h" +#include "TaskScheduler.h" diff --git a/src/server/shared/Updater/DBUpdater.cpp b/src/server/shared/Updater/DBUpdater.cpp index e5c571e4517..fd91e94b78f 100644 --- a/src/server/shared/Updater/DBUpdater.cpp +++ b/src/server/shared/Updater/DBUpdater.cpp @@ -239,10 +239,10 @@ bool DBUpdater<T>::Update(DatabaseWorkerPool<T>& pool) [&](Path const& file) { DBUpdater<T>::ApplyFile(pool, file); }, [&](std::string const& query) -> QueryResult { return DBUpdater<T>::Retrieve(pool, query); }); - uint32 count; + UpdateResult result; try { - count = updateFetcher.Update( + result = updateFetcher.Update( sConfigMgr->GetBoolDefault("Updates.Redundancy", true), sConfigMgr->GetBoolDefault("Updates.AllowRehash", true), sConfigMgr->GetBoolDefault("Updates.ArchivedRedundancy", false), @@ -253,10 +253,13 @@ bool DBUpdater<T>::Update(DatabaseWorkerPool<T>& pool) return false; } - if (!count) - TC_LOG_INFO("sql.updates", ">> %s database is up-to-date!", DBUpdater<T>::GetTableName().c_str()); + std::string const info = Trinity::StringFormat("Containing " SZFMTD " new and " SZFMTD " archived updates.", + result.recent, result.archived); + + if (!result.updated) + TC_LOG_INFO("sql.updates", ">> %s database is up-to-date! %s", DBUpdater<T>::GetTableName().c_str(), info.c_str()); else - TC_LOG_INFO("sql.updates", ">> Applied %d %s.", count, count == 1 ? "query" : "queries"); + TC_LOG_INFO("sql.updates", ">> Applied " SZFMTD " %s. %s", result.updated, result.updated == 1 ? "query" : "queries", info.c_str()); return true; } @@ -349,8 +352,27 @@ void DBUpdater<T>::ApplyFile(DatabaseWorkerPool<T>& pool, std::string const& hos args.push_back("-h" + host); args.push_back("-u" + user); args.push_back("-p" + password); + + // Check if we want to connect through ip or socket (Unix only) +#ifdef _WIN32 + args.push_back("-P" + port_or_socket); +#else + + if (!std::isdigit(port_or_socket[0])) + { + // We can't check here if host == "." because is named localhost if socket option is enabled + args.push_back("-P0"); + args.push_back("--protocol=SOCKET"); + args.push_back("-S" + port_or_socket); + } + else + // generic case + args.push_back("-P" + port_or_socket); + +#endif + // Set the default charset to utf8 args.push_back("--default-character-set=utf8"); diff --git a/src/server/shared/Updater/DBUpdater.h b/src/server/shared/Updater/DBUpdater.h index 0caf8a438fb..a2b12bed235 100644 --- a/src/server/shared/Updater/DBUpdater.h +++ b/src/server/shared/Updater/DBUpdater.h @@ -41,6 +41,19 @@ enum BaseLocation LOCATION_DOWNLOAD }; +struct UpdateResult +{ + UpdateResult() + : updated(0), recent(0), archived(0) { } + + UpdateResult(size_t const updated_, size_t const recent_, size_t const archived_) + : updated(updated_), recent(recent_), archived(archived_) { } + + size_t updated; + size_t recent; + size_t archived; +}; + template <class T> class DBUpdater { diff --git a/src/server/shared/Updater/UpdateFetcher.cpp b/src/server/shared/Updater/UpdateFetcher.cpp index a4bdd193743..ec023928b99 100644 --- a/src/server/shared/Updater/UpdateFetcher.cpp +++ b/src/server/shared/Updater/UpdateFetcher.cpp @@ -154,17 +154,27 @@ UpdateFetcher::SQLUpdate UpdateFetcher::ReadSQLUpdate(boost::filesystem::path co return update; } -uint32 UpdateFetcher::Update(bool const redundancyChecks, bool const allowRehash, bool const archivedRedundancy, int32 const cleanDeadReferencesMaxCount) const +UpdateResult UpdateFetcher::Update(bool const redundancyChecks, bool const allowRehash, bool const archivedRedundancy, int32 const cleanDeadReferencesMaxCount) const { LocaleFileStorage const available = GetFileList(); AppliedFileStorage applied = ReceiveAppliedFiles(); + size_t countRecentUpdates = 0; + size_t countArchivedUpdates = 0; + + // Count updates + for (auto const& entry : applied) + if (entry.second.state == RELEASED) + ++countRecentUpdates; + else + ++countArchivedUpdates; + // Fill hash to name cache HashToFileNameStorage hashToName; for (auto entry : applied) hashToName.insert(std::make_pair(entry.second.hash, entry.first)); - uint32 importedUpdates = 0; + size_t importedUpdates = 0; for (auto const& availableQuery : available) { @@ -314,7 +324,7 @@ uint32 UpdateFetcher::Update(bool const redundancyChecks, bool const allowRehash } } - return importedUpdates; + return UpdateResult(importedUpdates, countRecentUpdates, countArchivedUpdates); } std::string UpdateFetcher::CalculateHash(SQLUpdate const& query) const @@ -329,7 +339,6 @@ std::string UpdateFetcher::CalculateHash(SQLUpdate const& query) const 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(); @@ -338,7 +347,7 @@ uint32 UpdateFetcher::Apply(Path const& path) const _applyFile(path); // Return time the query took to apply - return std::chrono::duration_cast<ms>(Time::now() - begin).count(); + return std::chrono::duration_cast<std::chrono::milliseconds>(Time::now() - begin).count(); } void UpdateFetcher::UpdateEntry(AppliedFileEntry const& entry, uint32 const speed) const diff --git a/src/server/shared/Updater/UpdateFetcher.h b/src/server/shared/Updater/UpdateFetcher.h index fa142547873..4ff8c93bc76 100644 --- a/src/server/shared/Updater/UpdateFetcher.h +++ b/src/server/shared/Updater/UpdateFetcher.h @@ -35,7 +35,7 @@ public: std::function<void(Path const& path)> const& applyFile, std::function<QueryResult(std::string const&)> const& retrieve); - uint32 Update(bool const redundancyChecks, bool const allowRehash, + UpdateResult Update(bool const redundancyChecks, bool const allowRehash, bool const archivedRedundancy, int32 const cleanDeadReferencesMaxCount) const; private: diff --git a/src/server/shared/Utilities/TaskScheduler.cpp b/src/server/shared/Utilities/TaskScheduler.cpp new file mode 100644 index 00000000000..04a4071d1f5 --- /dev/null +++ b/src/server/shared/Utilities/TaskScheduler.cpp @@ -0,0 +1,232 @@ +/* + * 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 "TaskScheduler.h" + +TaskScheduler& TaskScheduler::ClearValidator() +{ + _predicate = EmptyValidator; + return *this; +} + +TaskScheduler& TaskScheduler::Update(success_t const& callback) +{ + _now = clock_t::now(); + Dispatch(callback); + return *this; +} + +TaskScheduler& TaskScheduler::Update(size_t const milliseconds, success_t const& callback) +{ + return Update(std::chrono::milliseconds(milliseconds), callback); +} + +TaskScheduler& TaskScheduler::Async(std::function<void()> const& callable) +{ + _asyncHolder.push(callable); + return *this; +} + +TaskScheduler& TaskScheduler::CancelAll() +{ + /// Clear the task holder + _task_holder.Clear(); + _asyncHolder = AsyncHolder(); + return *this; +} + +TaskScheduler& TaskScheduler::CancelGroup(group_t const group) +{ + _task_holder.RemoveIf([group](TaskContainer const& task) -> bool + { + return task->IsInGroup(group); + }); + return *this; +} + +TaskScheduler& TaskScheduler::CancelGroupsOf(std::vector<group_t> const& groups) +{ + std::for_each(groups.begin(), groups.end(), + std::bind(&TaskScheduler::CancelGroup, this, std::placeholders::_1)); + + return *this; +} + +TaskScheduler& TaskScheduler::InsertTask(TaskContainer task) +{ + _task_holder.Push(std::move(task)); + return *this; +} + +void TaskScheduler::Dispatch(success_t const& callback) +{ + // If the validation failed abort the dispatching here. + if (!_predicate()) + return; + + // Process all asyncs + while (!_asyncHolder.empty()) + { + _asyncHolder.front()(); + _asyncHolder.pop(); + + // If the validation failed abort the dispatching here. + if (!_predicate()) + return; + } + + if (_task_holder.IsEmpty()) + return; + + while (!_task_holder.IsEmpty()) + { + if (_task_holder.First()->_end > _now) + break; + + // Perfect forward the context to the handler + // Use weak references to catch destruction before callbacks. + TaskContext context(_task_holder.Pop(), std::weak_ptr<TaskScheduler>(self_reference)); + + // Invoke the context + context.Invoke(); + + // If the validation failed abort the dispatching here. + if (!_predicate()) + return; + } + + // On finish call the final callback + callback(); +} + +void TaskScheduler::TaskQueue::Push(TaskContainer&& task) +{ + container.insert(task); +} + +auto TaskScheduler::TaskQueue::Pop() -> TaskContainer +{ + TaskContainer result = *container.begin(); + container.erase(container.begin()); + return result; +} + +auto TaskScheduler::TaskQueue::First() const -> TaskContainer const& +{ + return *container.begin(); +} + +void TaskScheduler::TaskQueue::Clear() +{ + container.clear(); +} + +void TaskScheduler::TaskQueue::RemoveIf(std::function<bool(TaskContainer const&)> const& filter) +{ + for (auto itr = container.begin(); itr != container.end();) + if (filter(*itr)) + itr = container.erase(itr); + else + ++itr; +} + +void TaskScheduler::TaskQueue::ModifyIf(std::function<bool(TaskContainer const&)> const& filter) +{ + std::vector<TaskContainer> cache; + for (auto itr = container.begin(); itr != container.end();) + if (filter(*itr)) + { + cache.push_back(*itr); + itr = container.erase(itr); + } + else + ++itr; + + container.insert(cache.begin(), cache.end()); +} + +bool TaskScheduler::TaskQueue::IsEmpty() const +{ + return container.empty(); +} + +TaskContext& TaskContext::Dispatch(std::function<TaskScheduler&(TaskScheduler&)> const& apply) +{ + if (auto const owner = _owner.lock()) + apply(*owner); + + return *this; +} + +bool TaskContext::IsExpired() const +{ + return _owner.expired(); +} + +bool TaskContext::IsInGroup(TaskScheduler::group_t const group) const +{ + return _task->IsInGroup(group); +} + +TaskContext& TaskContext::SetGroup(TaskScheduler::group_t const group) +{ + _task->_group = group; + return *this; +} + +TaskContext& TaskContext::ClearGroup() +{ + _task->_group = boost::none; + return *this; +} + +TaskScheduler::repeated_t TaskContext::GetRepeatCounter() const +{ + return _task->_repeated; +} + +TaskContext& TaskContext::Async(std::function<void()> const& callable) +{ + return Dispatch(std::bind(&TaskScheduler::Async, std::placeholders::_1, callable)); +} + +TaskContext& TaskContext::CancelAll() +{ + return Dispatch(std::mem_fn(&TaskScheduler::CancelAll)); +} + +TaskContext& TaskContext::CancelGroup(TaskScheduler::group_t const group) +{ + return Dispatch(std::bind(&TaskScheduler::CancelGroup, std::placeholders::_1, group)); +} + +TaskContext& TaskContext::CancelGroupsOf(std::vector<TaskScheduler::group_t> const& groups) +{ + return Dispatch(std::bind(&TaskScheduler::CancelGroupsOf, std::placeholders::_1, std::cref(groups))); +} + +void TaskContext::AssertOnConsumed() const +{ + // This was adapted to TC to prevent static analysis tools from complaining. + // If you encounter this assertion check if you repeat a TaskContext more then 1 time! + ASSERT(!(*_consumed) && "Bad task logic, task context was consumed already!"); +} + +void TaskContext::Invoke() +{ + _task->_task(*this); +} diff --git a/src/server/shared/Utilities/TaskScheduler.h b/src/server/shared/Utilities/TaskScheduler.h new file mode 100644 index 00000000000..d45835b5f17 --- /dev/null +++ b/src/server/shared/Utilities/TaskScheduler.h @@ -0,0 +1,661 @@ +/* + * 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 _TASK_SCHEDULER_H_ +#define _TASK_SCHEDULER_H_ + +#include <algorithm> +#include <chrono> +#include <vector> +#include <queue> +#include <memory> +#include <utility> +#include <set> + +#include <boost/optional.hpp> + +#include "Util.h" + +class TaskContext; + +/// The TaskScheduler class provides the ability to schedule std::function's in the near future. +/// Use TaskScheduler::Update to update the scheduler. +/// Popular methods are: +/// * Schedule (Schedules a std::function which will be executed in the near future). +/// * Schedules an asynchronous function which will be executed at the next update tick. +/// * Cancel, Delay & Reschedule (Methods to manipulate already scheduled tasks). +/// Tasks are organized in groups (uint), multiple tasks can have the same group id, +/// you can provide a group or not, but keep in mind that you can only manipulate specific tasks through its group id! +/// Tasks callbacks use the function signature void(TaskContext) where TaskContext provides +/// access to the function schedule plan which makes it possible to repeat the task +/// with the same duration or a new one. +/// It also provides access to the repeat counter which is useful for task that repeat itself often +/// but behave different every time (spoken event dialogs for example). +class TaskScheduler +{ + friend class TaskContext; + + // Time definitions (use steady clock) + typedef std::chrono::steady_clock clock_t; + typedef clock_t::time_point timepoint_t; + typedef clock_t::duration duration_t; + + // Task group type + typedef uint32 group_t; + // Task repeated type + typedef uint32 repeated_t; + // Task handle type + typedef std::function<void(TaskContext)> task_handler_t; + // Predicate type + typedef std::function<bool()> predicate_t; + // Success handle type + typedef std::function<void()> success_t; + + class Task + { + friend class TaskContext; + friend class TaskScheduler; + + timepoint_t _end; + duration_t _duration; + boost::optional<group_t> _group; + repeated_t _repeated; + task_handler_t _task; + + public: + // All Argument construct + Task(timepoint_t const& end, duration_t const& duration, boost::optional<group_t> const& group, + repeated_t const repeated, task_handler_t const& task) + : _end(end), _duration(duration), _group(group), _repeated(repeated), _task(task) { } + + // Minimal Argument construct + Task(timepoint_t const& end, duration_t const& duration, task_handler_t const& task) + : _end(end), _duration(duration), _group(boost::none), _repeated(0), _task(task) { } + + // Copy construct + Task(Task const&) = delete; + // Move construct + Task(Task&&) = delete; + // Copy Assign + Task& operator= (Task const&) = default; + // Move Assign + Task& operator= (Task&& right) = delete; + + // Order tasks by its end + inline bool operator< (Task const& other) const + { + return _end < other._end; + } + + inline bool operator> (Task const& other) const + { + return _end > other._end; + } + + // Compare tasks with its end + inline bool operator== (Task const& other) + { + return _end == other._end; + } + + // Returns true if the task is in the given group + inline bool IsInGroup(group_t const group) const + { + return _group == group; + } + }; + + typedef std::shared_ptr<Task> TaskContainer; + + /// Container which provides Task order, insert and reschedule operations. + struct Compare + { + bool operator() (TaskContainer const& left, TaskContainer const& right) + { + return (*left.get()) < (*right.get()); + }; + }; + + class TaskQueue + { + std::multiset<TaskContainer, Compare> container; + + public: + // Pushes the task in the container + void Push(TaskContainer&& task); + + /// Pops the task out of the container + TaskContainer Pop(); + + TaskContainer const& First() const; + + void Clear(); + + void RemoveIf(std::function<bool(TaskContainer const&)> const& filter); + + void ModifyIf(std::function<bool(TaskContainer const&)> const& filter); + + bool IsEmpty() const; + }; + + /// Contains a self reference to track if this object was deleted or not. + std::shared_ptr<TaskScheduler> self_reference; + + /// The current time point (now) + timepoint_t _now; + + /// The Task Queue which contains all task objects. + TaskQueue _task_holder; + + typedef std::queue<std::function<void()>> AsyncHolder; + + /// Contains all asynchronous tasks which will be invoked at + /// the next update tick. + AsyncHolder _asyncHolder; + + predicate_t _predicate; + + static bool EmptyValidator() + { + return true; + } + + static void EmptyCallback() + { + } + +public: + TaskScheduler() + : self_reference(this, [](TaskScheduler const*) { }), _now(clock_t::now()), _predicate(EmptyValidator) { } + + template<typename P> + TaskScheduler(P&& predicate) + : self_reference(this, [](TaskScheduler const*) { }), _now(clock_t::now()), _predicate(std::forward<P>(predicate)) { } + + TaskScheduler(TaskScheduler const&) = delete; + TaskScheduler(TaskScheduler&&) = delete; + TaskScheduler& operator= (TaskScheduler const&) = delete; + TaskScheduler& operator= (TaskScheduler&&) = delete; + + /// Sets a validator which is asked if tasks are allowed to be executed. + template<typename P> + TaskScheduler& SetValidator(P&& predicate) + { + _predicate = std::forward<P>(predicate); + return *this; + } + + /// Clears the validator which is asked if tasks are allowed to be executed. + TaskScheduler& ClearValidator(); + + /// Update the scheduler to the current time. + /// Calls the optional callback on successfully finish. + TaskScheduler& Update(success_t const& callback = EmptyCallback); + + /// Update the scheduler with a difftime in ms. + /// Calls the optional callback on successfully finish. + TaskScheduler& Update(size_t const milliseconds, success_t const& callback = EmptyCallback); + + /// Update the scheduler with a difftime. + /// Calls the optional callback on successfully finish. + template<class _Rep, class _Period> + TaskScheduler& Update(std::chrono::duration<_Rep, _Period> const& difftime, + success_t const& callback = EmptyCallback) + { + _now += difftime; + Dispatch(callback); + return *this; + } + + /// Schedule an callable function that is executed at the next update tick. + /// Its safe to modify the TaskScheduler from within the callable. + TaskScheduler& Async(std::function<void()> const& callable); + + /// Schedule an event with a fixed rate. + /// Never call this from within a task context! Use TaskContext::Schedule instead! + template<class _Rep, class _Period> + TaskScheduler& Schedule(std::chrono::duration<_Rep, _Period> const& time, + task_handler_t const& task) + { + return ScheduleAt(_now, time, task); + } + + /// Schedule an event with a fixed rate. + /// Never call this from within a task context! Use TaskContext::Schedule instead! + template<class _Rep, class _Period> + TaskScheduler& Schedule(std::chrono::duration<_Rep, _Period> const& time, + group_t const group, task_handler_t const& task) + { + return ScheduleAt(_now, time, group, task); + } + + /// Schedule an event with a randomized rate between min and max rate. + /// Never call this from within a task context! Use TaskContext::Schedule instead! + template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight> + TaskScheduler& Schedule(std::chrono::duration<_RepLeft, _PeriodLeft> const& min, + std::chrono::duration<_RepRight, _PeriodRight> const& max, task_handler_t const& task) + { + return Schedule(RandomDurationBetween(min, max), task); + } + + /// Schedule an event with a fixed rate. + /// Never call this from within a task context! Use TaskContext::Schedule instead! + template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight> + TaskScheduler& Schedule(std::chrono::duration<_RepLeft, _PeriodLeft> const& min, + std::chrono::duration<_RepRight, _PeriodRight> const& max, group_t const group, + task_handler_t const& task) + { + return Schedule(RandomDurationBetween(min, max), group, task); + } + + /// Cancels all tasks. + /// Never call this from within a task context! Use TaskContext::CancelAll instead! + TaskScheduler& CancelAll(); + + /// Cancel all tasks of a single group. + /// Never call this from within a task context! Use TaskContext::CancelGroup instead! + TaskScheduler& CancelGroup(group_t const group); + + /// Cancels all groups in the given std::vector. + /// Hint: Use std::initializer_list for this: "{1, 2, 3, 4}" + TaskScheduler& CancelGroupsOf(std::vector<group_t> const& groups); + + /// Delays all tasks with the given duration. + template<class _Rep, class _Period> + TaskScheduler& DelayAll(std::chrono::duration<_Rep, _Period> const& duration) + { + _task_holder.ModifyIf([&duration](TaskContainer const& task) -> bool + { + task->_end += duration; + return true; + }); + return *this; + } + + /// Delays all tasks with a random duration between min and max. + template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight> + TaskScheduler& DelayAll(std::chrono::duration<_RepLeft, _PeriodLeft> const& min, + std::chrono::duration<_RepRight, _PeriodRight> const& max) + { + return DelayAll(RandomDurationBetween(min, max)); + } + + /// Delays all tasks of a group with the given duration. + template<class _Rep, class _Period> + TaskScheduler& DelayGroup(group_t const group, std::chrono::duration<_Rep, _Period> const& duration) + { + _task_holder.ModifyIf([&duration, group](TaskContainer const& task) -> bool + { + if (task->IsInGroup(group)) + { + task->_end += duration; + return true; + } + else + return false; + }); + return *this; + } + + /// Delays all tasks of a group with a random duration between min and max. + template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight> + TaskScheduler& DelayGroup(group_t const group, + std::chrono::duration<_RepLeft, _PeriodLeft> const& min, + std::chrono::duration<_RepRight, _PeriodRight> const& max) + { + return DelayGroup(group, RandomDurationBetween(min, max)); + } + + /// Reschedule all tasks with a given duration. + template<class _Rep, class _Period> + TaskScheduler& RescheduleAll(std::chrono::duration<_Rep, _Period> const& duration) + { + auto const end = _now + duration; + _task_holder.ModifyIf([end](TaskContainer const& task) -> bool + { + task->_end = end; + return true; + }); + return *this; + } + + /// Reschedule all tasks with a random duration between min and max. + template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight> + TaskScheduler& RescheduleAll(std::chrono::duration<_RepLeft, _PeriodLeft> const& min, + std::chrono::duration<_RepRight, _PeriodRight> const& max) + { + return RescheduleAll(RandomDurationBetween(min, max)); + } + + /// Reschedule all tasks of a group with the given duration. + template<class _Rep, class _Period> + TaskScheduler& RescheduleGroup(group_t const group, std::chrono::duration<_Rep, _Period> const& duration) + { + auto const end = _now + duration; + _task_holder.ModifyIf([end, group](TaskContainer const& task) -> bool + { + if (task->IsInGroup(group)) + { + task->_end = end; + return true; + } + else + return false; + }); + return *this; + } + + /// Reschedule all tasks of a group with a random duration between min and max. + template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight> + TaskScheduler& RescheduleGroup(group_t const group, + std::chrono::duration<_RepLeft, _PeriodLeft> const& min, + std::chrono::duration<_RepRight, _PeriodRight> const& max) + { + return RescheduleGroup(group, RandomDurationBetween(min, max)); + } + +private: + /// Insert a new task to the enqueued tasks. + TaskScheduler& InsertTask(TaskContainer task); + + template<class _Rep, class _Period> + TaskScheduler& ScheduleAt(timepoint_t const& end, + std::chrono::duration<_Rep, _Period> const& time, task_handler_t const& task) + { + return InsertTask(TaskContainer(new Task(end + time, time, task))); + } + + /// Schedule an event with a fixed rate. + /// Never call this from within a task context! Use TaskContext::schedule instead! + template<class _Rep, class _Period> + TaskScheduler& ScheduleAt(timepoint_t const& end, + std::chrono::duration<_Rep, _Period> const& time, + group_t const group, task_handler_t const& task) + { + static repeated_t const DEFAULT_REPEATED = 0; + return InsertTask(TaskContainer(new Task(end + time, time, group, DEFAULT_REPEATED, task))); + } + + // Returns a random duration between min and max + template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight> + static std::chrono::milliseconds + RandomDurationBetween(std::chrono::duration<_RepLeft, _PeriodLeft> const& min, + std::chrono::duration<_RepRight, _PeriodRight> const& max) + { + auto const milli_min = std::chrono::duration_cast<std::chrono::milliseconds>(min); + auto const milli_max = std::chrono::duration_cast<std::chrono::milliseconds>(max); + + // TC specific: use SFMT URandom + return std::chrono::milliseconds(urand(milli_min.count(), milli_max.count())); + } + + /// Dispatch remaining tasks + void Dispatch(success_t const& callback); +}; + +class TaskContext +{ + friend class TaskScheduler; + + /// Associated task + TaskScheduler::TaskContainer _task; + + /// Owner + std::weak_ptr<TaskScheduler> _owner; + + /// Marks the task as consumed + std::shared_ptr<bool> _consumed; + + /// Dispatches an action safe on the TaskScheduler + TaskContext& Dispatch(std::function<TaskScheduler&(TaskScheduler&)> const& apply); + +public: + // Empty constructor + TaskContext() + : _task(), _owner(), _consumed(std::make_shared<bool>(true)) { } + + // Construct from task and owner + explicit TaskContext(TaskScheduler::TaskContainer&& task, std::weak_ptr<TaskScheduler>&& owner) + : _task(task), _owner(owner), _consumed(std::make_shared<bool>(false)) { } + + // Copy construct + TaskContext(TaskContext const& right) + : _task(right._task), _owner(right._owner), _consumed(right._consumed) { } + + // Move construct + TaskContext(TaskContext&& right) + : _task(std::move(right._task)), _owner(std::move(right._owner)), _consumed(std::move(right._consumed)) { } + + // Copy assign + TaskContext& operator= (TaskContext const& right) + { + _task = right._task; + _owner = right._owner; + _consumed = right._consumed; + return *this; + } + + // Move assign + TaskContext& operator= (TaskContext&& right) + { + _task = std::move(right._task); + _owner = std::move(right._owner); + _consumed = std::move(right._consumed); + return *this; + } + + /// Returns true if the owner was deallocated and this context has expired. + bool IsExpired() const; + + /// Returns true if the event is in the given group + bool IsInGroup(TaskScheduler::group_t const group) const; + + /// Sets the event in the given group + TaskContext& SetGroup(TaskScheduler::group_t const group); + + /// Removes the group from the event + TaskContext& ClearGroup(); + + /// Returns the repeat counter which increases every time the task is repeated. + TaskScheduler::repeated_t GetRepeatCounter() const; + + /// Repeats the event and sets a new duration. + /// std::chrono::seconds(5) for example. + /// This will consume the task context, its not possible to repeat the task again + /// from the same task context! + template<class _Rep, class _Period> + TaskContext& Repeat(std::chrono::duration<_Rep, _Period> const& duration) + { + AssertOnConsumed(); + + // Set new duration, in-context timing and increment repeat counter + _task->_duration = duration; + _task->_end += duration; + _task->_repeated += 1; + (*_consumed) = true; + return Dispatch(std::bind(&TaskScheduler::InsertTask, std::placeholders::_1, _task)); + } + + /// Repeats the event with the same duration. + /// This will consume the task context, its not possible to repeat the task again + /// from the same task context! + TaskContext& Repeat() + { + return Repeat(_task->_duration); + } + + /// Repeats the event and set a new duration that is randomized between min and max. + /// std::chrono::seconds(5) for example. + /// This will consume the task context, its not possible to repeat the task again + /// from the same task context! + template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight> + TaskContext& Repeat(std::chrono::duration<_RepLeft, _PeriodLeft> const& min, + std::chrono::duration<_RepRight, _PeriodRight> const& max) + { + return Repeat(TaskScheduler::RandomDurationBetween(min, max)); + } + + /// Schedule a callable function that is executed at the next update tick from within the context. + /// Its safe to modify the TaskScheduler from within the callable. + TaskContext& Async(std::function<void()> const& callable); + + /// Schedule an event with a fixed rate from within the context. + /// Its possible that the new event is executed immediately! + /// Use TaskScheduler::Async to create a task + /// which will be called at the next update tick. + template<class _Rep, class _Period> + TaskContext& Schedule(std::chrono::duration<_Rep, _Period> const& time, + TaskScheduler::task_handler_t const& task) + { + auto const end = _task->_end; + return Dispatch([end, time, task](TaskScheduler& scheduler) -> TaskScheduler& + { + return scheduler.ScheduleAt<_Rep, _Period>(end, time, task); + }); + } + + /// Schedule an event with a fixed rate from within the context. + /// Its possible that the new event is executed immediately! + /// Use TaskScheduler::Async to create a task + /// which will be called at the next update tick. + template<class _Rep, class _Period> + TaskContext& Schedule(std::chrono::duration<_Rep, _Period> const& time, + TaskScheduler::group_t const group, TaskScheduler::task_handler_t const& task) + { + auto const end = _task->_end; + return Dispatch([end, time, group, task](TaskScheduler& scheduler) -> TaskScheduler& + { + return scheduler.ScheduleAt<_Rep, _Period>(end, time, group, task); + }); + } + + /// Schedule an event with a randomized rate between min and max rate from within the context. + /// Its possible that the new event is executed immediately! + /// Use TaskScheduler::Async to create a task + /// which will be called at the next update tick. + template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight> + TaskContext& Schedule(std::chrono::duration<_RepLeft, _PeriodLeft> const& min, + std::chrono::duration<_RepRight, _PeriodRight> const& max, TaskScheduler::task_handler_t const& task) + { + return Schedule(TaskScheduler::RandomDurationBetween(min, max), task); + } + + /// Schedule an event with a randomized rate between min and max rate from within the context. + /// Its possible that the new event is executed immediately! + /// Use TaskScheduler::Async to create a task + /// which will be called at the next update tick. + template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight> + TaskContext& Schedule(std::chrono::duration<_RepLeft, _PeriodLeft> const& min, + std::chrono::duration<_RepRight, _PeriodRight> const& max, TaskScheduler::group_t const group, + TaskScheduler::task_handler_t const& task) + { + return Schedule(TaskScheduler::RandomDurationBetween(min, max), group, task); + } + + /// Cancels all tasks from within the context. + TaskContext& CancelAll(); + + /// Cancel all tasks of a single group from within the context. + TaskContext& CancelGroup(TaskScheduler::group_t const group); + + /// Cancels all groups in the given std::vector from within the context. + /// Hint: Use std::initializer_list for this: "{1, 2, 3, 4}" + TaskContext& CancelGroupsOf(std::vector<TaskScheduler::group_t> const& groups); + + /// Delays all tasks with the given duration from within the context. + template<class _Rep, class _Period> + TaskContext& DelayAll(std::chrono::duration<_Rep, _Period> const& duration) + { + return Dispatch(std::bind(&TaskScheduler::DelayAll<_Rep, _Period>, std::placeholders::_1, duration)); + } + + /// Delays all tasks with a random duration between min and max from within the context. + template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight> + TaskContext& DelayAll(std::chrono::duration<_RepLeft, _PeriodLeft> const& min, + std::chrono::duration<_RepRight, _PeriodRight> const& max) + { + return DelayAll(TaskScheduler::RandomDurationBetween(min, max)); + } + + /// Delays all tasks of a group with the given duration from within the context. + template<class _Rep, class _Period> + TaskContext& DelayGroup(TaskScheduler::group_t const group, std::chrono::duration<_Rep, _Period> const& duration) + { + return Dispatch(std::bind(&TaskScheduler::DelayGroup<_Rep, _Period>, std::placeholders::_1, group, duration)); + } + + /// Delays all tasks of a group with a random duration between min and max from within the context. + template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight> + TaskContext& DelayGroup(TaskScheduler::group_t const group, + std::chrono::duration<_RepLeft, _PeriodLeft> const& min, + std::chrono::duration<_RepRight, _PeriodRight> const& max) + { + return DelayGroup(group, TaskScheduler::RandomDurationBetween(min, max)); + } + + /// Reschedule all tasks with the given duration. + template<class _Rep, class _Period> + TaskContext& RescheduleAll(std::chrono::duration<_Rep, _Period> const& duration) + { + return Dispatch(std::bind(&TaskScheduler::RescheduleAll, std::placeholders::_1, duration)); + } + + /// Reschedule all tasks with a random duration between min and max. + template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight> + TaskContext& RescheduleAll(std::chrono::duration<_RepLeft, _PeriodLeft> const& min, + std::chrono::duration<_RepRight, _PeriodRight> const& max) + { + return RescheduleAll(TaskScheduler::RandomDurationBetween(min, max)); + } + + /// Reschedule all tasks of a group with the given duration. + template<class _Rep, class _Period> + TaskContext& RescheduleGroup(TaskScheduler::group_t const group, std::chrono::duration<_Rep, _Period> const& duration) + { + return Dispatch(std::bind(&TaskScheduler::RescheduleGroup<_Rep, _Period>, std::placeholders::_1, group, duration)); + } + + /// Reschedule all tasks of a group with a random duration between min and max. + template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight> + TaskContext& RescheduleGroup(TaskScheduler::group_t const group, + std::chrono::duration<_RepLeft, _PeriodLeft> const& min, + std::chrono::duration<_RepRight, _PeriodRight> const& max) + { + return RescheduleGroup(group, TaskScheduler::RandomDurationBetween(min, max)); + } + +private: + /// Asserts if the task was consumed already. + void AssertOnConsumed() const; + + /// Invokes the associated hook of the task. + void Invoke(); +}; + +/// Milliseconds shorthand typedef. +typedef std::chrono::milliseconds Milliseconds; + +/// Seconds shorthand typedef. +typedef std::chrono::seconds Seconds; + +/// Minutes shorthand typedef. +typedef std::chrono::minutes Minutes; + +/// Hours shorthand typedef. +typedef std::chrono::hours Hours; + +#endif /// _TASK_SCHEDULER_H_ diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist index 2758c8e39cd..447ef9a45a8 100644 --- a/src/server/worldserver/worldserver.conf.dist +++ b/src/server/worldserver/worldserver.conf.dist @@ -1021,7 +1021,7 @@ OffhandCheckAtSpellUnlearn = 1 # ClientCacheVersion # Description: Client cache version for client cache data reset. Use any value different # from DB and not recently been used to trigger client side cache reset. -# Default: 0 - (Use DB value from world DB db_version.cache_id field) +# Default: 0 - (Use DB value from world DB version.cache_id field) ClientCacheVersion = 0 diff --git a/src/tools/map_extractor/mpq_libmpq.cpp b/src/tools/map_extractor/mpq_libmpq.cpp index 3e12747e9c5..482e3a3abbd 100644 --- a/src/tools/map_extractor/mpq_libmpq.cpp +++ b/src/tools/map_extractor/mpq_libmpq.cpp @@ -71,7 +71,7 @@ MPQFile::MPQFile(const char* filename): uint32_t filenum; if(libmpq__file_number(mpq_a, filename, &filenum)) continue; libmpq__off_t transferred; - libmpq__file_unpacked_size(mpq_a, filenum, &size); + libmpq__file_size_unpacked(mpq_a, filenum, &size); // HACK: in patch.mpq some files don't want to open and give 1 for filesize if (size<=1) { diff --git a/src/tools/map_extractor/mpq_libmpq04.h b/src/tools/map_extractor/mpq_libmpq04.h index 470e7bd0c50..c6fe36a8221 100644 --- a/src/tools/map_extractor/mpq_libmpq04.h +++ b/src/tools/map_extractor/mpq_libmpq04.h @@ -43,7 +43,7 @@ public: uint32_t filenum; if(libmpq__file_number(mpq_a, "(listfile)", &filenum)) return; libmpq__off_t size, transferred; - libmpq__file_unpacked_size(mpq_a, filenum, &size); + libmpq__file_size_unpacked(mpq_a, filenum, &size); char *buffer = new char[size+1]; buffer[size] = '\0'; diff --git a/src/tools/vmap4_extractor/mpq_libmpq.cpp b/src/tools/vmap4_extractor/mpq_libmpq.cpp index 5e0effc1a77..f3eb3da96b6 100644 --- a/src/tools/vmap4_extractor/mpq_libmpq.cpp +++ b/src/tools/vmap4_extractor/mpq_libmpq.cpp @@ -71,7 +71,7 @@ MPQFile::MPQFile(const char* filename): uint32 filenum; if(libmpq__file_number(mpq_a, filename, &filenum)) continue; libmpq__off_t transferred; - libmpq__file_unpacked_size(mpq_a, filenum, &size); + libmpq__file_size_unpacked(mpq_a, filenum, &size); // HACK: in patch.mpq some files don't want to open and give 1 for filesize if (size<=1) { diff --git a/src/tools/vmap4_extractor/mpq_libmpq04.h b/src/tools/vmap4_extractor/mpq_libmpq04.h index bb842daf258..6196285627d 100644 --- a/src/tools/vmap4_extractor/mpq_libmpq04.h +++ b/src/tools/vmap4_extractor/mpq_libmpq04.h @@ -42,7 +42,7 @@ public: uint32_t filenum; if(libmpq__file_number(mpq_a, "(listfile)", &filenum)) return; libmpq__off_t size, transferred; - libmpq__file_unpacked_size(mpq_a, filenum, &size); + libmpq__file_size_unpacked(mpq_a, filenum, &size); char *buffer = new char[size + 1]; buffer[size] = '\0'; |
