diff options
Diffstat (limited to 'src')
333 files changed, 10843 insertions, 9047 deletions
diff --git a/src/server/authserver/Authentication/TOTP.cpp b/src/server/authserver/Authentication/TOTP.cpp new file mode 100644 index 00000000000..51a21822bc0 --- /dev/null +++ b/src/server/authserver/Authentication/TOTP.cpp @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2008-2013 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 "TOTP.h" +#include <cstring> + +int base32_decode(const char* encoded, char* result, int bufSize) +{ + // Base32 implementation + // Copyright 2010 Google Inc. + // Author: Markus Gutschke + // Licensed under the Apache License, Version 2.0 + int buffer = 0; + int bitsLeft = 0; + int count = 0; + for (const char *ptr = encoded; count < bufSize && *ptr; ++ptr) + { + char ch = *ptr; + if (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n' || ch == '-') + continue; + buffer <<= 5; + + // Deal with commonly mistyped characters + if (ch == '0') + ch = 'O'; + else if (ch == '1') + ch = 'L'; + else if (ch == '8') + ch = 'B'; + + // Look up one base32 digit + if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z')) + ch = (ch & 0x1F) - 1; + else if (ch >= '2' && ch <= '7') + ch -= '2' - 26; + else + return -1; + + buffer |= ch; + bitsLeft += 5; + if (bitsLeft >= 8) + { + result[count++] = buffer >> (bitsLeft - 8); + bitsLeft -= 8; + } + } + + if (count < bufSize) + result[count] = '\000'; + return count; +} + +#define HMAC_RES_SIZE 20 + +namespace TOTP +{ + unsigned int GenerateToken(const char* b32key) + { + size_t keySize = strlen(b32key); + int bufsize = (keySize + 7)/8*5; + char* encoded = new char[bufsize]; + memset(encoded, 0, bufsize); + unsigned int hmacResSize = HMAC_RES_SIZE; + unsigned char hmacRes[HMAC_RES_SIZE]; + unsigned long timestamp = time(NULL)/30; + unsigned char challenge[8]; + + for (int i = 8; i--;timestamp >>= 8) + challenge[i] = timestamp; + + base32_decode(b32key, encoded, bufsize); + HMAC(EVP_sha1(), encoded, bufsize, challenge, 8, hmacRes, &hmacResSize); + unsigned int offset = hmacRes[19] & 0xF; + unsigned int truncHash = (hmacRes[offset] << 24) | (hmacRes[offset+1] << 16 )| (hmacRes[offset+2] << 8) | (hmacRes[offset+3]); + truncHash &= 0x7FFFFFFF; + + delete[] encoded; + + return truncHash % 1000000; + } +} diff --git a/src/server/authserver/Authentication/TOTP.h b/src/server/authserver/Authentication/TOTP.h new file mode 100644 index 00000000000..3080e7c7787 --- /dev/null +++ b/src/server/authserver/Authentication/TOTP.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2008-2013 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 _TOTP_H +#define _TOPT_H + +#include "openssl/hmac.h" +#include "openssl/evp.h" + +namespace TOTP +{ + unsigned int GenerateToken(const char* b32key); +} + +#endif diff --git a/src/server/authserver/Main.cpp b/src/server/authserver/Main.cpp index 9a6cc89fdd4..b16e86a7f9f 100644 --- a/src/server/authserver/Main.cpp +++ b/src/server/authserver/Main.cpp @@ -298,7 +298,7 @@ bool StartDB() } // NOTE: While authserver is singlethreaded you should keep synch_threads == 1. Increasing it is just silly since only 1 will be used ever. - if (!LoginDatabase.Open(dbstring.c_str(), uint8(worker_threads), uint8(synch_threads))) + if (!LoginDatabase.Open(dbstring, uint8(worker_threads), uint8(synch_threads))) { TC_LOG_ERROR(LOG_FILTER_AUTHSERVER, "Cannot connect to database"); return false; diff --git a/src/server/authserver/Realms/RealmList.h b/src/server/authserver/Realms/RealmList.h index 68e6524c334..d59990135f2 100644 --- a/src/server/authserver/Realms/RealmList.h +++ b/src/server/authserver/Realms/RealmList.h @@ -66,7 +66,7 @@ public: void UpdateIfNeed(); - void AddRealm(Realm NewRealm) {m_realms[NewRealm.name] = NewRealm;} + void AddRealm(const Realm& NewRealm) { m_realms[NewRealm.name] = NewRealm; } RealmMap::const_iterator begin() const { return m_realms.begin(); } RealmMap::const_iterator end() const { return m_realms.end(); } diff --git a/src/server/authserver/Server/AuthSocket.cpp b/src/server/authserver/Server/AuthSocket.cpp index 6bfe918643c..1ab9ae6eb62 100644 --- a/src/server/authserver/Server/AuthSocket.cpp +++ b/src/server/authserver/Server/AuthSocket.cpp @@ -27,6 +27,7 @@ #include "RealmList.h" #include "AuthSocket.h" #include "AuthCodes.h" +#include "TOTP.h" #include "SHA1.h" #include "openssl/crypto.h" @@ -267,12 +268,12 @@ void AuthSocket::_SetVSFields(const std::string& rI) uint8 mDigest[SHA_DIGEST_LENGTH]; memset(mDigest, 0, SHA_DIGEST_LENGTH); if (I.GetNumBytes() <= SHA_DIGEST_LENGTH) - memcpy(mDigest, I.AsByteArray(), I.GetNumBytes()); + memcpy(mDigest, I.AsByteArray().get(), I.GetNumBytes()); std::reverse(mDigest, mDigest + SHA_DIGEST_LENGTH); SHA1Hash sha; - sha.UpdateData(s.AsByteArray(), s.GetNumBytes()); + sha.UpdateData(s.AsByteArray().get(), s.GetNumBytes()); sha.UpdateData(mDigest, SHA_DIGEST_LENGTH); sha.Finalize(); BigNumber x; @@ -386,7 +387,7 @@ bool AuthSocket::_HandleLogonChallenge() TC_LOG_DEBUG(LOG_FILTER_AUTHSERVER, "[AuthChallenge] Account '%s' is locked to IP - '%s'", _login.c_str(), fields[3].GetCString()); TC_LOG_DEBUG(LOG_FILTER_AUTHSERVER, "[AuthChallenge] Player address is '%s'", ip_address.c_str()); - if (strcmp(fields[4].GetCString(), ip_address.c_str())) + if (strcmp(fields[4].GetCString(), ip_address.c_str()) != 0) { TC_LOG_DEBUG(LOG_FILTER_AUTHSERVER, "[AuthChallenge] Account IP differs"); pkt << uint8(WOW_FAIL_LOCKED_ENFORCED); @@ -484,14 +485,20 @@ bool AuthSocket::_HandleLogonChallenge() pkt << uint8(WOW_FAIL_VERSION_INVALID); // B may be calculated < 32B so we force minimal length to 32B - pkt.append(B.AsByteArray(32), 32); // 32 bytes + pkt.append(B.AsByteArray(32).get(), 32); // 32 bytes pkt << uint8(1); - pkt.append(g.AsByteArray(), 1); + pkt.append(g.AsByteArray().get(), 1); pkt << uint8(32); - pkt.append(N.AsByteArray(32), 32); - pkt.append(s.AsByteArray(), s.GetNumBytes()); // 32 bytes - pkt.append(unk3.AsByteArray(16), 16); + pkt.append(N.AsByteArray(32).get(), 32); + pkt.append(s.AsByteArray().get(), s.GetNumBytes()); // 32 bytes + pkt.append(unk3.AsByteArray(16).get(), 16); uint8 securityFlags = 0; + + // Check if token is used + _tokenKey = fields[8].GetString(); + if (!_tokenKey.empty()) + securityFlags = 4; + pkt << uint8(securityFlags); // security flags (0x0...0x04) if (securityFlags & 0x01) // PIN input @@ -574,7 +581,7 @@ bool AuthSocket::_HandleLogonProof() uint8 t[32]; uint8 t1[16]; uint8 vK[40]; - memcpy(t, S.AsByteArray(32), 32); + memcpy(t, S.AsByteArray(32).get(), 32); for (int i = 0; i < 16; ++i) t1[i] = t[i * 2]; @@ -629,7 +636,7 @@ bool AuthSocket::_HandleLogonProof() M.SetBinary(sha.GetDigest(), 20); // Check if SRP6 results match (password is correct), else send an error - if (!memcmp(M.AsByteArray(), lp.M1, 20)) + if (!memcmp(M.AsByteArray().get(), lp.M1, 20)) { TC_LOG_DEBUG(LOG_FILTER_AUTHSERVER, "'%s:%d' User '%s' successfully authenticated", socket().getRemoteAddress().c_str(), socket().getRemotePort(), _login.c_str()); @@ -652,6 +659,25 @@ bool AuthSocket::_HandleLogonProof() sha.UpdateBigNumbers(&A, &M, &K, NULL); sha.Finalize(); + // Check auth token + if ((lp.securityFlags & 0x04) || !_tokenKey.empty()) + { + uint8 size; + socket().recv((char*)&size, 1); + char* token = new char[size + 1]; + token[size] = '\0'; + socket().recv(token, size); + unsigned int validToken = TOTP::GenerateToken(_tokenKey.c_str()); + unsigned int incomingToken = atoi(token); + delete[] token; + if (validToken != incomingToken) + { + char data[] = { AUTH_LOGON_PROOF, WOW_FAIL_UNKNOWN_ACCOUNT, 3, 0 }; + socket().send(data, sizeof(data)); + return false; + } + } + if (_expversion & POST_BC_EXP_FLAG) // 2.x and 3.x clients { sAuthLogonProof_S proof; @@ -800,7 +826,7 @@ bool AuthSocket::_HandleReconnectChallenge() pkt << uint8(AUTH_RECONNECT_CHALLENGE); pkt << uint8(0x00); _reconnectProof.SetRand(16 * 8); - pkt.append(_reconnectProof.AsByteArray(16), 16); // 16 bytes random + pkt.append(_reconnectProof.AsByteArray(16).get(), 16); // 16 bytes random pkt << uint64(0x00) << uint64(0x00); // 16 bytes zeros socket().send((char const*)pkt.contents(), pkt.size()); return true; @@ -904,12 +930,13 @@ bool AuthSocket::_HandleRealmList() size_t RealmListSize = 0; for (RealmList::RealmMap::const_iterator i = sRealmList->begin(); i != sRealmList->end(); ++i) { + const Realm &realm = i->second; // don't work with realms which not compatible with the client - bool okBuild = ((_expversion & POST_BC_EXP_FLAG) && i->second.gamebuild == _build) || ((_expversion & PRE_BC_EXP_FLAG) && !AuthHelper::IsPreBCAcceptedClientBuild(i->second.gamebuild)); + bool okBuild = ((_expversion & POST_BC_EXP_FLAG) && realm.gamebuild == _build) || ((_expversion & PRE_BC_EXP_FLAG) && !AuthHelper::IsPreBCAcceptedClientBuild(realm.gamebuild)); // No SQL injection. id of realm is controlled by the database. - uint32 flag = i->second.flag; - RealmBuildInfo const* buildInfo = AuthHelper::GetBuildInfo(i->second.gamebuild); + uint32 flag = realm.flag; + RealmBuildInfo const* buildInfo = AuthHelper::GetBuildInfo(realm.gamebuild); if (!okBuild) { if (!buildInfo) @@ -930,27 +957,27 @@ bool AuthSocket::_HandleRealmList() } // We don't need the port number from which client connects with but the realm's port - clientAddr.set_port_number(i->second.ExternalAddress.get_port_number()); + clientAddr.set_port_number(realm.ExternalAddress.get_port_number()); - uint8 lock = (i->second.allowedSecurityLevel > _accountSecurityLevel) ? 1 : 0; + uint8 lock = (realm.allowedSecurityLevel > _accountSecurityLevel) ? 1 : 0; uint8 AmountOfCharacters = 0; stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_NUM_CHARS_ON_REALM); - stmt->setUInt32(0, i->second.m_ID); + stmt->setUInt32(0, realm.m_ID); stmt->setUInt32(1, id); result = LoginDatabase.Query(stmt); if (result) AmountOfCharacters = (*result)[0].GetUInt8(); - pkt << i->second.icon; // realm type + pkt << realm.icon; // realm type if (_expversion & POST_BC_EXP_FLAG) // only 2.x and 3.x clients pkt << lock; // if 1, then realm locked pkt << uint8(flag); // RealmFlags pkt << name; - pkt << GetAddressString(GetAddressForClient(i->second, clientAddr)); - pkt << i->second.populationLevel; + pkt << GetAddressString(GetAddressForClient(realm, clientAddr)); + pkt << realm.populationLevel; pkt << AmountOfCharacters; - pkt << i->second.timezone; // realm category + pkt << realm.timezone; // realm category if (_expversion & POST_BC_EXP_FLAG) // 2.x and 3.x clients pkt << uint8(0x2C); // unk, may be realm number/id? else diff --git a/src/server/authserver/Server/AuthSocket.h b/src/server/authserver/Server/AuthSocket.h index 6c13f85a022..c6513eaa5bf 100644 --- a/src/server/authserver/Server/AuthSocket.h +++ b/src/server/authserver/Server/AuthSocket.h @@ -69,6 +69,7 @@ private: bool _authed; std::string _login; + std::string _tokenKey; // Since GetLocaleByName() is _NOT_ bijective, we have to store the locale as a string. Otherwise we can't differ // between enUS and enGB, which is important for the patch system diff --git a/src/server/authserver/Server/RealmSocket.cpp b/src/server/authserver/Server/RealmSocket.cpp index 6710a6a88ae..88d81132306 100644 --- a/src/server/authserver/Server/RealmSocket.cpp +++ b/src/server/authserver/Server/RealmSocket.cpp @@ -45,8 +45,7 @@ RealmSocket::~RealmSocket(void) // delete RealmSocketObject must never be called from our code. closing_ = true; - if (session_) - delete session_; + delete session_; peer().close(); } @@ -286,8 +285,7 @@ int RealmSocket::handle_input(ACE_HANDLE) void RealmSocket::set_session(Session* session) { - if (session_ != NULL) - delete session_; + delete session_; session_ = session; } diff --git a/src/server/collision/BoundingIntervalHierarchyWrapper.h b/src/server/collision/BoundingIntervalHierarchyWrapper.h index 305d57b0075..8696a759fa8 100644 --- a/src/server/collision/BoundingIntervalHierarchyWrapper.h +++ b/src/server/collision/BoundingIntervalHierarchyWrapper.h @@ -37,20 +37,22 @@ class BIHWrap MDLCallback(RayCallback& callback, const T* const* objects_array, uint32 objects_size ) : objects(objects_array), _callback(callback), objects_size(objects_size) {} - bool operator() (const G3D::Ray& ray, uint32 Idx, float& MaxDist, bool /*stopAtFirst*/) + /// Intersect ray + bool operator() (const G3D::Ray& ray, uint32 idx, float& maxDist, bool /*stopAtFirst*/) { - if (Idx >= objects_size) + if (idx >= objects_size) return false; - if (const T* obj = objects[Idx]) - return _callback(ray, *obj, MaxDist/*, stopAtFirst*/); + if (const T* obj = objects[idx]) + return _callback(ray, *obj, maxDist/*, stopAtFirst*/); return false; } - void operator() (const G3D::Vector3& p, uint32 Idx) + /// Intersect point + void operator() (const G3D::Vector3& p, uint32 idx) { - if (Idx >= objects_size) - return false; - if (const T* obj = objects[Idx]) + if (idx >= objects_size) + return; + if (const T* obj = objects[idx]) _callback(p, *obj); } }; diff --git a/src/server/collision/Maps/MapTree.cpp b/src/server/collision/Maps/MapTree.cpp index dc12bb68e0d..436f30eed10 100644 --- a/src/server/collision/Maps/MapTree.cpp +++ b/src/server/collision/Maps/MapTree.cpp @@ -156,6 +156,11 @@ namespace VMAP bool StaticMapTree::isInLineOfSight(const Vector3& pos1, const Vector3& pos2) const { float maxDist = (pos2 - pos1).magnitude(); + // return false if distance is over max float, in case of cheater teleporting to the end of the universe + if (maxDist == std::numeric_limits<float>::max() || + maxDist == std::numeric_limits<float>::infinity()) + return false; + // valid map coords should *never ever* produce float overflow, but this would produce NaNs too ASSERT(maxDist < std::numeric_limits<float>::max()); // prevent NaN values which can cause BIH intersection to enter infinite loop diff --git a/src/server/collision/Maps/TileAssembler.cpp b/src/server/collision/Maps/TileAssembler.cpp index 02300c0b34a..f3a8b749a35 100644 --- a/src/server/collision/Maps/TileAssembler.cpp +++ b/src/server/collision/Maps/TileAssembler.cpp @@ -98,7 +98,16 @@ namespace VMAP printf("Creating map tree for map %u...\n", map_iter->first); BIH pTree; - pTree.build(mapSpawns, BoundsTrait<ModelSpawn*>::getBounds); + + try + { + pTree.build(mapSpawns, BoundsTrait<ModelSpawn*>::getBounds); + } + catch (std::exception& e) + { + printf("Exception ""%s"" when calling pTree.build", e.what()); + return false; + } // ===> possibly move this code to StaticMapTree class std::map<uint32, uint32> modelNodeIdx; @@ -503,7 +512,8 @@ namespace VMAP return false; } - char ident[8]; + char ident[9]; + ident[8] = '\0'; int readOperation = 0; READ_OR_RETURN(&ident, 8); diff --git a/src/server/collision/Models/GameObjectModel.cpp b/src/server/collision/Models/GameObjectModel.cpp index 9db3d706fca..a3af175a977 100644 --- a/src/server/collision/Models/GameObjectModel.cpp +++ b/src/server/collision/Models/GameObjectModel.cpp @@ -119,7 +119,7 @@ bool GameObjectModel::initialize(const GameObject& go, const GameObjectDisplayIn //ID = 0; iPos = Vector3(go.GetPositionX(), go.GetPositionY(), go.GetPositionZ()); phasemask = go.GetPhaseMask(); - iScale = go.GetFloatValue(OBJECT_FIELD_SCALE_X); + iScale = go.GetObjectScale(); iInvScale = 1.f / iScale; G3D::Matrix3 iRotation = G3D::Matrix3::fromEulerAnglesZYX(go.GetOrientation(), 0, 0); diff --git a/src/server/game/AI/CreatureAI.cpp b/src/server/game/AI/CreatureAI.cpp index cbb79b47958..75a1488ed45 100644 --- a/src/server/game/AI/CreatureAI.cpp +++ b/src/server/game/AI/CreatureAI.cpp @@ -75,6 +75,8 @@ void CreatureAI::DoZoneInCombat(Creature* creature /*= NULL*/, float maxRangeToN } } + // Intended duplicated check, the code above this should select a victim + // If it can't find a suitable attack target then we should error out. if (!creature->HasReactState(REACT_PASSIVE) && !creature->GetVictim()) { TC_LOG_ERROR(LOG_FILTER_GENERAL, "DoZoneInCombat called for creature that has empty threat list (creature entry = %u)", creature->GetEntry()); diff --git a/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp b/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp index 8f46896f6e8..befd6b9d16e 100644 --- a/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp +++ b/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp @@ -311,7 +311,7 @@ void FollowerAI::StartFollow(Player* player, uint32 factionForFollower, const Qu Player* FollowerAI::GetLeaderForFollower() { - if (Player* player = Unit::GetPlayer(*me, m_uiLeaderGUID)) + if (Player* player = ObjectAccessor::GetPlayer(*me, m_uiLeaderGUID)) { if (player->IsAlive()) return player; diff --git a/src/server/game/AI/SmartScripts/SmartAI.cpp b/src/server/game/AI/SmartScripts/SmartAI.cpp index c5b5cd5dfef..a56d0f94f2d 100644 --- a/src/server/game/AI/SmartScripts/SmartAI.cpp +++ b/src/server/game/AI/SmartScripts/SmartAI.cpp @@ -312,7 +312,7 @@ void SmartAI::UpdatePath(const uint32 diff) mWPReached = false; } } - if (me->IsInCombat() || HasEscortState(SMART_ESCORT_PAUSED | SMART_ESCORT_RETURNING)) + if ((!me->HasReactState(REACT_PASSIVE) && me->IsInCombat()) || HasEscortState(SMART_ESCORT_PAUSED | SMART_ESCORT_RETURNING)) return; // handle next wp if (mWPReached)//reached WP @@ -343,7 +343,7 @@ void SmartAI::UpdateAI(uint32 diff) { if (me->FindNearestCreature(mFollowArrivedEntry, INTERACTION_DISTANCE, true)) { - if (Player* player = me->GetPlayer(*me, mFollowGuid)) + if (Player* player = ObjectAccessor::GetPlayer(*me, mFollowGuid)) { if (!mFollowCreditType) player->RewardPlayerAndGroupAtEvent(mFollowCredit, me); @@ -365,7 +365,9 @@ void SmartAI::UpdateAI(uint32 diff) return; } mFollowArrivedTimer = 1000; - } else mFollowArrivedTimer -= diff; + } + else + mFollowArrivedTimer -= diff; } if (!UpdateVictim()) @@ -697,6 +699,10 @@ void SmartAI::InitializeAI() void SmartAI::OnCharmed(bool apply) { GetScript()->ProcessEventsFor(SMART_EVENT_CHARMED, NULL, 0, 0, apply); + + if (!apply && !me->IsInEvadeMode() && me->GetUInt64Value(UNIT_FIELD_CHARMEDBY)) + if (Unit* charmer = ObjectAccessor::GetUnit(*me, me->GetUInt64Value(UNIT_FIELD_CHARMEDBY))) + AttackStart(charmer); } void SmartAI::DoAction(int32 param) diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp index b4e18b66a69..70dd9e9d1ee 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.cpp +++ b/src/server/game/AI/SmartScripts/SmartScript.cpp @@ -34,6 +34,7 @@ #include "SmartScript.h" #include "SpellMgr.h" #include "Vehicle.h" +#include "GameEventMgr.h" class TrinityStringTextBuilder { @@ -730,7 +731,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u me->AI()->EnterEvadeMode(); TC_LOG_DEBUG(LOG_FILTER_DATABASE_AI, "SmartScript::ProcessAction:: SMART_ACTION_EVADE: Creature %u EnterEvadeMode", me->GetGUIDLow()); - return; + break; } case SMART_ACTION_FLEE_FOR_ASSIST: { @@ -765,28 +766,6 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u player->GroupEventHappens(e.action.quest.quest, GetBaseObject()); break; } - case SMART_ACTION_CALL_CASTEDCREATUREORGO: - { - if (!GetBaseObject()) - break; - - ObjectList* targets = GetTargets(e, unit); - if (!targets) - break; - - for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) - { - if (IsPlayer((*itr))) - { - (*itr)->ToPlayer()->CastedCreatureOrGO(e.action.callCastedCreatureOrGO.creature, GetBaseObject()->GetGUID(), e.action.callCastedCreatureOrGO.spell); - TC_LOG_DEBUG(LOG_FILTER_DATABASE_AI, "SmartScript::ProcessAction: SMART_ACTION_CALL_CASTEDCREATUREORGO: Player %u, target %u, spell %u", - (*itr)->GetGUIDLow(), e.action.callCastedCreatureOrGO.creature, e.action.callCastedCreatureOrGO.spell); - } - } - - delete targets; - break; - } case SMART_ACTION_REMOVEAURASFROMSPELL: { ObjectList* targets = GetTargets(e, unit); @@ -875,7 +854,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u } case SMART_ACTION_CALL_KILLEDMONSTER: { - if (e.target.type == SMART_TARGET_NONE) // Loot recipient and his group members + if (e.target.type == SMART_TARGET_NONE || e.target.type == SMART_TARGET_SELF) // Loot recipient and his group members { if (!me) break; @@ -1361,15 +1340,18 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u if (!me) break; - ObjectList* targets = GetTargets(e, unit); if (e.GetTargetType() == SMART_TARGET_SELF) me->SetFacingTo(me->GetHomePosition().GetOrientation()); else if (e.GetTargetType() == SMART_TARGET_POSITION) me->SetFacingTo(e.target.o); - else if (targets && !targets->empty()) - me->SetFacingToObject(*targets->begin()); + else if (ObjectList* targets = GetTargets(e, unit)) + { + if (!targets->empty()) + me->SetFacingToObject(*targets->begin()); + + delete targets; + } - delete targets; break; } case SMART_ACTION_PLAYMOVIE: @@ -1465,8 +1447,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u if (!einfo) { TC_LOG_ERROR(LOG_FILTER_SQL, "SmartScript: SMART_ACTION_EQUIP uses non-existent equipment info id %u for creature %u", equipId, npc->GetEntry()); - delete targets; - return; + break; } npc->SetCurrentEquipmentId(equipId); @@ -1789,10 +1770,14 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u if (!targets) break; + bool foundTarget = false; + for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) { if (IsCreature((*itr))) { + foundTarget = true; + if (e.action.moveRandom.distance) (*itr)->ToCreature()->GetMotionMaster()->MoveRandom((float)e.action.moveRandom.distance); else @@ -1800,6 +1785,14 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u } } + if (!foundTarget && me && IsCreature(me)) + { + if (e.action.moveRandom.distance) + me->GetMotionMaster()->MoveRandom((float)e.action.moveRandom.distance); + else + me->GetMotionMaster()->MoveIdle(); + } + delete targets; break; } @@ -1900,11 +1893,13 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u break; for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + { if (Creature* creature = (*itr)->ToCreature()) { creature->GetMotionMaster()->Clear(); creature->GetMotionMaster()->MoveJump(e.target.x, e.target.y, e.target.z, (float)e.action.jump.speedxy, (float)e.action.jump.speedz); } + } /// @todo Resume path when reached jump location delete targets; @@ -1934,7 +1929,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u if (!storedTargets) { delete targets; - return; + break; } for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) @@ -1971,6 +1966,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u break; for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + { if (Player* player = (*itr)->ToPlayer()) { if (e.action.sendGossipMenu.gossipMenuId) @@ -1980,6 +1976,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u player->SEND_GOSSIP_MENU(e.action.sendGossipMenu.gossipNpcTextId, GetBaseObject()->GetGUID()); } + } delete targets; break; @@ -1991,15 +1988,26 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u break; for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + { if (IsCreature(*itr)) { if (e.GetTargetType() == SMART_TARGET_SELF) (*itr)->ToCreature()->SetHomePosition(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation()); else if (e.GetTargetType() == SMART_TARGET_POSITION) (*itr)->ToCreature()->SetHomePosition(e.target.x, e.target.y, e.target.z, e.target.o); + else if (e.GetTargetType() == SMART_TARGET_CREATURE_RANGE || e.GetTargetType() == SMART_TARGET_CREATURE_GUID || + e.GetTargetType() == SMART_TARGET_CREATURE_DISTANCE || e.GetTargetType() == SMART_TARGET_GAMEOBJECT_RANGE || + e.GetTargetType() == SMART_TARGET_GAMEOBJECT_GUID || e.GetTargetType() == SMART_TARGET_GAMEOBJECT_DISTANCE || + e.GetTargetType() == SMART_TARGET_CLOSEST_CREATURE || e.GetTargetType() == SMART_TARGET_CLOSEST_GAMEOBJECT || + e.GetTargetType() == SMART_TARGET_OWNER_OR_SUMMONER || e.GetTargetType() == SMART_TARGET_ACTION_INVOKER || + e.GetTargetType() == SMART_TARGET_CLOSEST_ENEMY || e.GetTargetType() == SMART_TARGET_CLOSEST_FRIENDLY) + { + (*itr)->ToCreature()->SetHomePosition((*itr)->GetPositionX(), (*itr)->GetPositionY(), (*itr)->GetPositionZ(), (*itr)->GetOrientation()); + } else - TC_LOG_ERROR(LOG_FILTER_SQL, "SmartScript: Action target for SMART_ACTION_SET_HOME_POS is not using SMART_TARGET_SELF or SMART_TARGET_POSITION, skipping"); + TC_LOG_ERROR(LOG_FILTER_SQL, "SmartScript: Action target for SMART_ACTION_SET_HOME_POS is invalid, skipping"); } + } delete targets; break; @@ -2116,6 +2124,28 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u delete targets; break; } + case SMART_ACTION_GAME_EVENT_STOP: + { + uint32 eventId = e.action.gameEventStop.id; + if (!sGameEventMgr->IsActiveEvent(eventId)) + { + TC_LOG_ERROR(LOG_FILTER_SQL, "SmartScript::ProcessAction: At case SMART_ACTION_GAME_EVENT_STOP, inactive event (id: %u)", eventId); + break; + } + sGameEventMgr->StopEvent(eventId, true); + break; + } + case SMART_ACTION_GAME_EVENT_START: + { + uint32 eventId = e.action.gameEventStart.id; + if (sGameEventMgr->IsActiveEvent(eventId)) + { + TC_LOG_ERROR(LOG_FILTER_SQL, "SmartScript::ProcessAction: At case SMART_ACTION_GAME_EVENT_START, already activated event (id: %u)", eventId); + break; + } + sGameEventMgr->StartEvent(eventId, true); + break; + } default: TC_LOG_ERROR(LOG_FILTER_SQL, "SmartScript::ProcessAction: Entry %d SourceType %u, Event %u, Unhandled Action type %u", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType()); break; @@ -2231,6 +2261,7 @@ SmartScriptHolder SmartScript::CreateEvent(SMART_EVENT e, uint32 event_flags, ui script.event.raw.param4 = event_param4; script.event.event_phase_mask = phaseMask; script.event.event_flags = event_flags; + script.event.event_chance = 100; script.action.type = action; script.action.raw.param1 = action_param1; @@ -2268,8 +2299,9 @@ ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /* l->push_back(baseObject); break; case SMART_TARGET_VICTIM: - if (me && me->GetVictim()) - l->push_back(me->GetVictim()); + if (me) + if (Unit* victim = me->GetVictim()) + l->push_back(victim); break; case SMART_TARGET_HOSTILE_SECOND_AGGRO: if (me) @@ -2291,7 +2323,6 @@ ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /* if (Unit* u = me->AI()->SelectTarget(SELECT_TARGET_RANDOM, 1)) l->push_back(u); break; - case SMART_TARGET_NONE: case SMART_TARGET_ACTION_INVOKER: if (scriptTrigger) l->push_back(scriptTrigger); @@ -2483,8 +2514,15 @@ ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /* case SMART_TARGET_OWNER_OR_SUMMONER: { if (me) - if (Unit* owner = ObjectAccessor::GetUnit(*me, me->GetCharmerOrOwnerGUID())) + { + uint64 charmerOrOwnerGuid = me->GetCharmerOrOwnerGUID(); + + if (!charmerOrOwnerGuid) + charmerOrOwnerGuid = me->GetCreatorGUID(); + + if (Unit* owner = ObjectAccessor::GetUnit(*me, charmerOrOwnerGuid)) l->push_back(owner); + } break; } case SMART_TARGET_THREAT_LIST: @@ -2515,6 +2553,7 @@ ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /* break; } case SMART_TARGET_POSITION: + case SMART_TARGET_NONE: default: break; } @@ -2619,10 +2658,20 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui } case SMART_EVENT_TARGET_CASTING: { - if (!me || !me->IsInCombat() || !me->GetVictim() || !me->GetVictim()->IsNonMeleeSpellCasted(false, false, true)) + if (!me || !me->IsInCombat()) return; - ProcessTimedAction(e, e.event.minMaxRepeat.repeatMin, e.event.minMaxRepeat.repeatMax, me->GetVictim()); + Unit* victim = me->GetVictim(); + + if (!victim || !victim->IsNonMeleeSpellCasted(false, false, true)) + return; + + if (e.event.targetCasting.spellId > 0) + if (Spell* currSpell = victim->GetCurrentSpell(CURRENT_GENERIC_SPELL)) + if (currSpell->m_spellInfo->Id != e.event.targetCasting.spellId) + return; + + ProcessTimedAction(e, e.event.targetCasting.repeatMin, e.event.targetCasting.repeatMax, me->GetVictim()); break; } case SMART_EVENT_FRIENDLY_HEALTH: @@ -2630,10 +2679,10 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui if (!me || !me->IsInCombat()) return; - Unit* target = DoSelectLowestHpFriendly((float)e.event.friendlyHealt.radius, e.event.friendlyHealt.hpDeficit); + Unit* target = DoSelectLowestHpFriendly((float)e.event.friendlyHealth.radius, e.event.friendlyHealth.hpDeficit); if (!target || !target->IsInCombat()) return; - ProcessTimedAction(e, e.event.friendlyHealt.repeatMin, e.event.friendlyHealt.repeatMax, target); + ProcessTimedAction(e, e.event.friendlyHealth.repeatMin, e.event.friendlyHealth.repeatMax, target); break; } case SMART_EVENT_FRIENDLY_IS_CC: @@ -2981,7 +3030,7 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui { uint32 healthPct = uint32((*itr)->ToUnit()->GetHealthPct()); - if (healthPct > e.event.friendlyHealtPct.maxHpPct || healthPct < e.event.friendlyHealtPct.minHpPct) + if (healthPct > e.event.friendlyHealthPct.maxHpPct || healthPct < e.event.friendlyHealthPct.minHpPct) continue; target = (*itr)->ToUnit(); @@ -2994,7 +3043,7 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui if (!target) return; - ProcessTimedAction(e, e.event.friendlyHealtPct.repeatMin, e.event.friendlyHealtPct.repeatMax, target); + ProcessTimedAction(e, e.event.friendlyHealthPct.repeatMin, e.event.friendlyHealthPct.repeatMax, target); break; } default: diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp index 095440266f3..361cf025647 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp @@ -28,6 +28,8 @@ #include "ScriptedCreature.h" #include "GameEventMgr.h" #include "CreatureTextMgr.h" +#include "SpellMgr.h" +#include "SpellInfo.h" #include "SmartScriptMgr.h" @@ -407,10 +409,10 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) } break; case SMART_EVENT_FRIENDLY_HEALTH: - if (!NotNULL(e, e.event.friendlyHealt.radius)) + if (!NotNULL(e, e.event.friendlyHealth.radius)) return false; - if (!IsMinMaxValid(e, e.event.friendlyHealt.repeatMin, e.event.friendlyHealt.repeatMax)) + if (!IsMinMaxValid(e, e.event.friendlyHealth.repeatMin, e.event.friendlyHealth.repeatMax)) return false; break; case SMART_EVENT_FRIENDLY_IS_CC: @@ -437,6 +439,15 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) return false; break; case SMART_EVENT_TARGET_CASTING: + if (e.event.targetCasting.spellId > 0 && !sSpellMgr->GetSpellInfo(e.event.targetCasting.spellId)) + { + sLog->outError(LOG_FILTER_SQL, "SmartAIMgr: Entry %d SourceType %u Event %u Action %u uses non-existent Spell entry %u, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.event.spellHit.spell); + return false; + } + + if (!IsMinMaxValid(e, e.event.targetCasting.repeatMin, e.event.targetCasting.repeatMax)) + return false; + break; case SMART_EVENT_PASSENGER_BOARDED: case SMART_EVENT_PASSENGER_REMOVED: if (!IsMinMaxValid(e, e.event.minMax.repeatMin, e.event.minMax.repeatMax)) @@ -546,10 +557,10 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) break; } case SMART_EVENT_FRIENDLY_HEALTH_PCT: - if (!IsMinMaxValid(e, e.event.friendlyHealtPct.repeatMin, e.event.friendlyHealtPct.repeatMax)) + if (!IsMinMaxValid(e, e.event.friendlyHealthPct.repeatMin, e.event.friendlyHealthPct.repeatMax)) return false; - if (e.event.friendlyHealtPct.maxHpPct > 100 || e.event.friendlyHealtPct.minHpPct > 100) + if (e.event.friendlyHealthPct.maxHpPct > 100 || e.event.friendlyHealthPct.minHpPct > 100) { TC_LOG_ERROR(LOG_FILTER_SQL, "SmartAIMgr: Entry %d SourceType %u Event %u Action %u has pct value above 100, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType()); return false; @@ -727,13 +738,6 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) return false; } break; - case SMART_ACTION_CALL_CASTEDCREATUREORGO: - if (!IsCreatureValid(e, e.action.callCastedCreatureOrGO.creature)) - return false; - - if (!IsSpellValid(e, e.action.callCastedCreatureOrGO.spell)) - return false; - break; case SMART_ACTION_REMOVEAURASFROMSPELL: if (e.action.removeAura.spell != 0 && !IsSpellValid(e, e.action.removeAura.spell)) return false; @@ -767,6 +771,26 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) case SMART_ACTION_SUMMON_CREATURE: if (!IsCreatureValid(e, e.action.summonCreature.creature)) return false; + + for (uint32 i = 0; i < sSpellMgr->GetSpellInfoStoreSize(); ++i) + { + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(i); + if (!spellInfo) + continue; + + for (uint32 j = 0; j < MAX_SPELL_EFFECTS; ++j) + { + if (spellInfo->Effects[j].Effect == SPELL_EFFECT_SUMMON) + { + uint32 creatureSummonEntry = spellInfo->Effects[j].MiscValue; + + if (e.action.summonCreature.creature == creatureSummonEntry) + TC_LOG_ERROR(LOG_FILTER_SQL, "SmartAIMgr: Entry %d SourceType %u Event %u Action %u creature summon: %u has already summon spell (SpellId: %u effect: %u)", + e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.summonCreature.creature, spellInfo->Id, j); + } + } + } + if (e.action.summonCreature.type < TEMPSUMMON_TIMED_OR_DEAD_DESPAWN || e.action.summonCreature.type > TEMPSUMMON_MANUAL_DESPAWN) { TC_LOG_ERROR(LOG_FILTER_SQL, "SmartAIMgr: Entry %d SourceType %u Event %u Action %u uses incorrect TempSummonType %u, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.summonCreature.type); @@ -776,6 +800,25 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) case SMART_ACTION_CALL_KILLEDMONSTER: if (!IsCreatureValid(e, e.action.killedMonster.creature)) return false; + + for (uint32 i = 0; i < sSpellMgr->GetSpellInfoStoreSize(); ++i) + { + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(i); + if (!spellInfo) + continue; + + for (uint32 j = 0; j < MAX_SPELL_EFFECTS; ++j) + { + if (spellInfo->Effects[j].Effect == SPELL_EFFECT_KILL_CREDIT || spellInfo->Effects[j].Effect == SPELL_EFFECT_KILL_CREDIT2) + { + uint32 killCredit = spellInfo->Effects[j].MiscValue; + + if (e.action.killedMonster.creature == killCredit) + TC_LOG_ERROR(LOG_FILTER_SQL, "SmartAIMgr: Entry %d SourceType %u Event %u Action %u Kill Credit: %u has already spell kill credit (SpellId: %u effect: %u)", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.killedMonster.creature, spellInfo->Id, j); + } + } + } + if (e.GetTargetType() == SMART_TARGET_POSITION) { TC_LOG_ERROR(LOG_FILTER_SQL, "SmartAIMgr: Entry %d SourceType %u Event %u Action %u uses incorrect TargetType %u, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.GetTargetType()); @@ -805,6 +848,25 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) case SMART_ACTION_SUMMON_GO: if (!IsGameObjectValid(e, e.action.summonGO.entry)) return false; + + for (uint32 i = 0; i < sSpellMgr->GetSpellInfoStoreSize(); ++i) + { + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(i); + if (!spellInfo) + continue; + + for (uint32 j = 0; j < MAX_SPELL_EFFECTS; ++j) + { + if (spellInfo->Effects[j].Effect == SPELL_EFFECT_SUMMON_OBJECT_WILD) + { + uint32 goSummonEntry = spellInfo->Effects[j].MiscValue; + + if (e.action.summonGO.entry == goSummonEntry) + TC_LOG_ERROR(LOG_FILTER_SQL, "SmartAIMgr: Entry %d SourceType %u Event %u Action %u gameobject summon: %u has already summon spell (SpellId: %u effect: %u)", + e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.summonGO.entry, spellInfo->Id, j); + } + } + } break; case SMART_ACTION_ADD_ITEM: case SMART_ACTION_REMOVE_ITEM: @@ -866,6 +928,44 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) return false; } break; + case SMART_ACTION_GAME_EVENT_STOP: + { + uint32 eventId = e.action.gameEventStop.id; + + GameEventMgr::GameEventDataMap const& events = sGameEventMgr->GetEventMap(); + if (eventId < 1 || eventId >= events.size()) + { + TC_LOG_ERROR(LOG_FILTER_SQL, "SmartAIMgr: Entry %u SourceType %u Event %u Action %u uses non-existent event, eventId %u, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.gameEventStop.id); + return false; + } + + GameEventData const& eventData = events[eventId]; + if (!eventData.isValid()) + { + TC_LOG_ERROR(LOG_FILTER_SQL, "SmartAIMgr: Entry %u SourceType %u Event %u Action %u uses non-existent event, eventId %u, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.gameEventStop.id); + return false; + } + break; + } + case SMART_ACTION_GAME_EVENT_START: + { + uint32 eventId = e.action.gameEventStart.id; + + GameEventMgr::GameEventDataMap const& events = sGameEventMgr->GetEventMap(); + if (eventId < 1 || eventId >= events.size()) + { + TC_LOG_ERROR(LOG_FILTER_SQL, "SmartAIMgr: Entry %u SourceType %u Event %u Action %u uses non-existent event, eventId %u, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.gameEventStart.id); + return false; + } + + GameEventData const& eventData = events[eventId]; + if (!eventData.isValid()) + { + TC_LOG_ERROR(LOG_FILTER_SQL, "SmartAIMgr: Entry %u SourceType %u Event %u Action %u uses non-existent event, eventId %u, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.gameEventStart.id); + return false; + } + break; + } case SMART_ACTION_FOLLOW: case SMART_ACTION_SET_ORIENTATION: case SMART_ACTION_STORE_TARGET_LIST: diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.h b/src/server/game/AI/SmartScripts/SmartScriptMgr.h index 81336d0e0ca..6f0dd31e11f 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.h +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.h @@ -95,7 +95,7 @@ enum SMART_EVENT SMART_EVENT_OOC_LOS = 10, // NoHostile, MaxRnage, CooldownMin, CooldownMax SMART_EVENT_RESPAWN = 11, // type, MapId, ZoneId SMART_EVENT_TARGET_HEALTH_PCT = 12, // HPMin%, HPMax%, RepeatMin, RepeatMax - SMART_EVENT_TARGET_CASTING = 13, // RepeatMin, RepeatMax + SMART_EVENT_TARGET_CASTING = 13, // RepeatMin, RepeatMax, spellid SMART_EVENT_FRIENDLY_HEALTH = 14, // HPDeficit, Radius, RepeatMin, RepeatMax SMART_EVENT_FRIENDLY_IS_CC = 15, // Radius, RepeatMin, RepeatMax SMART_EVENT_FRIENDLY_MISSING_BUFF = 16, // SpellId, Radius, RepeatMin, RepeatMax @@ -216,11 +216,18 @@ struct SmartEvent struct { + uint32 repeatMin; + uint32 repeatMax; + uint32 spellId; + } targetCasting; + + struct + { uint32 hpDeficit; uint32 radius; uint32 repeatMin; uint32 repeatMax; - } friendlyHealt; + } friendlyHealth; struct { @@ -369,7 +376,7 @@ struct SmartEvent uint32 maxHpPct; uint32 repeatMin; uint32 repeatMax; - } friendlyHealtPct; + } friendlyHealthPct; struct { @@ -418,7 +425,7 @@ enum SMART_ACTION SMART_ACTION_EVADE = 24, // No Params SMART_ACTION_FLEE_FOR_ASSIST = 25, // With Emote SMART_ACTION_CALL_GROUPEVENTHAPPENS = 26, // QuestID - SMART_ACTION_CALL_CASTEDCREATUREORGO = 27, // CreatureId, SpellId + // none = 27, SMART_ACTION_REMOVEAURASFROMSPELL = 28, // Spellid, 0 removes all auras SMART_ACTION_FOLLOW = 29, // Distance (0 = default), Angle (0 = default), EndCreatureEntry, credit, creditType (0monsterkill, 1event) SMART_ACTION_RANDOM_PHASE = 30, // PhaseId1, PhaseId2, PhaseId3... @@ -502,8 +509,10 @@ enum SMART_ACTION SMART_ACTION_SET_POWER = 108, // PowerType, newPower SMART_ACTION_ADD_POWER = 109, // PowerType, newPower SMART_ACTION_REMOVE_POWER = 110, // PowerType, newPower + SMART_ACTION_GAME_EVENT_STOP = 111, // GameEventId + SMART_ACTION_GAME_EVENT_START = 112, // GameEventId - SMART_ACTION_END = 111 + SMART_ACTION_END = 113 }; struct SmartAction @@ -628,12 +637,6 @@ struct SmartAction struct { - uint32 creature; - uint32 spell; - } callCastedCreatureOrGO; - - struct - { uint32 spell; } removeAura; @@ -957,6 +960,16 @@ struct SmartAction uint32 newPower; } power; + struct + { + uint32 id; + } gameEventStop; + + struct + { + uint32 id; + } gameEventStart; + //! Note for any new future actions //! All parameters must have type uint32 diff --git a/src/server/game/Accounts/AccountMgr.cpp b/src/server/game/Accounts/AccountMgr.cpp index a9f178685d9..819a3b85fe6 100644 --- a/src/server/game/Accounts/AccountMgr.cpp +++ b/src/server/game/Accounts/AccountMgr.cpp @@ -34,21 +34,24 @@ AccountMgr::~AccountMgr() ClearRBAC(); } -AccountOpResult AccountMgr::CreateAccount(std::string username, std::string password) +AccountOpResult AccountMgr::CreateAccount(std::string username, std::string password, std::string email = "") { if (utf8length(username) > MAX_ACCOUNT_STR) return AOR_NAME_TOO_LONG; // username's too long normalizeString(username); normalizeString(password); + normalizeString(email); if (GetId(username)) - return AOR_NAME_ALREDY_EXIST; // username does already exist + return AOR_NAME_ALREADY_EXIST; // username does already exist PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_ACCOUNT); stmt->setString(0, username); stmt->setString(1, CalculateShaPassHash(username, password)); + stmt->setString(2, email); + stmt->setString(3, email); LoginDatabase.DirectExecute(stmt); // Enforce saving, otherwise AddGroup can fail @@ -202,6 +205,52 @@ AccountOpResult AccountMgr::ChangePassword(uint32 accountId, std::string newPass return AOR_OK; } +AccountOpResult AccountMgr::ChangeEmail(uint32 accountId, std::string newEmail) +{ + std::string username; + + if (!GetName(accountId, username)) + return AOR_NAME_NOT_EXIST; // account doesn't exist + + if (utf8length(newEmail) > MAX_EMAIL_STR) + return AOR_EMAIL_TOO_LONG; + + normalizeString(username); + normalizeString(newEmail); + + PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_EMAIL); + + stmt->setString(0, newEmail); + stmt->setUInt32(1, accountId); + + LoginDatabase.Execute(stmt); + + return AOR_OK; +} + +AccountOpResult AccountMgr::ChangeRegEmail(uint32 accountId, std::string newEmail) +{ + std::string username; + + if (!GetName(accountId, username)) + return AOR_NAME_NOT_EXIST; // account doesn't exist + + if (utf8length(newEmail) > MAX_EMAIL_STR) + return AOR_EMAIL_TOO_LONG; + + normalizeString(username); + normalizeString(newEmail); + + PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_REG_EMAIL); + + stmt->setString(0, newEmail); + stmt->setUInt32(1, accountId); + + LoginDatabase.Execute(stmt); + + return AOR_OK; +} + uint32 AccountMgr::GetId(std::string const& username) { PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_GET_ACCOUNT_ID_BY_USERNAME); @@ -245,6 +294,21 @@ bool AccountMgr::GetName(uint32 accountId, std::string& name) return false; } +bool AccountMgr::GetEmail(uint32 accountId, std::string& email) +{ + PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_GET_EMAIL_BY_ID); + stmt->setUInt32(0, accountId); + PreparedQueryResult result = LoginDatabase.Query(stmt); + + if (result) + { + email = (*result)[0].GetString(); + return true; + } + + return false; +} + bool AccountMgr::CheckPassword(uint32 accountId, std::string password) { std::string username; @@ -263,6 +327,23 @@ bool AccountMgr::CheckPassword(uint32 accountId, std::string password) return (result) ? true : false; } +bool AccountMgr::CheckEmail(uint32 accountId, std::string newEmail) +{ + std::string oldEmail; + + // We simply return false for a non-existing email + if (!GetEmail(accountId, oldEmail)) + return false; + + normalizeString(oldEmail); + normalizeString(newEmail); + + if (strcmp(oldEmail.c_str(), newEmail.c_str()) == 0) + return true; + + return false; +} + uint32 AccountMgr::GetCharactersCount(uint32 accountId) { // check character count diff --git a/src/server/game/Accounts/AccountMgr.h b/src/server/game/Accounts/AccountMgr.h index 878ecde24f9..92c1e2292d0 100644 --- a/src/server/game/Accounts/AccountMgr.h +++ b/src/server/game/Accounts/AccountMgr.h @@ -27,12 +27,21 @@ enum AccountOpResult AOR_OK, AOR_NAME_TOO_LONG, AOR_PASS_TOO_LONG, - AOR_NAME_ALREDY_EXIST, + AOR_EMAIL_TOO_LONG, + AOR_NAME_ALREADY_EXIST, AOR_NAME_NOT_EXIST, AOR_DB_INTERNAL_ERROR }; +enum PasswordChangeSecurity +{ + PW_NONE, + PW_EMAIL, + PW_RBAC +}; + #define MAX_ACCOUNT_STR 16 +#define MAX_EMAIL_STR 64 typedef std::map<uint32, RBACPermission*> RBACPermissionsContainer; typedef std::map<uint32, RBACRole*> RBACRolesContainer; @@ -48,16 +57,20 @@ class AccountMgr ~AccountMgr(); public: - AccountOpResult CreateAccount(std::string username, std::string password); + AccountOpResult CreateAccount(std::string username, std::string password, std::string email); static AccountOpResult DeleteAccount(uint32 accountId); static AccountOpResult ChangeUsername(uint32 accountId, std::string newUsername, std::string newPassword); static AccountOpResult ChangePassword(uint32 accountId, std::string newPassword); + static AccountOpResult ChangeEmail(uint32 accountId, std::string newEmail); + static AccountOpResult ChangeRegEmail(uint32 accountId, std::string newEmail); static bool CheckPassword(uint32 accountId, std::string password); + static bool CheckEmail(uint32 accountId, std::string newEmail); static uint32 GetId(std::string const& username); static uint32 GetSecurity(uint32 accountId); static uint32 GetSecurity(uint32 accountId, int32 realmId); static bool GetName(uint32 accountId, std::string& name); + static bool GetEmail(uint32 accountId, std::string& email); static uint32 GetCharactersCount(uint32 accountId); static std::string CalculateShaPassHash(std::string const& name, std::string const& password); diff --git a/src/server/game/Accounts/RBAC.h b/src/server/game/Accounts/RBAC.h index 10f00c0a279..e751cba0fbf 100644 --- a/src/server/game/Accounts/RBAC.h +++ b/src/server/game/Accounts/RBAC.h @@ -1,450 +1,1033 @@ -/*
- * Copyright (C) 2008-2013 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/>.
- */
-
-/**
-* @file RBAC.h
-* @brief Role Based Access Control related classes definition
-*
-* This file contains all the classes and enums used to implement
-* Role Based Access Control
-*
-* RBAC Rules:
-* - Pemission: Defines an autorization to perform certain operation.
-* - Role: Set of permissions.
-* - Group: Set of roles.
-* - An Account can have multiple groups, roles and permissions.
-* - Account Groups can only be granted or revoked
-* - Account Roles and Permissions can be granted, denied or revoked
-* - Grant: Assignment of the object (role/permission) and allow it
-* - Deny: Assignment of the object (role/permission) and deny it
-* - Revoke: Removal of the object (role/permission) no matter if it was granted or denied
-* - Global Permissions are computed as:
-* Group Grants + Role Grants + User Grans - Role Grants - User Grants
-* - Groups, Roles and Permissions can be assigned by realm
-*/
-
-#ifndef _RBAC_H
-#define _RBAC_H
-
-#include "Define.h"
-#include <string>
-#include <bitset>
-#include <set>
-#include <map>
-
-enum RBACPermissions
-{
- RBAC_PERM_INSTANT_LOGOUT = 1,
- RBAC_PERM_SKIP_QUEUE = 2,
- RBAC_PERM_JOIN_NORMAL_BG = 3,
- RBAC_PERM_JOIN_RANDOM_BG = 4,
- RBAC_PERM_JOIN_ARENAS = 5,
- RBAC_PERM_JOIN_DUNGEON_FINDER = 6,
- RBAC_PERM_PLAYER_COMMANDS = 7,
- RBAC_PERM_MODERATOR_COMMANDS = 8,
- RBAC_PERM_GAMEMASTER_COMMANDS = 9,
- RBAC_PERM_ADMINISTRATOR_COMMANDS = 10,
- RBAC_PERM_LOG_GM_TRADE = 11,
- // Free = 12
- RBAC_PERM_SKIP_CHECK_INSTANCE_REQUIRED_BOSSES = 13,
- RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_TEAMMASK = 14,
- RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_CLASSMASK = 15,
- RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_RACEMASK = 16,
- RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_RESERVEDNAME = 17,
- RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_HEROIC_CHARACTER = 18,
- RBAC_PERM_SKIP_CHECK_CHAT_CHANNEL_REQ = 19,
- RBAC_PERM_SKIP_CHECK_DISABLE_MAP = 20,
- RBAC_PERM_SKIP_CHECK_MORE_TALENTS_THAN_ALLOWED = 21,
- RBAC_PERM_SKIP_CHECK_CHAT_SPAM = 22,
- RBAC_PERM_SKIP_CHECK_OVERSPEED_PING = 23,
- RBAC_PERM_TWO_SIDE_CHARACTER_CREATION = 24,
- RBAC_PERM_TWO_SIDE_INTERACTION_CHAT = 25,
- RBAC_PERM_TWO_SIDE_INTERACTION_CHANNEL = 26,
- RBAC_PERM_TWO_SIDE_INTERACTION_MAIL = 27,
- RBAC_PERM_TWO_SIDE_WHO_LIST = 28,
- RBAC_PERM_TWO_SIDE_ADD_FRIEND = 29,
- RBAC_PERM_COMMANDS_SAVE_WITHOUT_DELAY = 30,
- RBAC_PERM_COMMANDS_USE_UNSTUCK_WITH_ARGS = 31,
- RBAC_PERM_COMMANDS_BE_ASSIGNED_TICKET = 32,
- RBAC_PERM_COMMANDS_NOTIFY_COMMAND_NOT_FOUND_ERROR = 33,
- RBAC_PERM_COMMANDS_APPEAR_IN_GM_LIST = 34,
- RBAC_PERM_WHO_SEE_ALL_SEC_LEVELS = 35,
- RBAC_PERM_CAN_FILTER_WHISPERS = 36,
- RBAC_PERM_CHAT_USE_STAFF_BADGE = 37,
- RBAC_PERM_RESURRECT_WITH_FULL_HPS = 38,
- RBAC_PERM_RESTORE_SAVED_GM_STATE = 39,
- RBAC_PERM_ALLOW_GM_FRIEND = 40,
- RBAC_PERM_USE_START_GM_LEVEL = 41,
- RBAC_PERM_OPCODE_WORLD_TELEPORT = 42,
- RBAC_PERM_OPCODE_WHOIS = 43,
- RBAC_PERM_RECEIVE_GLOBAL_GM_TEXTMESSAGE = 44,
- RBAC_PERM_SILENTLY_JOIN_CHANNEL = 45,
- RBAC_PERM_CHANGE_CHANNEL_NOT_MODERATOR = 46,
- RBAC_PERM_CHECK_FOR_LOWER_SECURITY = 47,
- RBAC_PERM_COMMANDS_PINFO_CHECK_PERSONAL_DATA = 48,
- RBAC_PERM_MAX
-};
-
-enum RBACCommandResult
-{
- RBAC_OK,
- RBAC_CANT_ADD_ALREADY_ADDED,
- RBAC_CANT_REVOKE_NOT_IN_LIST,
- RBAC_IN_GRANTED_LIST,
- RBAC_IN_DENIED_LIST,
- RBAC_ID_DOES_NOT_EXISTS
-};
-
-typedef std::bitset<RBAC_PERM_MAX> RBACPermissionContainer;
-typedef std::set<uint32> RBACRoleContainer;
-typedef std::set<uint32> RBACGroupContainer;
-
-class RBACObject
-{
- public:
- RBACObject(uint32 id = 0, std::string const& name = ""):
- _id(id), _name(name) { }
-
- virtual ~RBACObject() { }
-
- /// Gets the Name of the Object
- std::string const& GetName() const { return _name; }
- /// Gets the Id of the Object
- uint32 GetId() const { return _id; }
-
- private:
- uint32 _id; ///> id of the object
- std::string _name; ///> name of the object
-};
-
-/// Permission: Defines an autorization to perform certain operation
-class RBACPermission: public RBACObject
-{
- public:
- RBACPermission(uint32 id = 0, std::string const& name = ""):
- RBACObject(id, name) { }
-};
-
-/// Set of Permissions
-class RBACRole: public RBACObject
-{
- public:
- RBACRole(uint32 id = 0, std::string const& name = ""):
- RBACObject(id, name) { }
-
- /// Gets the Permissions assigned to this role
- RBACPermissionContainer const& GetPermissions() const { return _perms; }
- /// Grants a Permission (Adds)
- void GrantPermission(uint32 id);
- /// Revokes a Permission (Removes)
- void RevokePermission(uint32 id);
-
- private:
- RBACPermissionContainer _perms; ///> Set of permissions
-};
-
-/// Set of Roles
-class RBACGroup: public RBACObject
-{
- public:
- RBACGroup(uint32 id = 0, std::string const& name = ""):
- RBACObject(id, name) { }
-
- /// Gets the Roles assigned to this group
- RBACRoleContainer const& GetRoles() const { return _roles; }
- /// Grants a Role (Adds)
- void GrantRole(uint32 role);
- /// Revokes a Role (Removes)
- void RevokeRole(uint32 role);
-
- private:
- RBACRoleContainer _roles; ///> Set of Roles
-};
-
-/**
- * @name RBACData
- * @brief Contains all needed information about the acccount
- *
- * This class contains all the data needed to calculate the account permissions.
- * RBACDAta is formed by group permissions and user permissions through:
- * - Granted Groups, which contains roles, which contains permissions: Set of granted permissions
- * - Granted Roles, which contains permissions: Set of granted permissions
- * - Denied Roles, which contains permissions: Set of denied permissions
- * - Granted Permissions
- * - Denied Permissions
- *
- * Calculation of current Permissions: Granted permissions - Denied permissions
- * - Granted permissions: through groups, through roles and directly assigned
- * - Denied permissions: through roles and directly assigned
- */
-class RBACData: public RBACObject
-{
- public:
- RBACData(uint32 id, std::string const& name, int32 realmId):
- RBACObject(id, name), _realmId(realmId) { }
-
- /**
- * @name HasPermission
- * @brief Checks if certain action is allowed
- *
- * Checks if certain action can be performed.
- *
- * @return grant or deny action
- *
- * Example Usage:
- * @code
- * bool Player::CanJoinArena(Battleground* bg)
- * {
- * return bg->isArena() && HasPermission(RBAC_PERM_JOIN_ARENA);
- * }
- * @endcode
- */
- bool HasPermission(uint32 permission) const { return _globalPerms.test(permission); }
-
- // Functions enabled to be used by command system
- /// Returns all the granted permissions (after computation)
- RBACPermissionContainer const& GetPermissions() const { return _globalPerms; }
- /// Returns all the granted permissions
- RBACPermissionContainer const& GetGrantedPermissions() const { return _grantedPerms; }
- /// Returns all the denied permissions
- RBACPermissionContainer const& GetDeniedPermissions() const { return _deniedPerms; }
- /// Returns all the granted roles
- RBACRoleContainer const& GetGrantedRoles() const { return _grantedRoles; }
- /// Returns all the denied roles
- RBACRoleContainer const& GetDeniedRoles() const { return _deniedRoles; }
- /// Returns all the granted groups
- RBACGroupContainer const& GetGroups() const { return _groups; }
-
- /**
- * @name AddGroup
- * @brief Adds new group
- *
- * Add a new group to the account. If realm is 0 or the group can not be added
- * No save to db action will be performed.
- *
- * Fails if group Id does not exists or group already present
- *
- * @param groupId group to be added
- * @param realmId realm affected
- *
- * @return Success or failure (with reason) to add the group
- *
- * Example Usage:
- * @code
- * // previously defined "RBACData* rbac" with proper initialization
- * uint32 groupId = 2;
- * if (rbac->AddGroup(groupId) == RBAC_OK)
- * TC_LOG_DEBUG(LOG_FILTER_PLAYER, "Group %u succesfully added", groupId);
- * @endcode
- */
- RBACCommandResult AddGroup(uint32 groupId, int32 realmId = 0);
-
- /**
- * @name RemoveGroup
- * @brief Removes a group
- *
- * Removes a group from the account. If realm is 0 or the group can not be removed
- * No save to db action will be performed. Any delete operation will always affect
- * "all realms (-1)" in addition to the realm specified
- *
- * Fails if group not present
- *
- * @param groupId group to be removed
- * @param realmId realm affected
- *
- * @return Success or failure (with reason) to remove the group
- *
- * Example Usage:
- * // previously defined "RBACData* rbac" with proper initialization
- * uint32 groupId = 2;
- * if (rbac->RemoveGroup(groupId) == RBAC_OK)
- * TC_LOG_DEBUG(LOG_FILTER_PLAYER, "Group %u succesfully removed", groupId);
- * @endcode
- */
- RBACCommandResult RemoveGroup(uint32 groupId, int32 realmId = 0);
-
- /**
- * @name GrantRole
- * @brief Grants a role
- *
- * Grants a role to the account. If realm is 0 or the role can not be added
- * No save to db action will be performed.
- *
- * Fails if role Id does not exists or role already granted or denied
- *
- * @param roleId role to be granted
- * @param realmId realm affected
- *
- * @return Success or failure (with reason) to grant the role
- *
- * Example Usage:
- * // previously defined "RBACData* rbac" with proper initialization
- * uint32 roleId = 2;
- * if (rbac->GrantRole(roleId) == RBAC_IN_DENIED_LIST)
- * TC_LOG_DEBUG(LOG_FILTER_PLAYER, "Failed to grant role %u, already denied", roleId);
- * @endcode
- */
- RBACCommandResult GrantRole(uint32 roleId, int32 realmId = 0);
-
- /**
- * @name DenyRole
- * @brief Denies a role
- *
- * Denied a role to the account. If realm is 0 or the role can not be added
- * No save to db action will be performed.
- *
- * Fails if role Id does not exists or role already granted or denied
- *
- * @param roleId role to be denied
- * @param realmId realm affected
- *
- * @return Success or failure (with reason) to deny the role
- *
- * Example Usage:
- * // previously defined "RBACData* rbac" with proper initialization
- * uint32 roleId = 2;
- * if (rbac->DenyRole(roleId) == RBAC_ID_DOES_NOT_EXISTS)
- * TC_LOG_DEBUG(LOG_FILTER_PLAYER, "Role Id %u does not exists", roleId);
- * @endcode
- */
- RBACCommandResult DenyRole(uint32 roleId, int32 realmId = 0);
-
- /**
- * @name RevokeRole
- * @brief Removes a role
- *
- * Removes a role from the account. If realm is 0 or the role can not be removed
- * No save to db action will be performed. Any delete operation will always affect
- * "all realms (-1)" in addition to the realm specified
- *
- * Fails if role not present
- *
- * @param roleId role to be removed
- * @param realmId realm affected
- *
- * @return Success or failure (with reason) to remove the role
- *
- * Example Usage:
- * // previously defined "RBACData* rbac" with proper initialization
- * uint32 roleId = 2;
- * if (rbac->RevokeRole(roleId) == RBAC_OK)
- * TC_LOG_DEBUG(LOG_FILTER_PLAYER, "Role %u succesfully removed", roleId);
- * @endcode
- */
- RBACCommandResult RevokeRole(uint32 roleId, int32 realmId = 0);
-
- /**
- * @name GrantRole
- * @brief Grants a permission
- *
- * Grants a permission to the account. If realm is 0 or the permission can not be added
- * No save to db action will be performed.
- *
- * Fails if permission Id does not exists or permission already granted or denied
- *
- * @param permissionId permission to be granted
- * @param realmId realm affected
- *
- * @return Success or failure (with reason) to grant the permission
- *
- * Example Usage:
- * // previously defined "RBACData* rbac" with proper initialization
- * uint32 permissionId = 2;
- * if (rbac->GrantRole(permissionId) == RBAC_IN_DENIED_LIST)
- * TC_LOG_DEBUG(LOG_FILTER_PLAYER, "Failed to grant permission %u, already denied", permissionId);
- * @endcode
- */
- RBACCommandResult GrantPermission(uint32 permissionId, int32 realmId = 0);
-
- /**
- * @name DenyPermission
- * @brief Denies a permission
- *
- * Denied a permission to the account. If realm is 0 or the permission can not be added
- * No save to db action will be performed.
- *
- * Fails if permission Id does not exists or permission already granted or denied
- *
- * @param permissionId permission to be denied
- * @param realmId realm affected
- *
- * @return Success or failure (with reason) to deny the permission
- *
- * Example Usage:
- * // previously defined "RBACData* rbac" with proper initialization
- * uint32 permissionId = 2;
- * if (rbac->DenyRole(permissionId) == RBAC_ID_DOES_NOT_EXISTS)
- * TC_LOG_DEBUG(LOG_FILTER_PLAYER, "Role Id %u does not exists", permissionId);
- * @endcode
- */
- RBACCommandResult DenyPermission(uint32 permissionId, int32 realmId = 0);
-
- /**
- * @name RevokePermission
- * @brief Removes a permission
- *
- * Removes a permission from the account. If realm is 0 or the permission can not be removed
- * No save to db action will be performed. Any delete operation will always affect
- * "all realms (-1)" in addition to the realm specified
- *
- * Fails if permission not present
- *
- * @param permissionId permission to be removed
- * @param realmId realm affected
- *
- * @return Success or failure (with reason) to remove the permission
- *
- * Example Usage:
- * // previously defined "RBACData* rbac" with proper initialization
- * uint32 permissionId = 2;
- * if (rbac->RevokeRole(permissionId) == RBAC_OK)
- * TC_LOG_DEBUG(LOG_FILTER_PLAYER, "Permission %u succesfully removed", permissionId);
- * @endcode
- */
- RBACCommandResult RevokePermission(uint32 permissionId, int32 realmId = 0);
-
- /// Loads all permissions, groups and roles assigned to current account
- void LoadFromDB();
- private:
- /// Saves a role to DB, Granted or Denied
- void SaveRole(uint32 role, bool granted, int32 realm);
- /// Saves a permission to DB, Granted or Denied
- void SavePermission(uint32 role, bool granted, int32 realm);
-
- /**
- * @name CalculateNewPermissions
- * @brief Calculates new permissions
- *
- * Calculates new permissions after some change in groups, roles or permissions.
- * The calculation is done Granted - Denied:
- * - Granted permissions: through groups, through roles and directly assigned
- * - Denied permissions: through roles and directly assigned
- */
- void CalculateNewPermissions();
-
- int32 GetRealmId() { return _realmId; }
-
- int32 _realmId; ///> RealmId Affected
- RBACGroupContainer _groups; ///> Granted groups
- RBACRoleContainer _grantedRoles; ///> Granted roles
- RBACRoleContainer _deniedRoles; ///> Denied roles
- RBACPermissionContainer _grantedPerms; ///> Granted permissions
- RBACPermissionContainer _deniedPerms; ///> Denied permissions
- RBACPermissionContainer _globalPerms; ///> Calculated permissions
-};
-
-#endif
+/* + * Copyright (C) 2008-2013 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/>. + */ + +/** +* @file RBAC.h +* @brief Role Based Access Control related classes definition +* +* This file contains all the classes and enums used to implement +* Role Based Access Control +* +* RBAC Rules: +* - Pemission: Defines an autorization to perform certain operation. +* - Role: Set of permissions. +* - Group: Set of roles. +* - An Account can have multiple groups, roles and permissions. +* - Account Groups can only be granted or revoked +* - Account Roles and Permissions can be granted, denied or revoked +* - Grant: Assignment of the object (role/permission) and allow it +* - Deny: Assignment of the object (role/permission) and deny it +* - Revoke: Removal of the object (role/permission) no matter if it was granted or denied +* - Global Permissions are computed as: +* Group Grants + Role Grants + User Grans - Role Grants - User Grants +* - Groups, Roles and Permissions can be assigned by realm +*/ + +#ifndef _RBAC_H +#define _RBAC_H + +#include "Define.h" +#include <string> +#include <bitset> +#include <set> +#include <map> + +enum RBACPermissions +{ + RBAC_PERM_INSTANT_LOGOUT = 1, + RBAC_PERM_SKIP_QUEUE = 2, + RBAC_PERM_JOIN_NORMAL_BG = 3, + RBAC_PERM_JOIN_RANDOM_BG = 4, + RBAC_PERM_JOIN_ARENAS = 5, + RBAC_PERM_JOIN_DUNGEON_FINDER = 6, + // 7 - reuse + // 8 - reuse + // 9 - reuse + // 10 - reuse + RBAC_PERM_LOG_GM_TRADE = 11, + // 12 - reuse + RBAC_PERM_SKIP_CHECK_INSTANCE_REQUIRED_BOSSES = 13, + RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_TEAMMASK = 14, + RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_CLASSMASK = 15, + RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_RACEMASK = 16, + RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_RESERVEDNAME = 17, + RBAC_PERM_SKIP_CHECK_CHARACTER_CREATION_HEROIC_CHARACTER = 18, + RBAC_PERM_SKIP_CHECK_CHAT_CHANNEL_REQ = 19, + RBAC_PERM_SKIP_CHECK_DISABLE_MAP = 20, + RBAC_PERM_SKIP_CHECK_MORE_TALENTS_THAN_ALLOWED = 21, + RBAC_PERM_SKIP_CHECK_CHAT_SPAM = 22, + RBAC_PERM_SKIP_CHECK_OVERSPEED_PING = 23, + RBAC_PERM_TWO_SIDE_CHARACTER_CREATION = 24, + RBAC_PERM_TWO_SIDE_INTERACTION_CHAT = 25, + RBAC_PERM_TWO_SIDE_INTERACTION_CHANNEL = 26, + RBAC_PERM_TWO_SIDE_INTERACTION_MAIL = 27, + RBAC_PERM_TWO_SIDE_WHO_LIST = 28, + RBAC_PERM_TWO_SIDE_ADD_FRIEND = 29, + RBAC_PERM_COMMANDS_SAVE_WITHOUT_DELAY = 30, + RBAC_PERM_COMMANDS_USE_UNSTUCK_WITH_ARGS = 31, + RBAC_PERM_COMMANDS_BE_ASSIGNED_TICKET = 32, + RBAC_PERM_COMMANDS_NOTIFY_COMMAND_NOT_FOUND_ERROR = 33, + RBAC_PERM_COMMANDS_APPEAR_IN_GM_LIST = 34, + RBAC_PERM_WHO_SEE_ALL_SEC_LEVELS = 35, + RBAC_PERM_CAN_FILTER_WHISPERS = 36, + RBAC_PERM_CHAT_USE_STAFF_BADGE = 37, + RBAC_PERM_RESURRECT_WITH_FULL_HPS = 38, + RBAC_PERM_RESTORE_SAVED_GM_STATE = 39, + RBAC_PERM_ALLOW_GM_FRIEND = 40, + RBAC_PERM_USE_START_GM_LEVEL = 41, + RBAC_PERM_OPCODE_WORLD_TELEPORT = 42, + RBAC_PERM_OPCODE_WHOIS = 43, + RBAC_PERM_RECEIVE_GLOBAL_GM_TEXTMESSAGE = 44, + RBAC_PERM_SILENTLY_JOIN_CHANNEL = 45, + RBAC_PERM_CHANGE_CHANNEL_NOT_MODERATOR = 46, + RBAC_PERM_CHECK_FOR_LOWER_SECURITY = 47, + RBAC_PERM_COMMANDS_PINFO_CHECK_PERSONAL_DATA = 48, + RBAC_PERM_EMAIL_CONFIRM_FOR_PASS_CHANGE = 49, + RBAC_PERM_MAY_CHECK_OWN_EMAIL = 50, + // Leave some space for core permissions + + RBAC_PERM_COMMAND_RBAC = 200, + RBAC_PERM_COMMAND_RBAC_ACC = 201, + RBAC_PERM_COMMAND_RBAC_ACC_GROUP = 202, + RBAC_PERM_COMMAND_RBAC_ACC_GROUP_ADD = 203, + RBAC_PERM_COMMAND_RBAC_ACC_GROUP_DEL = 204, + RBAC_PERM_COMMAND_RBAC_ACC_ROLE = 205, + RBAC_PERM_COMMAND_RBAC_ACC_ROLE_GRANT = 206, + RBAC_PERM_COMMAND_RBAC_ACC_ROLE_DENY = 207, + RBAC_PERM_COMMAND_RBAC_ACC_ROLE_REVOKE = 208, + RBAC_PERM_COMMAND_RBAC_ACC_PERM = 209, + RBAC_PERM_COMMAND_RBAC_ACC_PERM_GRANT = 210, + RBAC_PERM_COMMAND_RBAC_ACC_PERM_DENY = 211, + RBAC_PERM_COMMAND_RBAC_ACC_PERM_REVOKE = 212, + RBAC_PERM_COMMAND_RBAC_LIST = 213, + RBAC_PERM_COMMAND_RBAC_LIST_GROUPS = 214, + RBAC_PERM_COMMAND_RBAC_LIST_ROLES = 215, + RBAC_PERM_COMMAND_RBAC_LIST_PERMS = 216, + RBAC_PERM_COMMAND_ACCOUNT = 217, + RBAC_PERM_COMMAND_ACCOUNT_ADDON = 218, + RBAC_PERM_COMMAND_ACCOUNT_CREATE = 219, + RBAC_PERM_COMMAND_ACCOUNT_DELETE = 220, + RBAC_PERM_COMMAND_ACCOUNT_LOCK = 221, + RBAC_PERM_COMMAND_ACCOUNT_LOCK_COUNTRY = 222, + RBAC_PERM_COMMAND_ACCOUNT_LOCK_IP = 223, + RBAC_PERM_COMMAND_ACCOUNT_ONLINE_LIST = 224, + RBAC_PERM_COMMAND_ACCOUNT_PASSWORD = 225, + RBAC_PERM_COMMAND_ACCOUNT_SET = 226, + RBAC_PERM_COMMAND_ACCOUNT_SET_ADDON = 227, + RBAC_PERM_COMMAND_ACCOUNT_SET_GMLEVEL = 228, + RBAC_PERM_COMMAND_ACCOUNT_SET_PASSWORD = 229, + RBAC_PERM_COMMAND_ACHIEVEMENT = 230, + RBAC_PERM_COMMAND_ACHIEVEMENT_ADD = 231, + RBAC_PERM_COMMAND_ARENA = 232, + RBAC_PERM_COMMAND_ARENA_CAPTAIN = 233, + RBAC_PERM_COMMAND_ARENA_CREATE = 234, + RBAC_PERM_COMMAND_ARENA_DISBAND = 235, + RBAC_PERM_COMMAND_ARENA_INFO = 236, + RBAC_PERM_COMMAND_ARENA_LOOKUP = 237, + RBAC_PERM_COMMAND_ARENA_RENAME = 238, + RBAC_PERM_COMMAND_BAN = 239, + RBAC_PERM_COMMAND_BAN_ACCOUNT = 240, + RBAC_PERM_COMMAND_BAN_CHARACTER = 241, + RBAC_PERM_COMMAND_BAN_IP = 242, + RBAC_PERM_COMMAND_BAN_PLAYERACCOUNT = 243, + RBAC_PERM_COMMAND_BANINFO = 244, + RBAC_PERM_COMMAND_BANINFO_ACCOUNT = 245, + RBAC_PERM_COMMAND_BANINFO_CHARACTER = 246, + RBAC_PERM_COMMAND_BANINFO_IP = 247, + RBAC_PERM_COMMAND_BANLIST = 248, + RBAC_PERM_COMMAND_BANLIST_ACCOUNT = 249, + RBAC_PERM_COMMAND_BANLIST_CHARACTER = 250, + RBAC_PERM_COMMAND_BANLIST_IP = 251, + RBAC_PERM_COMMAND_UNBAN = 252, + RBAC_PERM_COMMAND_UNBAN_ACCOUNT = 253, + RBAC_PERM_COMMAND_UNBAN_CHARACTER = 254, + RBAC_PERM_COMMAND_UNBAN_IP = 255, + RBAC_PERM_COMMAND_UNBAN_PLAYERACCOUNT = 256, + RBAC_PERM_COMMAND_BF = 257, + RBAC_PERM_COMMAND_BF_START = 258, + RBAC_PERM_COMMAND_BF_STOP = 259, + RBAC_PERM_COMMAND_BF_SWITCH = 260, + RBAC_PERM_COMMAND_BF_TIMER = 261, + RBAC_PERM_COMMAND_BF_ENABLE = 262, + RBAC_PERM_COMMAND_ACCOUNT_EMAIL = 263, + RBAC_PERM_COMMAND_ACCOUNT_SET_SEC = 264, + RBAC_PERM_COMMAND_ACCOUNT_SET_SEC_EMAIL = 265, + RBAC_PERM_COMMAND_ACCOUNT_SET_SEC_REGMAIL = 266, + RBAC_PERM_COMMAND_CAST = 267, + RBAC_PERM_COMMAND_CAST_BACK = 268, + RBAC_PERM_COMMAND_CAST_DIST = 269, + RBAC_PERM_COMMAND_CAST_SELF = 270, + RBAC_PERM_COMMAND_CAST_TARGET = 271, + RBAC_PERM_COMMAND_CAST_DEST = 272, + RBAC_PERM_COMMAND_CHARACTER = 273, + RBAC_PERM_COMMAND_CHARACTER_CUSTOMIZE = 274, + RBAC_PERM_COMMAND_CHARACTER_CHANGEFACTION = 275, + RBAC_PERM_COMMAND_CHARACTER_CHANGERACE = 276, + RBAC_PERM_COMMAND_CHARACTER_DELETED = 277, + RBAC_PERM_COMMAND_CHARACTER_DELETED_DELETE = 278, + RBAC_PERM_COMMAND_CHARACTER_DELETED_LIST = 279, + RBAC_PERM_COMMAND_CHARACTER_DELETED_RESTORE = 280, + RBAC_PERM_COMMAND_CHARACTER_DELETED_OLD = 281, + RBAC_PERM_COMMAND_CHARACTER_ERASE = 282, + RBAC_PERM_COMMAND_CHARACTER_LEVEL = 283, + RBAC_PERM_COMMAND_CHARACTER_RENAME = 284, + RBAC_PERM_COMMAND_CHARACTER_REPUTATION = 285, + RBAC_PERM_COMMAND_CHARACTER_TITLES = 286, + RBAC_PERM_COMMAND_LEVELUP = 287, + RBAC_PERM_COMMAND_PDUMP = 288, + RBAC_PERM_COMMAND_PDUMP_LOAD = 289, + RBAC_PERM_COMMAND_PDUMP_WRITE = 290, + RBAC_PERM_COMMAND_CHEAT = 291, + RBAC_PERM_COMMAND_CHEAT_CASTTIME = 292, + RBAC_PERM_COMMAND_CHEAT_COOLDOWN = 293, + RBAC_PERM_COMMAND_CHEAT_EXPLORE = 294, + RBAC_PERM_COMMAND_CHEAT_GOD = 295, + RBAC_PERM_COMMAND_CHEAT_POWER = 296, + RBAC_PERM_COMMAND_CHEAT_STATUS = 297, + RBAC_PERM_COMMAND_CHEAT_TAXI = 298, + RBAC_PERM_COMMAND_CHEAT_WATERWALK = 299, + RBAC_PERM_COMMAND_DEBUG = 300, + RBAC_PERM_COMMAND_DEBUG_ANIM = 301, + RBAC_PERM_COMMAND_DEBUG_AREATRIGGERS = 302, + RBAC_PERM_COMMAND_DEBUG_ARENA = 303, + RBAC_PERM_COMMAND_DEBUG_BG = 304, + RBAC_PERM_COMMAND_DEBUG_ENTERVEHICLE = 305, + RBAC_PERM_COMMAND_DEBUG_GETITEMSTATE = 306, + RBAC_PERM_COMMAND_DEBUG_GETITEMVALUE = 307, + RBAC_PERM_COMMAND_DEBUG_GETVALUE = 308, + RBAC_PERM_COMMAND_DEBUG_HOSTIL = 309, + RBAC_PERM_COMMAND_DEBUG_ITEMEXPIRE = 310, + RBAC_PERM_COMMAND_DEBUG_LOOTRECIPIENT = 311, + RBAC_PERM_COMMAND_DEBUG_LOS = 312, + RBAC_PERM_COMMAND_DEBUG_MOD32VALUE = 313, + RBAC_PERM_COMMAND_DEBUG_MOVEFLAGS = 314, + RBAC_PERM_COMMAND_DEBUG_PLAY = 315, + RBAC_PERM_COMMAND_DEBUG_PLAY_CINEMATIC = 316, + RBAC_PERM_COMMAND_DEBUG_PLAY_MOVIE = 317, + RBAC_PERM_COMMAND_DEBUG_PLAY_SOUND = 318, + RBAC_PERM_COMMAND_DEBUG_SEND = 319, + RBAC_PERM_COMMAND_DEBUG_SEND_BUYERROR = 320, + RBAC_PERM_COMMAND_DEBUG_SEND_CHANNELNOTIFY = 321, + RBAC_PERM_COMMAND_DEBUG_SEND_CHATMESSAGE = 322, + RBAC_PERM_COMMAND_DEBUG_SEND_EQUIPERROR = 323, + RBAC_PERM_COMMAND_DEBUG_SEND_LARGEPACKET = 324, + RBAC_PERM_COMMAND_DEBUG_SEND_OPCODE = 325, + RBAC_PERM_COMMAND_DEBUG_SEND_QINVALIDMSG = 326, + RBAC_PERM_COMMAND_DEBUG_SEND_QPARTYMSG = 327, + RBAC_PERM_COMMAND_DEBUG_SEND_SELLERROR = 328, + RBAC_PERM_COMMAND_DEBUG_SEND_SETPHASESHIFT = 329, + RBAC_PERM_COMMAND_DEBUG_SEND_SPELLFAIL = 330, + RBAC_PERM_COMMAND_DEBUG_SETAURASTATE = 331, + RBAC_PERM_COMMAND_DEBUG_SETBIT = 332, + RBAC_PERM_COMMAND_DEBUG_SETITEMVALUE = 333, + RBAC_PERM_COMMAND_DEBUG_SETVALUE = 334, + RBAC_PERM_COMMAND_DEBUG_SETVID = 335, + RBAC_PERM_COMMAND_DEBUG_SPAWNVEHICLE = 336, + RBAC_PERM_COMMAND_DEBUG_THREAT = 337, + RBAC_PERM_COMMAND_DEBUG_UPDATE = 338, + RBAC_PERM_COMMAND_DEBUG_UWS = 339, + RBAC_PERM_COMMAND_WPGPS = 340, + RBAC_PERM_COMMAND_DESERTER = 341, + RBAC_PERM_COMMAND_DESERTER_BG = 342, + RBAC_PERM_COMMAND_DESERTER_BG_ADD = 343, + RBAC_PERM_COMMAND_DESERTER_BG_REMOVE = 344, + RBAC_PERM_COMMAND_DESERTER_INSTANCE = 345, + RBAC_PERM_COMMAND_DESERTER_INSTANCE_ADD = 346, + RBAC_PERM_COMMAND_DESERTER_INSTANCE_REMOVE = 347, + RBAC_PERM_COMMAND_DISABLE = 348, + RBAC_PERM_COMMAND_DISABLE_ADD = 349, + RBAC_PERM_COMMAND_DISABLE_ADD_ACHIEVEMENT_CRITERIA = 350, + RBAC_PERM_COMMAND_DISABLE_ADD_BATTLEGROUND = 351, + RBAC_PERM_COMMAND_DISABLE_ADD_MAP = 352, + RBAC_PERM_COMMAND_DISABLE_ADD_MMAP = 353, + RBAC_PERM_COMMAND_DISABLE_ADD_OUTDOORPVP = 354, + RBAC_PERM_COMMAND_DISABLE_ADD_QUEST = 355, + RBAC_PERM_COMMAND_DISABLE_ADD_SPELL = 356, + RBAC_PERM_COMMAND_DISABLE_ADD_VMAP = 357, + RBAC_PERM_COMMAND_DISABLE_REMOVE = 358, + RBAC_PERM_COMMAND_DISABLE_REMOVE_ACHIEVEMENT_CRITERIA = 359, + RBAC_PERM_COMMAND_DISABLE_REMOVE_BATTLEGROUND = 360, + RBAC_PERM_COMMAND_DISABLE_REMOVE_MAP = 361, + RBAC_PERM_COMMAND_DISABLE_REMOVE_MMAP = 362, + RBAC_PERM_COMMAND_DISABLE_REMOVE_OUTDOORPVP = 363, + RBAC_PERM_COMMAND_DISABLE_REMOVE_QUEST = 364, + RBAC_PERM_COMMAND_DISABLE_REMOVE_SPELL = 365, + RBAC_PERM_COMMAND_DISABLE_REMOVE_VMAP = 366, + RBAC_PERM_COMMAND_EVENT = 367, + RBAC_PERM_COMMAND_EVENT_ACTIVELIST = 368, + RBAC_PERM_COMMAND_EVENT_START = 369, + RBAC_PERM_COMMAND_EVENT_STOP = 370, + RBAC_PERM_COMMAND_GM = 371, + RBAC_PERM_COMMAND_GM_CHAT = 372, + RBAC_PERM_COMMAND_GM_FLY = 373, + RBAC_PERM_COMMAND_GM_INGAME = 374, + RBAC_PERM_COMMAND_GM_LIST = 375, + RBAC_PERM_COMMAND_GM_VISIBLE = 376, + RBAC_PERM_COMMAND_GO = 377, + RBAC_PERM_COMMAND_GO_CREATURE = 378, + RBAC_PERM_COMMAND_GO_GRAVEYARD = 379, + RBAC_PERM_COMMAND_GO_GRID = 380, + RBAC_PERM_COMMAND_GO_OBJECT = 381, + RBAC_PERM_COMMAND_GO_TAXINODE = 382, + RBAC_PERM_COMMAND_GO_TICKET = 383, + RBAC_PERM_COMMAND_GO_TRIGGER = 384, + RBAC_PERM_COMMAND_GO_XYZ = 385, + RBAC_PERM_COMMAND_GO_ZONEXY = 386, + RBAC_PERM_COMMAND_GOBJECT = 387, + RBAC_PERM_COMMAND_GOBJECT_ACTIVATE = 388, + RBAC_PERM_COMMAND_GOBJECT_ADD = 389, + RBAC_PERM_COMMAND_GOBJECT_ADD_TEMP = 390, + RBAC_PERM_COMMAND_GOBJECT_DELETE = 391, + RBAC_PERM_COMMAND_GOBJECT_INFO = 392, + RBAC_PERM_COMMAND_GOBJECT_MOVE = 393, + RBAC_PERM_COMMAND_GOBJECT_NEAR = 394, + RBAC_PERM_COMMAND_GOBJECT_SET = 395, + RBAC_PERM_COMMAND_GOBJECT_SET_PHASE = 396, + RBAC_PERM_COMMAND_GOBJECT_SET_STATE = 397, + RBAC_PERM_COMMAND_GOBJECT_TARGET = 398, + RBAC_PERM_COMMAND_GOBJECT_TURN = 399, + // 400 - reuse + RBAC_PERM_COMMAND_GUILD = 401, + RBAC_PERM_COMMAND_GUILD_CREATE = 402, + RBAC_PERM_COMMAND_GUILD_DELETE = 403, + RBAC_PERM_COMMAND_GUILD_INVITE = 404, + RBAC_PERM_COMMAND_GUILD_UNINVITE = 405, + RBAC_PERM_COMMAND_GUILD_RANK = 406, + RBAC_PERM_COMMAND_GUILD_RENAME = 407, + RBAC_PERM_COMMAND_HONOR = 408, + RBAC_PERM_COMMAND_HONOR_ADD = 409, + RBAC_PERM_COMMAND_HONOR_ADD_KILL = 410, + RBAC_PERM_COMMAND_HONOR_UPDATE = 411, + RBAC_PERM_COMMAND_INSTANCE = 412, + RBAC_PERM_COMMAND_INSTANCE_LISTBINDS = 413, + RBAC_PERM_COMMAND_INSTANCE_UNBIND = 414, + RBAC_PERM_COMMAND_INSTANCE_STATS = 415, + RBAC_PERM_COMMAND_INSTANCE_SAVEDATA = 416, + RBAC_PERM_COMMAND_LEARN = 417, + RBAC_PERM_COMMAND_LEARN_ALL = 418, + RBAC_PERM_COMMAND_LEARN_ALL_MY = 419, + RBAC_PERM_COMMAND_LEARN_ALL_MY_CLASS = 420, + RBAC_PERM_COMMAND_LEARN_ALL_MY_PETTALENTS = 421, + RBAC_PERM_COMMAND_LEARN_ALL_MY_SPELLS = 422, + RBAC_PERM_COMMAND_LEARN_ALL_MY_TALENTS = 423, + RBAC_PERM_COMMAND_LEARN_ALL_GM = 424, + RBAC_PERM_COMMAND_LEARN_ALL_CRAFTS = 425, + RBAC_PERM_COMMAND_LEARN_ALL_DEFAULT = 426, + RBAC_PERM_COMMAND_LEARN_ALL_LANG = 427, + RBAC_PERM_COMMAND_LEARN_ALL_RECIPES = 428, + RBAC_PERM_COMMAND_UNLEARN = 429, + RBAC_PERM_COMMAND_LFG = 430, + RBAC_PERM_COMMAND_LFG_PLAYER = 431, + RBAC_PERM_COMMAND_LFG_GROUP = 432, + RBAC_PERM_COMMAND_LFG_QUEUE = 433, + RBAC_PERM_COMMAND_LFG_CLEAN = 434, + RBAC_PERM_COMMAND_LFG_OPTIONS = 435, + RBAC_PERM_COMMAND_LIST = 436, + RBAC_PERM_COMMAND_LIST_CREATURE = 437, + RBAC_PERM_COMMAND_LIST_ITEM = 438, + RBAC_PERM_COMMAND_LIST_OBJECT = 439, + RBAC_PERM_COMMAND_LIST_AURAS = 440, + RBAC_PERM_COMMAND_LIST_MAIL = 441, + RBAC_PERM_COMMAND_LOOKUP = 442, + RBAC_PERM_COMMAND_LOOKUP_AREA = 443, + RBAC_PERM_COMMAND_LOOKUP_CREATURE = 444, + RBAC_PERM_COMMAND_LOOKUP_EVENT = 445, + RBAC_PERM_COMMAND_LOOKUP_FACTION = 446, + RBAC_PERM_COMMAND_LOOKUP_ITEM = 447, + RBAC_PERM_COMMAND_LOOKUP_ITEMSET = 448, + RBAC_PERM_COMMAND_LOOKUP_OBJECT = 449, + RBAC_PERM_COMMAND_LOOKUP_QUEST = 450, + RBAC_PERM_COMMAND_LOOKUP_PLAYER = 451, + RBAC_PERM_COMMAND_LOOKUP_PLAYER_IP = 452, + RBAC_PERM_COMMAND_LOOKUP_PLAYER_ACCOUNT = 453, + RBAC_PERM_COMMAND_LOOKUP_PLAYER_EMAIL = 454, + RBAC_PERM_COMMAND_LOOKUP_SKILL = 455, + RBAC_PERM_COMMAND_LOOKUP_SPELL = 456, + RBAC_PERM_COMMAND_LOOKUP_SPELL_ID = 457, + RBAC_PERM_COMMAND_LOOKUP_TAXINODE = 458, + RBAC_PERM_COMMAND_LOOKUP_TELE = 459, + RBAC_PERM_COMMAND_LOOKUP_TITLE = 460, + RBAC_PERM_COMMAND_LOOKUP_MAP = 461, + RBAC_PERM_COMMAND_ANNOUNCE = 462, + RBAC_PERM_COMMAND_CHANNEL = 463, + RBAC_PERM_COMMAND_CHANNEL_SET = 464, + RBAC_PERM_COMMAND_CHANNEL_SET_OWNERSHIP = 465, + RBAC_PERM_COMMAND_GMANNOUNCE = 466, + RBAC_PERM_COMMAND_GMNAMEANNOUNCE = 467, + RBAC_PERM_COMMAND_GMNOTIFY = 468, + RBAC_PERM_COMMAND_NAMEANNOUNCE = 469, + RBAC_PERM_COMMAND_NOTIFY = 470, + RBAC_PERM_COMMAND_WHISPERS = 471, + RBAC_PERM_COMMAND_GROUP = 472, + RBAC_PERM_COMMAND_GROUP_LEADER = 473, + RBAC_PERM_COMMAND_GROUP_DISBAND = 474, + RBAC_PERM_COMMAND_GROUP_REMOVE = 475, + RBAC_PERM_COMMAND_GROUP_JOIN = 476, + RBAC_PERM_COMMAND_GROUP_LIST = 477, + RBAC_PERM_COMMAND_GROUP_SUMMON = 478, + RBAC_PERM_COMMAND_PET = 479, + RBAC_PERM_COMMAND_PET_CREATE = 480, + RBAC_PERM_COMMAND_PET_LEARN = 481, + RBAC_PERM_COMMAND_PET_UNLEARN = 482, + RBAC_PERM_COMMAND_SEND = 483, + RBAC_PERM_COMMAND_SEND_ITEMS = 484, + RBAC_PERM_COMMAND_SEND_MAIL = 485, + RBAC_PERM_COMMAND_SEND_MESSAGE = 486, + RBAC_PERM_COMMAND_SEND_MONEY = 487, + RBAC_PERM_COMMAND_ADDITEM = 488, + RBAC_PERM_COMMAND_ADDITEMSET = 489, + RBAC_PERM_COMMAND_APPEAR = 490, + RBAC_PERM_COMMAND_AURA = 491, + RBAC_PERM_COMMAND_BANK = 492, + RBAC_PERM_COMMAND_BINDSIGHT = 493, + RBAC_PERM_COMMAND_COMBATSTOP = 494, + RBAC_PERM_COMMAND_COMETOME = 495, + RBAC_PERM_COMMAND_COMMANDS = 496, + RBAC_PERM_COMMAND_COOLDOWN = 497, + RBAC_PERM_COMMAND_DAMAGE = 498, + RBAC_PERM_COMMAND_DEV = 499, + RBAC_PERM_COMMAND_DIE = 500, + RBAC_PERM_COMMAND_DISMOUNT = 501, + RBAC_PERM_COMMAND_DISTANCE = 502, + RBAC_PERM_COMMAND_FLUSHARENAPOINTS = 503, + RBAC_PERM_COMMAND_FREEZE = 504, + RBAC_PERM_COMMAND_GPS = 505, + RBAC_PERM_COMMAND_GUID = 506, + RBAC_PERM_COMMAND_HELP = 507, + RBAC_PERM_COMMAND_HIDEAREA = 508, + RBAC_PERM_COMMAND_ITEMMOVE = 509, + RBAC_PERM_COMMAND_KICK = 510, + RBAC_PERM_COMMAND_LINKGRAVE = 511, + RBAC_PERM_COMMAND_LISTFREEZE = 512, + RBAC_PERM_COMMAND_MAXSKILL = 513, + RBAC_PERM_COMMAND_MOVEGENS = 514, + RBAC_PERM_COMMAND_MUTE = 515, + RBAC_PERM_COMMAND_NEARGRAVE = 516, + RBAC_PERM_COMMAND_PINFO = 517, + RBAC_PERM_COMMAND_PLAYALL = 518, + RBAC_PERM_COMMAND_POSSESS = 519, + RBAC_PERM_COMMAND_RECALL = 520, + RBAC_PERM_COMMAND_REPAIRITEMS = 521, + RBAC_PERM_COMMAND_RESPAWN = 522, + RBAC_PERM_COMMAND_REVIVE = 523, + RBAC_PERM_COMMAND_SAVE = 524, + RBAC_PERM_COMMAND_SAVEALL = 525, + RBAC_PERM_COMMAND_SETSKILL = 526, + RBAC_PERM_COMMAND_SHOWAREA = 527, + RBAC_PERM_COMMAND_SUMMON = 528, + RBAC_PERM_COMMAND_UNAURA = 529, + RBAC_PERM_COMMAND_UNBINDSIGHT = 530, + RBAC_PERM_COMMAND_UNFREEZE = 531, + RBAC_PERM_COMMAND_UNMUTE = 532, + RBAC_PERM_COMMAND_UNPOSSESS = 533, + RBAC_PERM_COMMAND_UNSTUCK = 534, + RBAC_PERM_COMMAND_WCHANGE = 535, + RBAC_PERM_COMMAND_MMAP = 536, + RBAC_PERM_COMMAND_MMAP_LOADEDTILES = 537, + RBAC_PERM_COMMAND_MMAP_LOC = 538, + RBAC_PERM_COMMAND_MMAP_PATH = 539, + RBAC_PERM_COMMAND_MMAP_STATS = 540, + RBAC_PERM_COMMAND_MMAP_TESTAREA = 541, + RBAC_PERM_COMMAND_MORPH = 542, + RBAC_PERM_COMMAND_DEMORPH = 543, + RBAC_PERM_COMMAND_MODIFY = 544, + RBAC_PERM_COMMAND_MODIFY_ARENAPOINTS = 545, + RBAC_PERM_COMMAND_MODIFY_BIT = 546, + RBAC_PERM_COMMAND_MODIFY_DRUNK = 547, + RBAC_PERM_COMMAND_MODIFY_ENERGY = 548, + RBAC_PERM_COMMAND_MODIFY_FACTION = 549, + RBAC_PERM_COMMAND_MODIFY_GENDER = 550, + RBAC_PERM_COMMAND_MODIFY_HONOR = 551, + RBAC_PERM_COMMAND_MODIFY_HP = 552, + RBAC_PERM_COMMAND_MODIFY_MANA = 553, + RBAC_PERM_COMMAND_MODIFY_MONEY = 554, + RBAC_PERM_COMMAND_MODIFY_MOUNT = 555, + RBAC_PERM_COMMAND_MODIFY_PHASE = 556, + RBAC_PERM_COMMAND_MODIFY_RAGE = 557, + RBAC_PERM_COMMAND_MODIFY_REPUTATION = 558, + RBAC_PERM_COMMAND_MODIFY_RUNICPOWER = 559, + RBAC_PERM_COMMAND_MODIFY_SCALE = 560, + RBAC_PERM_COMMAND_MODIFY_SPEED = 561, + RBAC_PERM_COMMAND_MODIFY_SPEED_ALL = 562, + RBAC_PERM_COMMAND_MODIFY_SPEED_BACKWALK = 563, + RBAC_PERM_COMMAND_MODIFY_SPEED_FLY = 564, + RBAC_PERM_COMMAND_MODIFY_SPEED_WALK = 565, + RBAC_PERM_COMMAND_MODIFY_SPEED_SWIM = 566, + RBAC_PERM_COMMAND_MODIFY_SPELL = 567, + RBAC_PERM_COMMAND_MODIFY_STANDSTATE = 568, + RBAC_PERM_COMMAND_MODIFY_TALENTPOINTS = 569, + RBAC_PERM_COMMAND_NPC = 570, + RBAC_PERM_COMMAND_NPC_ADD = 571, + RBAC_PERM_COMMAND_NPC_ADD_FORMATION = 572, + RBAC_PERM_COMMAND_NPC_ADD_ITEM = 573, + RBAC_PERM_COMMAND_NPC_ADD_MOVE = 574, + RBAC_PERM_COMMAND_NPC_ADD_TEMP = 575, + RBAC_PERM_COMMAND_NPC_DELETE = 576, + RBAC_PERM_COMMAND_NPC_DELETE_ITEM = 577, + RBAC_PERM_COMMAND_NPC_FOLLOW = 578, + RBAC_PERM_COMMAND_NPC_FOLLOW_STOP = 579, + RBAC_PERM_COMMAND_NPC_SET = 580, + RBAC_PERM_COMMAND_NPC_SET_ALLOWMOVE = 581, + RBAC_PERM_COMMAND_NPC_SET_ENTRY = 582, + RBAC_PERM_COMMAND_NPC_SET_FACTIONID = 583, + RBAC_PERM_COMMAND_NPC_SET_FLAG = 584, + RBAC_PERM_COMMAND_NPC_SET_LEVEL = 585, + RBAC_PERM_COMMAND_NPC_SET_LINK = 586, + RBAC_PERM_COMMAND_NPC_SET_MODEL = 587, + RBAC_PERM_COMMAND_NPC_SET_MOVETYPE = 588, + RBAC_PERM_COMMAND_NPC_SET_PHASE = 589, + RBAC_PERM_COMMAND_NPC_SET_SPAWNDIST = 590, + RBAC_PERM_COMMAND_NPC_SET_SPAWNTIME = 591, + RBAC_PERM_COMMAND_NPC_SET_DATA = 592, + RBAC_PERM_COMMAND_NPC_INFO = 593, + RBAC_PERM_COMMAND_NPC_NEAR = 594, + RBAC_PERM_COMMAND_NPC_MOVE = 595, + RBAC_PERM_COMMAND_NPC_PLAYEMOTE = 596, + RBAC_PERM_COMMAND_NPC_SAY = 597, + RBAC_PERM_COMMAND_NPC_TEXTEMOTE = 598, + RBAC_PERM_COMMAND_NPC_WHISPER = 599, + RBAC_PERM_COMMAND_NPC_YELL = 600, + RBAC_PERM_COMMAND_NPC_TAME = 601, + RBAC_PERM_COMMAND_QUEST = 602, + RBAC_PERM_COMMAND_QUEST_ADD = 603, + RBAC_PERM_COMMAND_QUEST_COMPLETE = 604, + RBAC_PERM_COMMAND_QUEST_REMOVE = 605, + RBAC_PERM_COMMAND_QUEST_REWARD = 606, + RBAC_PERM_COMMANDS_RELOAD = 607, + RBAC_PERM_COMMANDS_RELOAD_ACCESS_REQUIREMENT = 608, + RBAC_PERM_COMMANDS_RELOAD_ACHIEVEMENT_CRITERIA_DATA = 609, + RBAC_PERM_COMMANDS_RELOAD_ACHIEVEMENT_REWARD = 610, + RBAC_PERM_COMMANDS_RELOAD_ALL = 611, + RBAC_PERM_COMMANDS_RELOAD_ALL_ACHIEVEMENT = 612, + RBAC_PERM_COMMANDS_RELOAD_ALL_AREA = 613, + RBAC_PERM_COMMANDS_RELOAD_ALL_EVENTAI = 614, + RBAC_PERM_COMMANDS_RELOAD_ALL_GOSSIP = 615, + RBAC_PERM_COMMANDS_RELOAD_ALL_ITEM = 616, + RBAC_PERM_COMMANDS_RELOAD_ALL_LOCALES = 617, + RBAC_PERM_COMMANDS_RELOAD_ALL_LOOT = 618, + RBAC_PERM_COMMANDS_RELOAD_ALL_NPC = 619, + RBAC_PERM_COMMANDS_RELOAD_ALL_QUEST = 620, + RBAC_PERM_COMMANDS_RELOAD_ALL_SCRIPTS = 621, + RBAC_PERM_COMMANDS_RELOAD_ALL_SPELL = 622, + RBAC_PERM_COMMANDS_RELOAD_AREATRIGGER_INVOLVEDRELATION = 623, + RBAC_PERM_COMMANDS_RELOAD_AREATRIGGER_TAVERN = 624, + RBAC_PERM_COMMANDS_RELOAD_AREATRIGGER_TELEPORT = 625, + RBAC_PERM_COMMANDS_RELOAD_AUCTIONS = 626, + RBAC_PERM_COMMANDS_RELOAD_AUTOBROADCAST = 627, + RBAC_PERM_COMMANDS_RELOAD_COMMAND = 628, + RBAC_PERM_COMMANDS_RELOAD_CONDITIONS = 629, + RBAC_PERM_COMMANDS_RELOAD_CONFIG = 630, + RBAC_PERM_COMMANDS_RELOAD_CREATURE_AI_SCRIPTS = 631, + RBAC_PERM_COMMANDS_RELOAD_CREATURE_AI_TEXTS = 632, + RBAC_PERM_COMMANDS_RELOAD_CREATURE_LINKED_RESPAWN = 633, + RBAC_PERM_COMMANDS_RELOAD_CREATURE_LOOT_TEMPLATE = 634, + RBAC_PERM_COMMANDS_RELOAD_CREATURE_ONKILL_REPUTATION = 635, + RBAC_PERM_COMMANDS_RELOAD_CREATURE_QUESTENDER = 636, + RBAC_PERM_COMMANDS_RELOAD_CREATURE_QUESTSTARTER = 637, + RBAC_PERM_COMMANDS_RELOAD_CREATURE_SUMMON_GROUPS = 638, + RBAC_PERM_COMMANDS_RELOAD_CREATURE_TEMPLATE = 639, + RBAC_PERM_COMMANDS_RELOAD_CREATURE_TEXT = 640, + RBAC_PERM_COMMANDS_RELOAD_DISABLES = 641, + RBAC_PERM_COMMANDS_RELOAD_DISENCHANT_LOOT_TEMPLATE = 642, + RBAC_PERM_COMMANDS_RELOAD_EVENT_SCRIPTS = 643, + RBAC_PERM_COMMANDS_RELOAD_FISHING_LOOT_TEMPLATE = 644, + RBAC_PERM_COMMANDS_RELOAD_GAME_GRAVEYARD_ZONE = 645, + RBAC_PERM_COMMANDS_RELOAD_GAMEOBJECT_QUESTENDER = 646, + RBAC_PERM_COMMANDS_RELOAD_GAMEOBJECT_QUEST_LOOT_TEMPLATE = 647, + RBAC_PERM_COMMANDS_RELOAD_GAMEOBJECT_QUESTSTARTER = 648, + RBAC_PERM_COMMANDS_RELOAD_GAME_TELE = 649, + RBAC_PERM_COMMANDS_RELOAD_GM_TICKETS = 650, + RBAC_PERM_COMMANDS_RELOAD_GOSSIP_MENU = 651, + RBAC_PERM_COMMANDS_RELOAD_GOSSIP_MENU_OPTION = 652, + RBAC_PERM_COMMANDS_RELOAD_ITEM_ENCHANTMENT_TEMPLATE = 653, + RBAC_PERM_COMMANDS_RELOAD_ITEM_LOOT_TEMPLATE = 654, + RBAC_PERM_COMMANDS_RELOAD_ITEM_SET_NAMES = 655, + RBAC_PERM_COMMANDS_RELOAD_LFG_DUNGEON_REWARDS = 656, + RBAC_PERM_COMMANDS_RELOAD_LOCALES_ACHIEVEMENT_REWARD = 657, + RBAC_PERM_COMMANDS_RELOAD_LOCALES_CRETURE = 658, + RBAC_PERM_COMMANDS_RELOAD_LOCALES_CRETURE_TEXT = 659, + RBAC_PERM_COMMANDS_RELOAD_LOCALES_GAMEOBJECT = 660, + RBAC_PERM_COMMANDS_RELOAD_LOCALES_GOSSIP_MENU_OPTION = 661, + RBAC_PERM_COMMANDS_RELOAD_LOCALES_ITEM = 662, + RBAC_PERM_COMMANDS_RELOAD_LOCALES_ITEM_SET_NAME = 663, + RBAC_PERM_COMMANDS_RELOAD_LOCALES_NPC_TEXT = 664, + RBAC_PERM_COMMANDS_RELOAD_LOCALES_PAGE_TEXT = 665, + RBAC_PERM_COMMANDS_RELOAD_LOCALES_POINTS_OF_INTEREST = 666, + RBAC_PERM_COMMANDS_RELOAD_LOCALES_QUEST = 667, + RBAC_PERM_COMMANDS_RELOAD_MAIL_LEVEL_REWARD = 668, + RBAC_PERM_COMMANDS_RELOAD_MAIL_LOOT_TEMPLATE = 669, + RBAC_PERM_COMMANDS_RELOAD_MILLING_LOOT_TEMPLATE = 670, + RBAC_PERM_COMMANDS_RELOAD_NPC_SPELLCLICK_SPELLS = 671, + RBAC_PERM_COMMANDS_RELOAD_NPC_TRAINER = 672, + RBAC_PERM_COMMANDS_RELOAD_NPC_VENDOR = 673, + RBAC_PERM_COMMANDS_RELOAD_PAGE_TEXT = 674, + RBAC_PERM_COMMANDS_RELOAD_PICKPOCKETING_LOOT_TEMPLATE = 675, + RBAC_PERM_COMMANDS_RELOAD_POINTS_OF_INTEREST = 676, + RBAC_PERM_COMMANDS_RELOAD_PROSPECTING_LOOT_TEMPLATE = 677, + RBAC_PERM_COMMANDS_RELOAD_QUEST_POI = 678, + RBAC_PERM_COMMANDS_RELOAD_QUEST_TEMPLATE = 679, + RBAC_PERM_COMMANDS_RELOAD_RBAC = 680, + RBAC_PERM_COMMANDS_RELOAD_REFERENCE_LOOT_TEMPLATE = 681, + RBAC_PERM_COMMANDS_RELOAD_REPUTATION_REWARD_RATE = 682, + RBAC_PERM_COMMANDS_RELOAD_RESERVED_NAME = 683, + RBAC_PERM_COMMANDS_RELOAD_SKILL_DISCOVERY_TEMPLATE = 684, + RBAC_PERM_COMMANDS_RELOAD_SKILL_EXTRA_ITEM_TEMPLATE = 685, + RBAC_PERM_COMMANDS_RELOAD_SKILL_FISHING_BASE_LEVEL = 686, + RBAC_PERM_COMMANDS_RELOAD_SKINNING_LOOT_TEMPLATE = 687, + RBAC_PERM_COMMANDS_RELOAD_SMART_SCRIPTS = 688, + RBAC_PERM_COMMANDS_RELOAD_SPELL_AREA = 689, + RBAC_PERM_COMMANDS_RELOAD_SPELL_BONUS_DATA = 690, + RBAC_PERM_COMMANDS_RELOAD_SPELL_GROUP = 691, + RBAC_PERM_COMMANDS_RELOAD_SPELL_GROUP_STACK_RULES = 692, + RBAC_PERM_COMMANDS_RELOAD_SPELL_LEARN_SPELL = 693, + RBAC_PERM_COMMANDS_RELOAD_SPELL_LINKED_SPELL = 694, + RBAC_PERM_COMMANDS_RELOAD_SPELL_LOOT_TEMPLATE = 695, + RBAC_PERM_COMMANDS_RELOAD_SPELL_PET_AURAS = 696, + RBAC_PERM_COMMANDS_RELOAD_SPELL_PROC = 697, + RBAC_PERM_COMMANDS_RELOAD_SPELL_PROC_EVENT = 698, + RBAC_PERM_COMMANDS_RELOAD_SPELL_REQUIRED = 699, + RBAC_PERM_COMMANDS_RELOAD_SPELL_SCRIPTS = 700, + RBAC_PERM_COMMANDS_RELOAD_SPELL_TARGET_POSITION = 701, + RBAC_PERM_COMMANDS_RELOAD_SPELL_THREATS = 702, + RBAC_PERM_COMMANDS_RELOAD_SPILLOVER_TEMPLATE = 703, + RBAC_PERM_COMMANDS_RELOAD_TRINITY_STRING = 704, + RBAC_PERM_COMMANDS_RELOAD_VEHICLE_ACCESORY = 705, + RBAC_PERM_COMMANDS_RELOAD_VEHICLE_TEMPLATE_ACCESSORY = 706, + RBAC_PERM_COMMANDS_RELOAD_WARDEN_ACTION = 707, + RBAC_PERM_COMMANDS_RELOAD_WAYPOINT_DATA = 708, + RBAC_PERM_COMMANDS_RELOAD_WAYPOINT_SCRIPTS = 709, + RBAC_PERM_COMMAND_RESET = 710, + RBAC_PERM_COMMAND_RESET_ACHIEVEMENTS = 711, + RBAC_PERM_COMMAND_RESET_HONOR = 712, + RBAC_PERM_COMMAND_RESET_LEVEL = 713, + RBAC_PERM_COMMAND_RESET_SPELLS = 714, + RBAC_PERM_COMMAND_RESET_STATS = 715, + RBAC_PERM_COMMAND_RESET_TALENTS = 716, + RBAC_PERM_COMMAND_RESET_ALL = 717, + RBAC_PERM_COMMAND_SERVER = 718, + RBAC_PERM_COMMAND_SERVER_CORPSES = 719, + RBAC_PERM_COMMAND_SERVER_EXIT = 720, + RBAC_PERM_COMMAND_SERVER_IDLERESTART = 721, + RBAC_PERM_COMMAND_SERVER_IDLERESTART_CANCEL = 722, + RBAC_PERM_COMMAND_SERVER_IDLESHUTDOWN = 723, + RBAC_PERM_COMMAND_SERVER_IDLESHUTDOWN_CANCEL = 724, + RBAC_PERM_COMMAND_SERVER_INFO = 725, + RBAC_PERM_COMMAND_SERVER_PLIMIT = 726, + RBAC_PERM_COMMAND_SERVER_RESTART = 727, + RBAC_PERM_COMMAND_SERVER_RESTART_CANCEL = 728, + RBAC_PERM_COMMAND_SERVER_SET = 729, + RBAC_PERM_COMMAND_SERVER_SET_CLOSED = 730, + RBAC_PERM_COMMAND_SERVER_SET_DIFFTIME = 731, + RBAC_PERM_COMMAND_SERVER_SET_LOGLEVEL = 732, + RBAC_PERM_COMMAND_SERVER_SET_MOTD = 733, + RBAC_PERM_COMMAND_SERVER_SHUTDOWN = 734, + RBAC_PERM_COMMAND_SERVER_SHUTDOWN_CANCEL = 735, + RBAC_PERM_COMMAND_SERVER_MOTD = 736, + RBAC_PERM_COMMAND_TELE = 737, + RBAC_PERM_COMMAND_TELE_ADD = 738, + RBAC_PERM_COMMAND_TELE_DEL = 739, + RBAC_PERM_COMMAND_TELE_NAME = 740, + RBAC_PERM_COMMAND_TELE_GROUP = 741, + RBAC_PERM_COMMAND_TICKET = 742, + RBAC_PERM_COMMAND_TICKET_ASSIGN = 743, + RBAC_PERM_COMMAND_TICKET_CLOSE = 744, + RBAC_PERM_COMMAND_TICKET_CLOSEDLIST = 745, + RBAC_PERM_COMMAND_TICKET_COMMENT = 746, + RBAC_PERM_COMMAND_TICKET_COMPLETE = 747, + RBAC_PERM_COMMAND_TICKET_DELETE = 748, + RBAC_PERM_COMMAND_TICKET_ESCALATE = 749, + RBAC_PERM_COMMAND_TICKET_ESCALATEDLIST = 750, + RBAC_PERM_COMMAND_TICKET_LIST = 751, + RBAC_PERM_COMMAND_TICKET_ONLINELIST = 752, + RBAC_PERM_COMMAND_TICKET_RESET = 753, + RBAC_PERM_COMMAND_TICKET_RESPONSE = 754, + RBAC_PERM_COMMAND_TICKET_RESPONSE_APPEND = 755, + RBAC_PERM_COMMAND_TICKET_RESPONSE_APPENDLN = 756, + RBAC_PERM_COMMAND_TICKET_TOGGLESYSTEM = 757, + RBAC_PERM_COMMAND_TICKET_UNASSIGN = 758, + RBAC_PERM_COMMAND_TICKET_VIEWID = 759, + RBAC_PERM_COMMAND_TICKET_VIEWNAME = 760, + RBAC_PERM_COMMAND_TITLES = 761, + RBAC_PERM_COMMAND_TITLES_ADD = 762, + RBAC_PERM_COMMAND_TITLES_CURRENT = 763, + RBAC_PERM_COMMAND_TITLES_REMOVE = 764, + RBAC_PERM_COMMAND_TITLES_SET = 765, + RBAC_PERM_COMMAND_TITLES_SET_MASK = 766, + RBAC_PERM_COMMAND_WP = 767, + RBAC_PERM_COMMAND_WP_ADD = 768, + RBAC_PERM_COMMAND_WP_EVENT = 769, + RBAC_PERM_COMMAND_WP_LOAD = 770, + RBAC_PERM_COMMAND_WP_MODIFY = 771, + RBAC_PERM_COMMAND_WP_UNLOAD = 772, + RBAC_PERM_COMMAND_WP_RELOAD = 773, + RBAC_PERM_COMMAND_WP_SHOW = 774, + RBAC_PERM_COMMAND_MODIFY_CURRENCY = 775, // only 4.3.4 + RBAC_PERM_COMMAND_DEBUG_PHASE = 776, // Only 4.3.4 + + // custom permissions 1000+ + RBAC_PERM_MAX +}; + +enum RBACCommandResult +{ + RBAC_OK, + RBAC_CANT_ADD_ALREADY_ADDED, + RBAC_CANT_REVOKE_NOT_IN_LIST, + RBAC_IN_GRANTED_LIST, + RBAC_IN_DENIED_LIST, + RBAC_ID_DOES_NOT_EXISTS +}; + +typedef std::bitset<RBAC_PERM_MAX> RBACPermissionContainer; +typedef std::set<uint32> RBACRoleContainer; +typedef std::set<uint32> RBACGroupContainer; + +class RBACObject +{ + public: + RBACObject(uint32 id = 0, std::string const& name = ""): + _id(id), _name(name) { } + + virtual ~RBACObject() { } + + /// Gets the Name of the Object + std::string const& GetName() const { return _name; } + /// Gets the Id of the Object + uint32 GetId() const { return _id; } + + private: + uint32 _id; ///> id of the object + std::string _name; ///> name of the object +}; + +/// Permission: Defines an autorization to perform certain operation +class RBACPermission: public RBACObject +{ + public: + RBACPermission(uint32 id = 0, std::string const& name = ""): + RBACObject(id, name) { } +}; + +/// Set of Permissions +class RBACRole: public RBACObject +{ + public: + RBACRole(uint32 id = 0, std::string const& name = ""): + RBACObject(id, name) { } + + /// Gets the Permissions assigned to this role + RBACPermissionContainer const& GetPermissions() const { return _perms; } + /// Grants a Permission (Adds) + void GrantPermission(uint32 id); + /// Revokes a Permission (Removes) + void RevokePermission(uint32 id); + + private: + RBACPermissionContainer _perms; ///> Set of permissions +}; + +/// Set of Roles +class RBACGroup: public RBACObject +{ + public: + RBACGroup(uint32 id = 0, std::string const& name = ""): + RBACObject(id, name) { } + + /// Gets the Roles assigned to this group + RBACRoleContainer const& GetRoles() const { return _roles; } + /// Grants a Role (Adds) + void GrantRole(uint32 role); + /// Revokes a Role (Removes) + void RevokeRole(uint32 role); + + private: + RBACRoleContainer _roles; ///> Set of Roles +}; + +/** + * @name RBACData + * @brief Contains all needed information about the acccount + * + * This class contains all the data needed to calculate the account permissions. + * RBACDAta is formed by group permissions and user permissions through: + * - Granted Groups, which contains roles, which contains permissions: Set of granted permissions + * - Granted Roles, which contains permissions: Set of granted permissions + * - Denied Roles, which contains permissions: Set of denied permissions + * - Granted Permissions + * - Denied Permissions + * + * Calculation of current Permissions: Granted permissions - Denied permissions + * - Granted permissions: through groups, through roles and directly assigned + * - Denied permissions: through roles and directly assigned + */ +class RBACData: public RBACObject +{ + public: + RBACData(uint32 id, std::string const& name, int32 realmId): + RBACObject(id, name), _realmId(realmId) { } + + /** + * @name HasPermission + * @brief Checks if certain action is allowed + * + * Checks if certain action can be performed. + * + * @return grant or deny action + * + * Example Usage: + * @code + * bool Player::CanJoinArena(Battleground* bg) + * { + * return bg->isArena() && HasPermission(RBAC_PERM_JOIN_ARENA); + * } + * @endcode + */ + bool HasPermission(uint32 permission) const { return _globalPerms.test(permission); } + + // Functions enabled to be used by command system + /// Returns all the granted permissions (after computation) + RBACPermissionContainer const& GetPermissions() const { return _globalPerms; } + /// Returns all the granted permissions + RBACPermissionContainer const& GetGrantedPermissions() const { return _grantedPerms; } + /// Returns all the denied permissions + RBACPermissionContainer const& GetDeniedPermissions() const { return _deniedPerms; } + /// Returns all the granted roles + RBACRoleContainer const& GetGrantedRoles() const { return _grantedRoles; } + /// Returns all the denied roles + RBACRoleContainer const& GetDeniedRoles() const { return _deniedRoles; } + /// Returns all the granted groups + RBACGroupContainer const& GetGroups() const { return _groups; } + + /** + * @name AddGroup + * @brief Adds new group + * + * Add a new group to the account. If realm is 0 or the group can not be added + * No save to db action will be performed. + * + * Fails if group Id does not exists or group already present + * + * @param groupId group to be added + * @param realmId realm affected + * + * @return Success or failure (with reason) to add the group + * + * Example Usage: + * @code + * // previously defined "RBACData* rbac" with proper initialization + * uint32 groupId = 2; + * if (rbac->AddGroup(groupId) == RBAC_OK) + * TC_LOG_DEBUG(LOG_FILTER_PLAYER, "Group %u succesfully added", groupId); + * @endcode + */ + RBACCommandResult AddGroup(uint32 groupId, int32 realmId = 0); + + /** + * @name RemoveGroup + * @brief Removes a group + * + * Removes a group from the account. If realm is 0 or the group can not be removed + * No save to db action will be performed. Any delete operation will always affect + * "all realms (-1)" in addition to the realm specified + * + * Fails if group not present + * + * @param groupId group to be removed + * @param realmId realm affected + * + * @return Success or failure (with reason) to remove the group + * + * Example Usage: + * // previously defined "RBACData* rbac" with proper initialization + * uint32 groupId = 2; + * if (rbac->RemoveGroup(groupId) == RBAC_OK) + * TC_LOG_DEBUG(LOG_FILTER_PLAYER, "Group %u succesfully removed", groupId); + * @endcode + */ + RBACCommandResult RemoveGroup(uint32 groupId, int32 realmId = 0); + + /** + * @name GrantRole + * @brief Grants a role + * + * Grants a role to the account. If realm is 0 or the role can not be added + * No save to db action will be performed. + * + * Fails if role Id does not exists or role already granted or denied + * + * @param roleId role to be granted + * @param realmId realm affected + * + * @return Success or failure (with reason) to grant the role + * + * Example Usage: + * // previously defined "RBACData* rbac" with proper initialization + * uint32 roleId = 2; + * if (rbac->GrantRole(roleId) == RBAC_IN_DENIED_LIST) + * TC_LOG_DEBUG(LOG_FILTER_PLAYER, "Failed to grant role %u, already denied", roleId); + * @endcode + */ + RBACCommandResult GrantRole(uint32 roleId, int32 realmId = 0); + + /** + * @name DenyRole + * @brief Denies a role + * + * Denied a role to the account. If realm is 0 or the role can not be added + * No save to db action will be performed. + * + * Fails if role Id does not exists or role already granted or denied + * + * @param roleId role to be denied + * @param realmId realm affected + * + * @return Success or failure (with reason) to deny the role + * + * Example Usage: + * // previously defined "RBACData* rbac" with proper initialization + * uint32 roleId = 2; + * if (rbac->DenyRole(roleId) == RBAC_ID_DOES_NOT_EXISTS) + * TC_LOG_DEBUG(LOG_FILTER_PLAYER, "Role Id %u does not exists", roleId); + * @endcode + */ + RBACCommandResult DenyRole(uint32 roleId, int32 realmId = 0); + + /** + * @name RevokeRole + * @brief Removes a role + * + * Removes a role from the account. If realm is 0 or the role can not be removed + * No save to db action will be performed. Any delete operation will always affect + * "all realms (-1)" in addition to the realm specified + * + * Fails if role not present + * + * @param roleId role to be removed + * @param realmId realm affected + * + * @return Success or failure (with reason) to remove the role + * + * Example Usage: + * // previously defined "RBACData* rbac" with proper initialization + * uint32 roleId = 2; + * if (rbac->RevokeRole(roleId) == RBAC_OK) + * TC_LOG_DEBUG(LOG_FILTER_PLAYER, "Role %u succesfully removed", roleId); + * @endcode + */ + RBACCommandResult RevokeRole(uint32 roleId, int32 realmId = 0); + + /** + * @name GrantRole + * @brief Grants a permission + * + * Grants a permission to the account. If realm is 0 or the permission can not be added + * No save to db action will be performed. + * + * Fails if permission Id does not exists or permission already granted or denied + * + * @param permissionId permission to be granted + * @param realmId realm affected + * + * @return Success or failure (with reason) to grant the permission + * + * Example Usage: + * // previously defined "RBACData* rbac" with proper initialization + * uint32 permissionId = 2; + * if (rbac->GrantRole(permissionId) == RBAC_IN_DENIED_LIST) + * TC_LOG_DEBUG(LOG_FILTER_PLAYER, "Failed to grant permission %u, already denied", permissionId); + * @endcode + */ + RBACCommandResult GrantPermission(uint32 permissionId, int32 realmId = 0); + + /** + * @name DenyPermission + * @brief Denies a permission + * + * Denied a permission to the account. If realm is 0 or the permission can not be added + * No save to db action will be performed. + * + * Fails if permission Id does not exists or permission already granted or denied + * + * @param permissionId permission to be denied + * @param realmId realm affected + * + * @return Success or failure (with reason) to deny the permission + * + * Example Usage: + * // previously defined "RBACData* rbac" with proper initialization + * uint32 permissionId = 2; + * if (rbac->DenyRole(permissionId) == RBAC_ID_DOES_NOT_EXISTS) + * TC_LOG_DEBUG(LOG_FILTER_PLAYER, "Role Id %u does not exists", permissionId); + * @endcode + */ + RBACCommandResult DenyPermission(uint32 permissionId, int32 realmId = 0); + + /** + * @name RevokePermission + * @brief Removes a permission + * + * Removes a permission from the account. If realm is 0 or the permission can not be removed + * No save to db action will be performed. Any delete operation will always affect + * "all realms (-1)" in addition to the realm specified + * + * Fails if permission not present + * + * @param permissionId permission to be removed + * @param realmId realm affected + * + * @return Success or failure (with reason) to remove the permission + * + * Example Usage: + * // previously defined "RBACData* rbac" with proper initialization + * uint32 permissionId = 2; + * if (rbac->RevokeRole(permissionId) == RBAC_OK) + * TC_LOG_DEBUG(LOG_FILTER_PLAYER, "Permission %u succesfully removed", permissionId); + * @endcode + */ + RBACCommandResult RevokePermission(uint32 permissionId, int32 realmId = 0); + + /// Loads all permissions, groups and roles assigned to current account + void LoadFromDB(); + private: + /// Saves a role to DB, Granted or Denied + void SaveRole(uint32 role, bool granted, int32 realm); + /// Saves a permission to DB, Granted or Denied + void SavePermission(uint32 role, bool granted, int32 realm); + + /** + * @name CalculateNewPermissions + * @brief Calculates new permissions + * + * Calculates new permissions after some change in groups, roles or permissions. + * The calculation is done Granted - Denied: + * - Granted permissions: through groups, through roles and directly assigned + * - Denied permissions: through roles and directly assigned + */ + void CalculateNewPermissions(); + + int32 GetRealmId() { return _realmId; } + + int32 _realmId; ///> RealmId Affected + RBACGroupContainer _groups; ///> Granted groups + RBACRoleContainer _grantedRoles; ///> Granted roles + RBACRoleContainer _deniedRoles; ///> Denied roles + RBACPermissionContainer _grantedPerms; ///> Granted permissions + RBACPermissionContainer _deniedPerms; ///> Denied permissions + RBACPermissionContainer _globalPerms; ///> Calculated permissions +}; + +#endif diff --git a/src/server/game/Achievements/AchievementMgr.cpp b/src/server/game/Achievements/AchievementMgr.cpp index f86146520e3..f60674fee01 100644 --- a/src/server/game/Achievements/AchievementMgr.cpp +++ b/src/server/game/Achievements/AchievementMgr.cpp @@ -83,6 +83,7 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria) switch (criteria->type) { case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE: + case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE: case ACHIEVEMENT_CRITERIA_TYPE_WIN_BG: case ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING: case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST: // only hardcoded list @@ -117,7 +118,6 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria) switch (dataType) { case ACHIEVEMENT_CRITERIA_DATA_TYPE_NONE: - case ACHIEVEMENT_CRITERIA_DATA_TYPE_VALUE: case ACHIEVEMENT_CRITERIA_DATA_INSTANCE_SCRIPT: return true; case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_CREATURE: @@ -180,6 +180,14 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria) } return true; } + case ACHIEVEMENT_CRITERIA_DATA_TYPE_VALUE: + if (value.compType >= COMP_TYPE_MAX) + { + TC_LOG_ERROR(LOG_FILTER_SQL, "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_VALUE (%u) has wrong ComparisionType in value2 (%u), ignored.", + criteria->ID, criteria->type, dataType, value.compType); + return false; + } + return true; case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_LEVEL: if (level.minlevel > STRONG_MAX_LEVEL) { @@ -307,7 +315,7 @@ bool AchievementCriteriaData::Meets(uint32 criteria_id, Player const* source, Un case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_AURA: return target && target->HasAuraEffect(aura.spell_id, aura.effect_idx); case ACHIEVEMENT_CRITERIA_DATA_TYPE_VALUE: - return miscValue1 >= value.minvalue; + return CompareValues(ComparisionType(value.compType), miscValue1, value.value); case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_LEVEL: if (!target) return false; @@ -544,103 +552,50 @@ void AchievementMgr<Player>::SaveToDB(SQLTransaction& trans) { if (!m_completedAchievements.empty()) { - bool need_execute = false; - std::ostringstream ssdel; - std::ostringstream ssins; for (CompletedAchievementMap::iterator iter = m_completedAchievements.begin(); iter != m_completedAchievements.end(); ++iter) { if (!iter->second.changed) continue; - /// first new/changed record prefix - if (!need_execute) - { - ssdel << "DELETE FROM character_achievement WHERE guid = " << GetOwner()->GetGUIDLow() << " AND achievement IN ("; - ssins << "INSERT INTO character_achievement (guid, achievement, date) VALUES "; - need_execute = true; - } - /// next new/changed record prefix - else - { - ssdel << ','; - ssins << ','; - } + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_ACHIEVEMENT_BY_ACHIEVEMENT); + stmt->setUInt16(0, iter->first); + stmt->setUInt32(1, GetOwner()->GetGUID()); + trans->Append(stmt); - // new/changed record data - ssdel << iter->first; - ssins << '(' << GetOwner()->GetGUIDLow() << ',' << iter->first << ',' << uint64(iter->second.date) << ')'; + stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHAR_ACHIEVEMENT); + stmt->setUInt32(0, GetOwner()->GetGUID()); + stmt->setUInt16(1, iter->first); + stmt->setUInt32(2, uint32(iter->second.date)); + trans->Append(stmt); - /// mark as saved in db iter->second.changed = false; } - - if (need_execute) - { - ssdel << ')'; - trans->Append(ssdel.str().c_str()); - trans->Append(ssins.str().c_str()); - } } if (!m_criteriaProgress.empty()) { - /// prepare deleting and insert - bool need_execute_del = false; - bool need_execute_ins = false; - std::ostringstream ssdel; - std::ostringstream ssins; for (CriteriaProgressMap::iterator iter = m_criteriaProgress.begin(); iter != m_criteriaProgress.end(); ++iter) { if (!iter->second.changed) continue; - // deleted data (including 0 progress state) - { - /// first new/changed record prefix (for any counter value) - if (!need_execute_del) - { - ssdel << "DELETE FROM character_achievement_progress WHERE guid = " << GetOwner()->GetGUIDLow() << " AND criteria IN ("; - need_execute_del = true; - } - /// next new/changed record prefix - else - ssdel << ','; - - // new/changed record data - ssdel << iter->first; - } + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_ACHIEVEMENT_PROGRESS_BY_CRITERIA); + stmt->setUInt32(0, GetOwner()->GetGUID()); + stmt->setUInt16(1, iter->first); + trans->Append(stmt); - // store data only for real progress - if (iter->second.counter != 0) + if (iter->second.counter) { - /// first new/changed record prefix - if (!need_execute_ins) - { - ssins << "INSERT INTO character_achievement_progress (guid, criteria, counter, date) VALUES "; - need_execute_ins = true; - } - /// next new/changed record prefix - else - ssins << ','; - - // new/changed record data - ssins << '(' << GetOwner()->GetGUIDLow() << ',' << iter->first << ',' << iter->second.counter << ',' << iter->second.date << ')'; + stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHAR_ACHIEVEMENT_PROGRESS); + stmt->setUInt32(0, GetOwner()->GetGUID()); + stmt->setUInt16(1, iter->first); + stmt->setUInt32(2, iter->second.counter); + stmt->setUInt32(3, uint32(iter->second.date)); + trans->Append(stmt); } - /// mark as updated in db iter->second.changed = false; } - - if (need_execute_del) // DELETE ... IN (.... _)_ - ssdel << ')'; - - if (need_execute_del || need_execute_ins) - { - if (need_execute_del) - trans->Append(ssdel.str().c_str()); - if (need_execute_ins) - trans->Append(ssins.str().c_str()); - } } } @@ -1193,6 +1148,7 @@ void AchievementMgr<T>::UpdateAchievementCriteria(AchievementCriteriaTypes type, SetCriteriaProgress(achievementCriteria, miscValue1, referencePlayer, PROGRESS_ACCUMULATE); break; case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE: + case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE: case ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE: case ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM: case ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM: @@ -1405,7 +1361,6 @@ void AchievementMgr<T>::UpdateAchievementCriteria(AchievementCriteriaTypes type, } } } - break; } case ACHIEVEMENT_CRITERIA_TYPE_REACH_GUILD_LEVEL: @@ -1416,7 +1371,6 @@ void AchievementMgr<T>::UpdateAchievementCriteria(AchievementCriteriaTypes type, case ACHIEVEMENT_CRITERIA_TYPE_PLAY_ARENA: case ACHIEVEMENT_CRITERIA_TYPE_OWN_RANK: case ACHIEVEMENT_CRITERIA_TYPE_EARNED_PVP_TITLE: - case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE: case ACHIEVEMENT_CRITERIA_TYPE_SPENT_GOLD_GUILD_REPAIRS: case ACHIEVEMENT_CRITERIA_TYPE_CRAFT_ITEMS_GUILD: case ACHIEVEMENT_CRITERIA_TYPE_CATCH_FROM_POOL: @@ -1592,6 +1546,7 @@ bool AchievementMgr<T>::IsCompletedCriteria(AchievementCriteriaEntry const* achi case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_AT_BARBER: case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_MAIL: case ACHIEVEMENT_CRITERIA_TYPE_LOSE_DUEL: + case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE: case ACHIEVEMENT_CRITERIA_TYPE_GOLD_EARNED_BY_AUCTIONS: case ACHIEVEMENT_CRITERIA_TYPE_CREATE_AUCTION: case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_BID: diff --git a/src/server/game/Achievements/AchievementMgr.h b/src/server/game/Achievements/AchievementMgr.h index 198e9a0e4ce..6bf84439a7f 100644 --- a/src/server/game/Achievements/AchievementMgr.h +++ b/src/server/game/Achievements/AchievementMgr.h @@ -104,7 +104,8 @@ struct AchievementCriteriaData // ACHIEVEMENT_CRITERIA_DATA_TYPE_VALUE = 8 struct { - uint32 minvalue; + uint32 value; + uint32 compType; } value; // ACHIEVEMENT_CRITERIA_DATA_TYPE_T_LEVEL = 9 struct diff --git a/src/server/game/Battlefield/Battlefield.cpp b/src/server/game/Battlefield/Battlefield.cpp index bff46b9de73..3deb9cd7c46 100644 --- a/src/server/game/Battlefield/Battlefield.cpp +++ b/src/server/game/Battlefield/Battlefield.cpp @@ -810,7 +810,7 @@ bool BfGraveyard::HasNpc(uint64 guid) // ********************** Misc *************************** // ******************************************************* -Creature* Battlefield::SpawnCreature(uint32 entry, Position pos, TeamId team) +Creature* Battlefield::SpawnCreature(uint32 entry, const Position& pos, TeamId team) { return SpawnCreature(entry, pos.m_positionX, pos.m_positionY, pos.m_positionZ, pos.m_orientation, team); } diff --git a/src/server/game/Battlefield/Battlefield.h b/src/server/game/Battlefield/Battlefield.h index 9b3542fca65..fd8e294a426 100644 --- a/src/server/game/Battlefield/Battlefield.h +++ b/src/server/game/Battlefield/Battlefield.h @@ -288,7 +288,7 @@ class Battlefield : public ZoneScript // Misc methods Creature* SpawnCreature(uint32 entry, float x, float y, float z, float o, TeamId team); - Creature* SpawnCreature(uint32 entry, Position pos, TeamId team); + Creature* SpawnCreature(uint32 entry, const Position& pos, TeamId team); GameObject* SpawnGameObject(uint32 entry, float x, float y, float z, float o); Creature* GetCreature(uint64 GUID); diff --git a/src/server/game/Battlefield/BattlefieldMgr.cpp b/src/server/game/Battlefield/BattlefieldMgr.cpp index 28a72152e9d..53b3ce0a6d9 100644 --- a/src/server/game/Battlefield/BattlefieldMgr.cpp +++ b/src/server/game/Battlefield/BattlefieldMgr.cpp @@ -74,11 +74,12 @@ void BattlefieldMgr::HandlePlayerEnterZone(Player* player, uint32 zoneid) if (itr == m_BattlefieldMap.end()) return; - if (itr->second->HasPlayer(player) || !itr->second->IsEnabled()) + Battlefield* bf = itr->second; + if (bf->HasPlayer(player) || !bf->IsEnabled()) return; - itr->second->HandlePlayerEnterZone(player, zoneid); - TC_LOG_DEBUG(LOG_FILTER_BATTLEFIELD, "Player %u entered outdoorpvp id %u", player->GetGUIDLow(), itr->second->GetTypeId()); + bf->HandlePlayerEnterZone(player, zoneid); + TC_LOG_DEBUG(LOG_FILTER_BATTLEFIELD, "Player %u entered outdoorpvp id %u", player->GetGUIDLow(), bf->GetTypeId()); } void BattlefieldMgr::HandlePlayerLeaveZone(Player* player, uint32 zoneid) diff --git a/src/server/game/Battlefield/Zones/BattlefieldWG.h b/src/server/game/Battlefield/Zones/BattlefieldWG.h index dbfe3b3c763..1c959d0e8c1 100644 --- a/src/server/game/Battlefield/Zones/BattlefieldWG.h +++ b/src/server/game/Battlefield/Zones/BattlefieldWG.h @@ -579,8 +579,8 @@ struct WintergraspBuildingSpawnData struct WintergraspRebuildableBuildingData { - uint32 entry; uint64 Guid; + uint32 entry; uint32 WorldState; float x; float y; @@ -1559,7 +1559,7 @@ struct WintergraspWorkshopData } // Spawning associate creature and store them - void AddCreature(WintergraspObjectPositionData obj) + void AddCreature(const WintergraspObjectPositionData& obj) { if (Creature* creature = m_WG->SpawnCreature(obj.entryHorde, obj.x, obj.y, obj.z, obj.o, TEAM_HORDE)) m_CreatureOnPoint[TEAM_HORDE].insert(creature->GetGUID()); @@ -1569,7 +1569,7 @@ struct WintergraspWorkshopData } // Spawning Associate gameobject and store them - void AddGameObject(WintergraspObjectPositionData obj) + void AddGameObject(const WintergraspObjectPositionData& obj) { if (GameObject* gameobject = m_WG->SpawnGameObject(obj.entryHorde, obj.x, obj.y, obj.z, obj.o)) m_GameObjectOnPoint[TEAM_HORDE].insert(gameobject->GetGUID()); diff --git a/src/server/game/Battlegrounds/ArenaTeam.cpp b/src/server/game/Battlegrounds/ArenaTeam.cpp index 9639e36f204..85ce81418c3 100644 --- a/src/server/game/Battlegrounds/ArenaTeam.cpp +++ b/src/server/game/Battlegrounds/ArenaTeam.cpp @@ -84,7 +84,7 @@ bool ArenaTeam::Create(uint64 captainGuid, uint8 type, std::string const& arenaT // Add captain as member AddMember(CaptainGuid); - TC_LOG_DEBUG(LOG_FILTER_ARENAS, "New ArenaTeam created [Id: %u] [Type: %u] [Captain low GUID: %u]", GetId(), GetType(), captainLowGuid); + TC_LOG_DEBUG(LOG_FILTER_ARENAS, "New ArenaTeam created [Id: %u, Name: %s] [Type: %u] [Captain low GUID: %u]", GetId(), GetName().c_str(), GetType(), captainLowGuid); return true; } @@ -306,9 +306,9 @@ void ArenaTeam::SetCaptain(uint64 guid) newCaptain->SetArenaTeamInfoField(GetSlot(), ARENA_TEAM_MEMBER, 0); if (oldCaptain) { - TC_LOG_DEBUG(LOG_FILTER_ARENAS, "Player: %s [GUID: %u] promoted player: %s [GUID: %u] to leader of arena team [Id: %u] [Type: %u].", + TC_LOG_DEBUG(LOG_FILTER_ARENAS, "Player: %s [GUID: %u] promoted player: %s [GUID: %u] to leader of arena team [Id: %u, Name: %s] [Type: %u].", oldCaptain->GetName().c_str(), oldCaptain->GetGUIDLow(), newCaptain->GetName().c_str(), - newCaptain->GetGUIDLow(), GetId(), GetType()); + newCaptain->GetGUIDLow(), GetId(), GetName().c_str(), GetType()); } } } @@ -329,7 +329,7 @@ void ArenaTeam::DelMember(uint64 guid, bool cleanDb) // delete all info regarding this team for (uint32 i = 0; i < ARENA_TEAM_END; ++i) player->SetArenaTeamInfoField(GetSlot(), ArenaTeamInfoType(i), 0); - TC_LOG_DEBUG(LOG_FILTER_ARENAS, "Player: %s [GUID: %u] left arena team type: %u [Id: %u].", player->GetName().c_str(), player->GetGUIDLow(), GetType(), GetId()); + TC_LOG_DEBUG(LOG_FILTER_ARENAS, "Player: %s [GUID: %u] left arena team type: %u [Id: %u, Name: %s].", player->GetName().c_str(), player->GetGUIDLow(), GetType(), GetId(), GetName().c_str()); } // Only used for single member deletion, for arena team disband we use a single query for more efficiency @@ -349,7 +349,7 @@ void ArenaTeam::Disband(WorldSession* session) { BroadcastEvent(ERR_ARENA_TEAM_DISBANDED_S, 0, 2, session->GetPlayerName(), GetName(), ""); if (Player* player = session->GetPlayer()) - TC_LOG_DEBUG(LOG_FILTER_ARENAS, "Player: %s [GUID: %u] disbanded arena team type: %u [Id: %u].", player->GetName().c_str(), player->GetGUIDLow(), GetType(), GetId()); + TC_LOG_DEBUG(LOG_FILTER_ARENAS, "Player: %s [GUID: %u] disbanded arena team type: %u [Id: %u, Name: %s].", player->GetName().c_str(), player->GetGUIDLow(), GetType(), GetId(), GetName().c_str()); } // Remove all members from arena team diff --git a/src/server/game/Battlegrounds/Battleground.cpp b/src/server/game/Battlegrounds/Battleground.cpp index c134e47d007..e6012313c68 100644 --- a/src/server/game/Battlegrounds/Battleground.cpp +++ b/src/server/game/Battlegrounds/Battleground.cpp @@ -923,8 +923,8 @@ void Battleground::EndBattleground(uint32 winner) } } - uint32 winner_kills = player->GetRandomWinner() ? BG_REWARD_WINNER_HONOR_LAST : BG_REWARD_WINNER_HONOR_FIRST; - uint32 loser_kills = player->GetRandomWinner() ? BG_REWARD_LOSER_HONOR_LAST : BG_REWARD_LOSER_HONOR_FIRST; + uint32 winnerKills = player->GetRandomWinner() ? sWorld->getIntConfig(CONFIG_BG_REWARD_WINNER_HONOR_LAST) : sWorld->getIntConfig(CONFIG_BG_REWARD_WINNER_HONOR_FIRST); + uint32 loserKills = player->GetRandomWinner() ? sWorld->getIntConfig(CONFIG_BG_REWARD_LOSER_HONOR_LAST) : sWorld->getIntConfig(CONFIG_BG_REWARD_LOSER_HONOR_FIRST); // remove temporary currency bonus auras before rewarding player player->RemoveAura(SPELL_HONORABLE_DEFENDER_25Y); @@ -935,16 +935,16 @@ void Battleground::EndBattleground(uint32 winner) { if (IsRandom() || BattlegroundMgr::IsBGWeekend(GetTypeID())) { - UpdatePlayerScore(player, SCORE_BONUS_HONOR, GetBonusHonorFromKill(winner_kills)); + UpdatePlayerScore(player, SCORE_BONUS_HONOR, GetBonusHonorFromKill(winnerKills)); if (!player->GetRandomWinner()) { // 100cp awarded for the first random battleground won each day - player->ModifyCurrency(CURRENCY_TYPE_CONQUEST_META_ARENA, BG_REWARD_WINNER_CONQUEST_FIRST); + player->ModifyCurrency(CURRENCY_TYPE_CONQUEST_META_ARENA, sWorld->getIntConfig(CONFIG_BG_REWARD_WINNER_CONQUEST_FIRST)); player->SetRandomWinner(true); } } else // 50cp awarded for each non-rated battleground won - player->ModifyCurrency(CURRENCY_TYPE_CONQUEST_META_ARENA, BG_REWARD_WINNER_CONQUEST_LAST); + player->ModifyCurrency(CURRENCY_TYPE_CONQUEST_META_ARENA, sWorld->getIntConfig(CONFIG_BG_REWARD_WINNER_CONQUEST_LAST)); player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WIN_BG, 1); if (!guildAwarded) @@ -962,7 +962,7 @@ void Battleground::EndBattleground(uint32 winner) else { if (IsRandom() || BattlegroundMgr::IsBGWeekend(GetTypeID())) - UpdatePlayerScore(player, SCORE_BONUS_HONOR, GetBonusHonorFromKill(loser_kills)); + UpdatePlayerScore(player, SCORE_BONUS_HONOR, GetBonusHonorFromKill(loserKills)); } player->ResetAllPowers(); diff --git a/src/server/game/Battlegrounds/Battleground.h b/src/server/game/Battlegrounds/Battleground.h index 6cac44d65fc..7f166b92f80 100644 --- a/src/server/game/Battlegrounds/Battleground.h +++ b/src/server/game/Battlegrounds/Battleground.h @@ -145,18 +145,7 @@ enum BattlegroundBuffObjects BG_OBJECTID_BERSERKERBUFF_ENTRY = 179905 }; -/// Battleground currency rewards. Should be with precision mod. -enum BattlegroundRandomRewards -{ - BG_REWARD_WINNER_HONOR_FIRST = 27000, - BG_REWARD_WINNER_CONQUEST_FIRST = 10000, - BG_REWARD_WINNER_HONOR_LAST = 13500, - BG_REWARD_WINNER_CONQUEST_LAST = 5000, - BG_REWARD_LOSER_HONOR_FIRST = 4500, - BG_REWARD_LOSER_HONOR_LAST = 3500 -}; - -const uint32 Buff_Entries[3] = { BG_OBJECTID_SPEEDBUFF_ENTRY, BG_OBJECTID_REGENBUFF_ENTRY, BG_OBJECTID_BERSERKERBUFF_ENTRY }; +uint32 const Buff_Entries[3] = { BG_OBJECTID_SPEEDBUFF_ENTRY, BG_OBJECTID_REGENBUFF_ENTRY, BG_OBJECTID_BERSERKERBUFF_ENTRY }; enum BattlegroundStatus { diff --git a/src/server/game/Battlegrounds/BattlegroundMgr.cpp b/src/server/game/Battlegrounds/BattlegroundMgr.cpp index 9352b2d5710..f6a3148edc3 100644 --- a/src/server/game/Battlegrounds/BattlegroundMgr.cpp +++ b/src/server/game/Battlegrounds/BattlegroundMgr.cpp @@ -384,8 +384,10 @@ void BattlegroundMgr::BuildPvpLogDataPacket(WorldPacket* data, Battleground* bg) TC_LOG_ERROR(LOG_FILTER_BATTLEGROUND, "Player " UI64FMTD " has scoreboard entry for battleground %u but is not in battleground!", itr->first, bg->GetTypeID(true)); continue; } + Player* player = ObjectAccessor::FindPlayer(itr->first); ObjectGuid playerGUID = itr->first; + BattlegroundScore* score = itr->second; data->WriteBit(0); // Unk 1 data->WriteBit(0); // Unk 2 @@ -402,18 +404,18 @@ void BattlegroundMgr::BuildPvpLogDataPacket(WorldPacket* data, Battleground* bg) data->WriteBit(player->GetBGTeam() == HORDE ? 0 : 1); data->WriteBit(playerGUID[7]); - buff << uint32(itr->second->HealingDone); // healing done - buff << uint32(itr->second->DamageDone); // damage done + buff << uint32(score->HealingDone); // healing done + buff << uint32(score->DamageDone); // damage done if (!isArena) { - buff << uint32(itr->second->BonusHonor / 100); - buff << uint32(itr->second->Deaths); - buff << uint32(itr->second->HonorableKills); + buff << uint32(score->BonusHonor / 100); + buff << uint32(score->Deaths); + buff << uint32(score->HonorableKills); } buff.WriteByteSeq(playerGUID[4]); - buff << uint32(itr->second->KillingBlows); + buff << uint32(score->KillingBlows); // if (unk 5) << uint32() unk buff.WriteByteSeq(playerGUID[5]); // if (unk 6) << uint32() unk @@ -421,7 +423,6 @@ void BattlegroundMgr::BuildPvpLogDataPacket(WorldPacket* data, Battleground* bg) buff.WriteByteSeq(playerGUID[1]); buff.WriteByteSeq(playerGUID[6]); - buff << int32(player->GetPrimaryTalentTree(player->GetActiveSpec())); switch (bg->GetTypeID(true)) // Custom values @@ -431,45 +432,45 @@ void BattlegroundMgr::BuildPvpLogDataPacket(WorldPacket* data, Battleground* bg) { case 489: data->WriteBits(0x00000002, 24); - buff << uint32(((BattlegroundWGScore*)itr->second)->FlagCaptures); // flag captures - buff << uint32(((BattlegroundWGScore*)itr->second)->FlagReturns); // flag returns + buff << uint32(((BattlegroundWGScore*)score)->FlagCaptures); // flag captures + buff << uint32(((BattlegroundWGScore*)score)->FlagReturns); // flag returns break; case 566: data->WriteBits(0x00000001, 24); - buff << uint32(((BattlegroundEYScore*)itr->second)->FlagCaptures); // flag captures + buff << uint32(((BattlegroundEYScore*)score)->FlagCaptures); // flag captures break; case 529: data->WriteBits(0x00000002, 24); - buff << uint32(((BattlegroundABScore*)itr->second)->BasesAssaulted); // bases assaulted - buff << uint32(((BattlegroundABScore*)itr->second)->BasesDefended); // bases defended + buff << uint32(((BattlegroundABScore*)score)->BasesAssaulted); // bases assaulted + buff << uint32(((BattlegroundABScore*)score)->BasesDefended); // bases defended break; case 30: data->WriteBits(0x00000005, 24); - buff << uint32(((BattlegroundAVScore*)itr->second)->GraveyardsAssaulted); // GraveyardsAssaulted - buff << uint32(((BattlegroundAVScore*)itr->second)->GraveyardsDefended); // GraveyardsDefended - buff << uint32(((BattlegroundAVScore*)itr->second)->TowersAssaulted); // TowersAssaulted - buff << uint32(((BattlegroundAVScore*)itr->second)->TowersDefended); // TowersDefended - buff << uint32(((BattlegroundAVScore*)itr->second)->MinesCaptured); // MinesCaptured + buff << uint32(((BattlegroundAVScore*)score)->GraveyardsAssaulted); // GraveyardsAssaulted + buff << uint32(((BattlegroundAVScore*)score)->GraveyardsDefended); // GraveyardsDefended + buff << uint32(((BattlegroundAVScore*)score)->TowersAssaulted); // TowersAssaulted + buff << uint32(((BattlegroundAVScore*)score)->TowersDefended); // TowersDefended + buff << uint32(((BattlegroundAVScore*)score)->MinesCaptured); // MinesCaptured break; case 607: data->WriteBits(0x00000002, 24); - buff << uint32(((BattlegroundSAScore*)itr->second)->demolishers_destroyed); - buff << uint32(((BattlegroundSAScore*)itr->second)->gates_destroyed); + buff << uint32(((BattlegroundSAScore*)score)->demolishers_destroyed); + buff << uint32(((BattlegroundSAScore*)score)->gates_destroyed); break; case 628: // IC data->WriteBits(0x00000002, 24); - buff << uint32(((BattlegroundICScore*)itr->second)->BasesAssaulted); // bases assaulted - buff << uint32(((BattlegroundICScore*)itr->second)->BasesDefended); // bases defended + buff << uint32(((BattlegroundICScore*)score)->BasesAssaulted); // bases assaulted + buff << uint32(((BattlegroundICScore*)score)->BasesDefended); // bases defended break; case 726: data->WriteBits(0x00000002, 24); - buff << uint32(((BattlegroundTPScore*)itr->second)->FlagCaptures); // flag captures - buff << uint32(((BattlegroundTPScore*)itr->second)->FlagReturns); // flag returns + buff << uint32(((BattlegroundTPScore*)score)->FlagCaptures); // flag captures + buff << uint32(((BattlegroundTPScore*)score)->FlagReturns); // flag returns break; case 761: data->WriteBits(0x00000002, 24); - buff << uint32(((BattlegroundBFGScore*)itr->second)->BasesAssaulted); // bases assaulted - buff << uint32(((BattlegroundBFGScore*)itr->second)->BasesDefended); // bases defended + buff << uint32(((BattlegroundBFGScore*)score)->BasesAssaulted); // bases assaulted + buff << uint32(((BattlegroundBFGScore*)score)->BasesDefended); // bases defended break; default: data->WriteBits(0, 24); @@ -478,45 +479,45 @@ void BattlegroundMgr::BuildPvpLogDataPacket(WorldPacket* data, Battleground* bg) break; case BATTLEGROUND_AV: data->WriteBits(0x00000005, 24); - buff << uint32(((BattlegroundAVScore*)itr->second)->GraveyardsAssaulted); // GraveyardsAssaulted - buff << uint32(((BattlegroundAVScore*)itr->second)->GraveyardsDefended); // GraveyardsDefended - buff << uint32(((BattlegroundAVScore*)itr->second)->TowersAssaulted); // TowersAssaulted - buff << uint32(((BattlegroundAVScore*)itr->second)->TowersDefended); // TowersDefended - buff << uint32(((BattlegroundAVScore*)itr->second)->MinesCaptured); // MinesCaptured + buff << uint32(((BattlegroundAVScore*)score)->GraveyardsAssaulted); // GraveyardsAssaulted + buff << uint32(((BattlegroundAVScore*)score)->GraveyardsDefended); // GraveyardsDefended + buff << uint32(((BattlegroundAVScore*)score)->TowersAssaulted); // TowersAssaulted + buff << uint32(((BattlegroundAVScore*)score)->TowersDefended); // TowersDefended + buff << uint32(((BattlegroundAVScore*)score)->MinesCaptured); // MinesCaptured break; case BATTLEGROUND_WS: data->WriteBits(0x00000002, 24); - buff << uint32(((BattlegroundWGScore*)itr->second)->FlagCaptures); // flag captures - buff << uint32(((BattlegroundWGScore*)itr->second)->FlagReturns); // flag returns + buff << uint32(((BattlegroundWGScore*)score)->FlagCaptures); // flag captures + buff << uint32(((BattlegroundWGScore*)score)->FlagReturns); // flag returns break; case BATTLEGROUND_AB: data->WriteBits(0x00000002, 24); - buff << uint32(((BattlegroundABScore*)itr->second)->BasesAssaulted); // bases assaulted - buff << uint32(((BattlegroundABScore*)itr->second)->BasesDefended); // bases defended + buff << uint32(((BattlegroundABScore*)score)->BasesAssaulted); // bases assaulted + buff << uint32(((BattlegroundABScore*)score)->BasesDefended); // bases defended break; case BATTLEGROUND_EY: data->WriteBits(0x00000001, 24); - buff << uint32(((BattlegroundEYScore*)itr->second)->FlagCaptures); // flag captures + buff << uint32(((BattlegroundEYScore*)score)->FlagCaptures); // flag captures break; case BATTLEGROUND_SA: data->WriteBits(0x00000002, 24); - buff << uint32(((BattlegroundSAScore*)itr->second)->demolishers_destroyed); - buff << uint32(((BattlegroundSAScore*)itr->second)->gates_destroyed); + buff << uint32(((BattlegroundSAScore*)score)->demolishers_destroyed); + buff << uint32(((BattlegroundSAScore*)score)->gates_destroyed); break; case BATTLEGROUND_IC: data->WriteBits(0x00000002, 24); - buff << uint32(((BattlegroundICScore*)itr->second)->BasesAssaulted); // bases assaulted - buff << uint32(((BattlegroundICScore*)itr->second)->BasesDefended); // bases defended + buff << uint32(((BattlegroundICScore*)score)->BasesAssaulted); // bases assaulted + buff << uint32(((BattlegroundICScore*)score)->BasesDefended); // bases defended break; case BATTLEGROUND_TP: data->WriteBits(0x00000002, 24); - buff << uint32(((BattlegroundTPScore*)itr->second)->FlagCaptures); // flag captures - buff << uint32(((BattlegroundTPScore*)itr->second)->FlagReturns); // flag returns + buff << uint32(((BattlegroundTPScore*)score)->FlagCaptures); // flag captures + buff << uint32(((BattlegroundTPScore*)score)->FlagReturns); // flag returns break; case BATTLEGROUND_BFG: data->WriteBits(0x00000002, 24); - buff << uint32(((BattlegroundBFGScore*)itr->second)->BasesAssaulted); // bases assaulted - buff << uint32(((BattlegroundBFGScore*)itr->second)->BasesDefended); // bases defended + buff << uint32(((BattlegroundBFGScore*)score)->BasesAssaulted); // bases assaulted + buff << uint32(((BattlegroundBFGScore*)score)->BasesDefended); // bases defended break; case BATTLEGROUND_NA: case BATTLEGROUND_BE: @@ -1126,22 +1127,22 @@ void BattlegroundMgr::BuildBattlegroundListPacket(WorldPacket* data, uint64 guid if (!bracketEntry) return; - uint32 winner_conquest = (player->GetRandomWinner() ? BG_REWARD_WINNER_CONQUEST_FIRST : BG_REWARD_WINNER_CONQUEST_LAST) / CURRENCY_PRECISION; - uint32 winner_honor = (player->GetRandomWinner() ? BG_REWARD_WINNER_HONOR_FIRST : BG_REWARD_WINNER_HONOR_LAST) / CURRENCY_PRECISION; - uint32 loser_honor = (!player->GetRandomWinner() ? BG_REWARD_LOSER_HONOR_FIRST : BG_REWARD_LOSER_HONOR_LAST) / CURRENCY_PRECISION; + uint32 winnerConquest = (player->GetRandomWinner() ? sWorld->getIntConfig(CONFIG_BG_REWARD_WINNER_CONQUEST_FIRST) : sWorld->getIntConfig(CONFIG_BG_REWARD_WINNER_CONQUEST_LAST)) / CURRENCY_PRECISION; + uint32 winnerHonor = (player->GetRandomWinner() ? sWorld->getIntConfig(CONFIG_BG_REWARD_WINNER_HONOR_FIRST) : sWorld->getIntConfig(CONFIG_BG_REWARD_WINNER_HONOR_LAST)) / CURRENCY_PRECISION; + uint32 loserHonor = (!player->GetRandomWinner() ? sWorld->getIntConfig(CONFIG_BG_REWARD_LOSER_HONOR_FIRST) : sWorld->getIntConfig(CONFIG_BG_REWARD_LOSER_HONOR_LAST)) / CURRENCY_PRECISION; ObjectGuid guidBytes = guid; data->Initialize(SMSG_BATTLEFIELD_LIST); - *data << uint32(winner_conquest) // Winner Conquest Reward or Random Winner Conquest Reward - << uint32(winner_conquest) // Winner Conquest Reward or Random Winner Conquest Reward - << uint32(loser_honor) // Loser Honor Reward or Random Loser Honor Reward - << uint32(bgTypeId) // battleground id - << uint32(loser_honor) // Loser Honor Reward or Random Loser Honor Reward - << uint32(winner_honor) // Winner Honor Reward or Random Winner Honor Reward - << uint32(winner_honor) // Winner Honor Reward or Random Winner Honor Reward - << uint8(bracketEntry->maxLevel) // max level - << uint8(bracketEntry->minLevel); // min level + *data << uint32(winnerConquest) // Winner Conquest Reward or Random Winner Conquest Reward + << uint32(winnerConquest) // Winner Conquest Reward or Random Winner Conquest Reward + << uint32(loserHonor) // Loser Honor Reward or Random Loser Honor Reward + << uint32(bgTypeId) // battleground id + << uint32(loserHonor) // Loser Honor Reward or Random Loser Honor Reward + << uint32(winnerHonor) // Winner Honor Reward or Random Winner Honor Reward + << uint32(winnerHonor) // Winner Honor Reward or Random Winner Honor Reward + << uint8(bracketEntry->maxLevel) // max level + << uint8(bracketEntry->minLevel); // min level data->WriteBit(guidBytes[0]); data->WriteBit(guidBytes[1]); diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp index 56e2c413228..87a0ead6ca5 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp @@ -544,7 +544,11 @@ void BattlegroundIC::EventPlayerClickedOnFlag(Player* player, GameObject* target float cords[4] = {banner->GetPositionX(), banner->GetPositionY(), banner->GetPositionZ(), banner->GetOrientation() }; DelObject(nodePoint[i].gameobject_type); - AddObject(nodePoint[i].gameobject_type, nodePoint[i].gameobject_entry, cords[0], cords[1], cords[2], cords[3], 0, 0, 0, 0, RESPAWN_ONE_DAY); + if (!AddObject(nodePoint[i].gameobject_type, nodePoint[i].gameobject_entry, cords[0], cords[1], cords[2], cords[3], 0, 0, 0, 0, RESPAWN_ONE_DAY)) + { + TC_LOG_ERROR(LOG_FILTER_BATTLEGROUND, "Isle of Conquest: There was an error spawning a banner (type: %u, entry: %u). Isle of Conquest BG cancelled.", nodePoint[i].gameobject_type, nodePoint[i].gameobject_entry); + Battleground::EndBattleground(WINNER_NONE); + } GetBGObject(nodePoint[i].gameobject_type)->SetUInt32Value(GAMEOBJECT_FACTION, nodePoint[i].faction == TEAM_ALLIANCE ? BG_IC_Factions[1] : BG_IC_Factions[0]); @@ -641,10 +645,13 @@ void BattlegroundIC::HandleCapturedNodes(ICNodePoint* nodePoint, bool recapture) for (uint8 u = 0; u < MAX_HANGAR_TELEPORTERS_SPAWNS; ++u) { uint8 type = BG_IC_GO_HANGAR_TELEPORTER_1+u; - AddObject(type, (nodePoint->faction == TEAM_ALLIANCE ? GO_ALLIANCE_GUNSHIP_PORTAL : GO_HORDE_GUNSHIP_PORTAL), + if (!AddObject(type, (nodePoint->faction == TEAM_ALLIANCE ? GO_ALLIANCE_GUNSHIP_PORTAL : GO_HORDE_GUNSHIP_PORTAL), BG_IC_HangarTeleporters[u].GetPositionX(), BG_IC_HangarTeleporters[u].GetPositionY(), BG_IC_HangarTeleporters[u].GetPositionZ(), BG_IC_HangarTeleporters[u].GetOrientation(), - 0, 0, 0, 0, RESPAWN_ONE_DAY); + 0, 0, 0, 0, RESPAWN_ONE_DAY)) + { + TC_LOG_ERROR(LOG_FILTER_BATTLEGROUND, "Isle of Conquest: There was an error spawning a gunship portal. Type: %u", BG_IC_GO_HANGAR_TELEPORTER_1+u); + } } //TC_LOG_ERROR(LOG_FILTER_BATTLEGROUND, "BG_IC_GO_HANGAR_BANNER CAPTURED Faction: %u", nodePoint->faction); diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundIC.h b/src/server/game/Battlegrounds/Zones/BattlegroundIC.h index 34d03a5d92c..6fdc97f25c5 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundIC.h +++ b/src/server/game/Battlegrounds/Zones/BattlegroundIC.h @@ -818,7 +818,7 @@ const Position allianceGunshipPassengers[5] = struct ICNodePoint { uint32 gameobject_type; // with this we will get the GameObject of that point - uint32 gameobject_entry; // what gamoebject entry is active here. + uint32 gameobject_entry; // what gameobject entry is active here. uint8 faction; // who has this node ICNodePointType nodeType; // here we can specify if it is graveyards, hangar etc... uint32 banners[4]; // the banners that have this point diff --git a/src/server/game/Calendar/CalendarMgr.h b/src/server/game/Calendar/CalendarMgr.h index fac5a59d2f1..1974804e230 100644 --- a/src/server/game/Calendar/CalendarMgr.h +++ b/src/server/game/Calendar/CalendarMgr.h @@ -166,7 +166,7 @@ struct CalendarInvite void SetStatusTime(time_t statusTime) { _statusTime = statusTime; } time_t GetStatusTime() const { return _statusTime; } - void SetText(std::string text) { _text = text; } + void SetText(const std::string& text) { _text = text; } std::string GetText() const { return _text; } void SetStatus(CalendarInviteStatus status) { _status = status; } @@ -223,10 +223,10 @@ struct CalendarEvent void SetGuildId(uint32 guildId) { _guildId = guildId; } uint32 GetGuildId() const { return _guildId; } - void SetTitle(std::string title) { _title = title; } + void SetTitle(const std::string& title) { _title = title; } std::string GetTitle() const { return _title; } - void SetDescription(std::string description) { _description = description; } + void SetDescription(const std::string& description) { _description = description; } std::string GetDescription() const { return _description; } void SetType(CalendarEventType type) { _type = type; } diff --git a/src/server/game/Chat/Channels/ChannelMgr.cpp b/src/server/game/Chat/Channels/ChannelMgr.cpp index aab67fb03bd..5fecf2e7419 100644 --- a/src/server/game/Chat/Channels/ChannelMgr.cpp +++ b/src/server/game/Chat/Channels/ChannelMgr.cpp @@ -44,7 +44,9 @@ ChannelMgr* ChannelMgr::forTeam(uint32 team) Channel* ChannelMgr::GetJoinChannel(std::string const& name, uint32 channelId) { std::wstring wname; - Utf8toWStr(name, wname); + if (!Utf8toWStr(name, wname)) + return NULL; + wstrToLower(wname); ChannelMap::const_iterator i = channels.find(wname); @@ -62,7 +64,9 @@ Channel* ChannelMgr::GetJoinChannel(std::string const& name, uint32 channelId) Channel* ChannelMgr::GetChannel(std::string const& name, Player* player, bool pkt) { std::wstring wname; - Utf8toWStr(name, wname); + if (!Utf8toWStr(name, wname)) + return NULL; + wstrToLower(wname); ChannelMap::const_iterator i = channels.find(wname); @@ -85,7 +89,9 @@ Channel* ChannelMgr::GetChannel(std::string const& name, Player* player, bool pk void ChannelMgr::LeftChannel(std::string const& name) { std::wstring wname; - Utf8toWStr(name, wname); + if (!Utf8toWStr(name, wname)) + return; + wstrToLower(wname); ChannelMap::const_iterator i = channels.find(wname); diff --git a/src/server/game/Chat/Chat.cpp b/src/server/game/Chat/Chat.cpp index 469a2b53b79..fdaaac394f4 100644 --- a/src/server/game/Chat/Chat.cpp +++ b/src/server/game/Chat/Chat.cpp @@ -95,7 +95,7 @@ ChatCommand* ChatHandler::getCommandTable() Field* fields = result->Fetch(); std::string name = fields[0].GetString(); - SetDataForCommandInTable(commandTableCache, name.c_str(), fields[1].GetUInt8(), fields[2].GetString(), name); + SetDataForCommandInTable(commandTableCache, name.c_str(), fields[1].GetUInt16(), fields[2].GetString(), name); } while (result->NextRow()); } @@ -122,28 +122,7 @@ const char *ChatHandler::GetTrinityString(int32 entry) const bool ChatHandler::isAvailable(ChatCommand const& cmd) const { - uint32 permission = 0; - - ///@Workaround:: Fast adaptation to RBAC system till all commands are moved to permissions - switch (AccountTypes(cmd.SecurityLevel)) - { - case SEC_ADMINISTRATOR: - permission = RBAC_PERM_ADMINISTRATOR_COMMANDS; - break; - case SEC_GAMEMASTER: - permission = RBAC_PERM_GAMEMASTER_COMMANDS; - break; - case SEC_MODERATOR: - permission = RBAC_PERM_MODERATOR_COMMANDS; - break; - case SEC_PLAYER: - permission = RBAC_PERM_PLAYER_COMMANDS; - break; - default: // Allow custom security levels for commands - return m_session->GetSecurity() >= AccountTypes(cmd.SecurityLevel); - } - - return HasPermission(permission); + return HasPermission(cmd.Permission); } bool ChatHandler::HasLowerSecurity(Player* target, uint64 guid, bool strong) @@ -299,7 +278,7 @@ void ChatHandler::PSendSysMessage(const char *format, ...) SendSysMessage(str); } -bool ChatHandler::ExecuteCommandInTable(ChatCommand* table, const char* text, const std::string& fullcmd) +bool ChatHandler::ExecuteCommandInTable(ChatCommand* table, const char* text, std::string const& fullcmd) { char const* oldtext = text; std::string cmd = ""; @@ -325,9 +304,7 @@ bool ChatHandler::ExecuteCommandInTable(ChatCommand* table, const char* text, co if (!hasStringAbbr(table[j].Name, cmd.c_str())) continue; - if (strcmp(table[j].Name, cmd.c_str()) != 0) - continue; - else + if (strcmp(table[j].Name, cmd.c_str()) == 0) { match = true; break; @@ -342,7 +319,7 @@ bool ChatHandler::ExecuteCommandInTable(ChatCommand* table, const char* text, co { if (!ExecuteCommandInTable(table[i].ChildCommands, text, fullcmd)) { - if (text && text[0] != '\0') + if (text[0] != '\0') SendSysMessage(LANG_NO_SUBCMD); else SendSysMessage(LANG_CMD_SYNTAX); @@ -361,28 +338,31 @@ bool ChatHandler::ExecuteCommandInTable(ChatCommand* table, const char* text, co // table[i].Name == "" is special case: send original command to handler if ((table[i].Handler)(this, table[i].Name[0] != '\0' ? text : oldtext)) { - // FIXME: When Command system is moved to RBAC this check must be changed - if (!AccountMgr::IsPlayerAccount(table[i].SecurityLevel)) + if (!m_session) // ignore console + return true; + + Player* player = m_session->GetPlayer(); + if (!AccountMgr::IsPlayerAccount(m_session->GetSecurity())) { - // chat case - if (m_session) + uint64 guid = player->GetSelection(); + uint32 areaId = player->GetAreaId(); + std::string areaName = "Unknown"; + std::string zoneName = "Unknown"; + if (AreaTableEntry const* area = GetAreaEntryByAreaID(areaId)) { - Player* p = m_session->GetPlayer(); - uint64 sel_guid = p->GetSelection(); - uint32 areaId = p->GetAreaId(); - std::string areaName = "Unknown"; - std::string zoneName = "Unknown"; - if (AreaTableEntry const* area = GetAreaEntryByAreaID(areaId)) - { - areaName = area->area_name; - if (AreaTableEntry const* zone = GetAreaEntryByAreaID(area->zone)) - zoneName = zone->area_name; - } - - sLog->outCommand(m_session->GetAccountId(), "Command: %s [Player: %s (Guid: %u) (Account: %u) X: %f Y: %f Z: %f Map: %u (%s) Area: %u (%s) Zone: %s Selected %s: %s (GUID: %u)]", - fullcmd.c_str(), p->GetName().c_str(), GUID_LOPART(p->GetGUID()), m_session->GetAccountId(), p->GetPositionX(), p->GetPositionY(), p->GetPositionZ(), p->GetMapId(), p->GetMap() ? p->GetMap()->GetMapName() : "Unknown", areaId, areaName.c_str(), zoneName.c_str(), - GetLogNameForGuid(sel_guid), (p->GetSelectedUnit()) ? p->GetSelectedUnit()->GetName().c_str() : "", GUID_LOPART(sel_guid)); + areaName = area->area_name; + if (AreaTableEntry const* zone = GetAreaEntryByAreaID(area->zone)) + zoneName = zone->area_name; } + + sLog->outCommand(m_session->GetAccountId(), "Command: %s [Player: %s (Guid: %u) (Account: %u) X: %f Y: %f Z: %f Map: %u (%s) Area: %u (%s) Zone: %s Selected %s: %s (GUID: %u)]", + fullcmd.c_str(), player->GetName().c_str(), GUID_LOPART(player->GetGUID()), + m_session->GetAccountId(), player->GetPositionX(), player->GetPositionY(), + player->GetPositionZ(), player->GetMapId(), + player->GetMap() ? player->GetMap()->GetMapName() : "Unknown", + areaId, areaName.c_str(), zoneName.c_str(), GetLogNameForGuid(guid), + (player->GetSelectedUnit()) ? player->GetSelectedUnit()->GetName().c_str() : "", + GUID_LOPART(guid)); } } // some commands have custom error messages. Don't send the default one in these cases. @@ -400,7 +380,7 @@ bool ChatHandler::ExecuteCommandInTable(ChatCommand* table, const char* text, co return false; } -bool ChatHandler::SetDataForCommandInTable(ChatCommand* table, char const* text, uint32 security, std::string const& help, std::string const& fullcommand) +bool ChatHandler::SetDataForCommandInTable(ChatCommand* table, char const* text, uint32 permission, std::string const& help, std::string const& fullcommand) { std::string cmd = ""; @@ -421,7 +401,7 @@ bool ChatHandler::SetDataForCommandInTable(ChatCommand* table, char const* text, // select subcommand from child commands list (including "") if (table[i].ChildCommands != NULL) { - if (SetDataForCommandInTable(table[i].ChildCommands, text, security, help, fullcommand)) + if (SetDataForCommandInTable(table[i].ChildCommands, text, permission, help, fullcommand)) return true; else if (*text) return false; @@ -435,10 +415,10 @@ bool ChatHandler::SetDataForCommandInTable(ChatCommand* table, char const* text, return false; } - if (table[i].SecurityLevel != security) - TC_LOG_INFO(LOG_FILTER_GENERAL, "Table `command` overwrite for command '%s' default security (%u) by %u", fullcommand.c_str(), table[i].SecurityLevel, security); + if (table[i].Permission != permission) + TC_LOG_INFO(LOG_FILTER_GENERAL, "Table `command` overwrite for command '%s' default permission (%u) by %u", fullcommand.c_str(), table[i].Permission, permission); - table[i].SecurityLevel = security; + table[i].Permission = permission; table[i].Help = help; return true; } @@ -462,9 +442,6 @@ bool ChatHandler::ParseCommands(char const* text) std::string fullcmd = text; - if (m_session && !m_session->HasPermission(RBAC_PERM_PLAYER_COMMANDS)) - return false; - /// chat case (.command or !command format) if (m_session) { @@ -695,13 +672,12 @@ void ChatHandler::FillMessageData(WorldPacket* data, WorldSession* session, uint *data << uint32(0); // 2.1.0 *data << uint32(speaker->GetName().size() + 1); *data << speaker->GetName(); - uint64 listener_guid = 0; - *data << uint64(listener_guid); - if (listener_guid && !IS_PLAYER_GUID(listener_guid)) - { - *data << uint32(1); // string listener_name_length - *data << uint8(0); // string listener_name - } + *data << uint64(0); // listener_guid + //if (listener_guid && !IS_PLAYER_GUID(listener_guid)) + //{ + // *data << uint32(1); // string listener_name_length + // *data << uint8(0); // string listener_name + //} *data << uint32(messageLength); *data << message; *data << uint8(0); diff --git a/src/server/game/Chat/Chat.h b/src/server/game/Chat/Chat.h index 298bb91692b..372f98644b5 100644 --- a/src/server/game/Chat/Chat.h +++ b/src/server/game/Chat/Chat.h @@ -21,6 +21,7 @@ #include "SharedDefines.h" #include "WorldSession.h" +#include "RBAC.h" #include <vector> @@ -38,7 +39,7 @@ class ChatCommand { public: const char * Name; - uint32 SecurityLevel; // function pointer required correct align (use uint32) + uint32 Permission; // function pointer required correct align (use uint32) bool AllowConsole; bool (*Handler)(ChatHandler*, const char* args); std::string Help; @@ -129,7 +130,7 @@ class ChatHandler bool ShowHelpForCommand(ChatCommand* table, const char* cmd); protected: explicit ChatHandler() : m_session(NULL), sentErrorMessage(false) {} // for CLI subclass - static bool SetDataForCommandInTable(ChatCommand* table, const char* text, uint32 security, std::string const& help, std::string const& fullcommand); + static bool SetDataForCommandInTable(ChatCommand* table, const char* text, uint32 permission, std::string const& help, std::string const& fullcommand); bool ExecuteCommandInTable(ChatCommand* table, const char* text, std::string const& fullcmd); bool ShowHelpForSubCommands(ChatCommand* table, char const* cmd, char const* subcmd); diff --git a/src/server/game/Combat/HostileRefManager.cpp b/src/server/game/Combat/HostileRefManager.cpp index 4cd76b4e7a2..1e550596368 100644 --- a/src/server/game/Combat/HostileRefManager.cpp +++ b/src/server/game/Combat/HostileRefManager.cpp @@ -35,6 +35,9 @@ HostileRefManager::~HostileRefManager() void HostileRefManager::threatAssist(Unit* victim, float baseThreat, SpellInfo const* threatSpell) { + if (getSize() == 0) + return; + HostileReference* ref = getFirst(); float threat = ThreatCalcHelper::calcThreat(victim, iOwner, baseThreat, (threatSpell ? threatSpell->GetSchoolMask() : SPELL_SCHOOL_MASK_NORMAL), threatSpell); threat /= getSize(); diff --git a/src/server/game/Conditions/ConditionMgr.cpp b/src/server/game/Conditions/ConditionMgr.cpp index 60bbda1a2fb..34c6b63444f 100644 --- a/src/server/game/Conditions/ConditionMgr.cpp +++ b/src/server/game/Conditions/ConditionMgr.cpp @@ -1799,7 +1799,7 @@ bool ConditionMgr::isConditionTypeValid(Condition* cond) { if (cond->ConditionValue2 >= COMP_TYPE_MAX) { - TC_LOG_ERROR(LOG_FILTER_SQL, "Level condition has invalid option (%u), skipped", cond->ConditionValue2); + TC_LOG_ERROR(LOG_FILTER_SQL, "Level condition has invalid ComparisionType (%u), skipped", cond->ConditionValue2); return false; } if (cond->ConditionValue3) diff --git a/src/server/game/Conditions/ConditionMgr.h b/src/server/game/Conditions/ConditionMgr.h index d92a77d51b6..4245f41031e 100644 --- a/src/server/game/Conditions/ConditionMgr.h +++ b/src/server/game/Conditions/ConditionMgr.h @@ -129,20 +129,10 @@ enum ConditionSourceType CONDITION_SOURCE_TYPE_SMART_EVENT = 22, CONDITION_SOURCE_TYPE_NPC_VENDOR = 23, CONDITION_SOURCE_TYPE_SPELL_PROC = 24, - CONDITION_SOURCE_TYPE_PHASE_DEFINITION = 25, + CONDITION_SOURCE_TYPE_PHASE_DEFINITION = 25, // only 4.3.4 CONDITION_SOURCE_TYPE_MAX = 26 // MAX }; -enum ComparisionType -{ - COMP_TYPE_EQ = 0, - COMP_TYPE_HIGH, - COMP_TYPE_LOW, - COMP_TYPE_HIGH_EQ, - COMP_TYPE_LOW_EQ, - COMP_TYPE_MAX -}; - enum RelationType { RELATION_SELF = 0, @@ -277,27 +267,6 @@ class ConditionMgr PhaseDefinitionConditionContainer PhaseDefinitionsConditionStore; }; -template <class T> bool CompareValues(ComparisionType type, T val1, T val2) -{ - switch (type) - { - case COMP_TYPE_EQ: - return val1 == val2; - case COMP_TYPE_HIGH: - return val1 > val2; - case COMP_TYPE_LOW: - return val1 < val2; - case COMP_TYPE_HIGH_EQ: - return val1 >= val2; - case COMP_TYPE_LOW_EQ: - return val1 <= val2; - default: - // incorrect parameter - ASSERT(false); - return false; - } -} - #define sConditionMgr ACE_Singleton<ConditionMgr, ACE_Null_Mutex>::instance() #endif diff --git a/src/server/game/DataStores/DBCStructure.h b/src/server/game/DataStores/DBCStructure.h index 893cbd41f6b..2ef0d846c9c 100644 --- a/src/server/game/DataStores/DBCStructure.h +++ b/src/server/game/DataStores/DBCStructure.h @@ -2263,9 +2263,9 @@ struct VehicleSeatEntry bool CanEnterOrExit() const { return m_flags & VEHICLE_SEAT_FLAG_CAN_ENTER_OR_EXIT; } bool CanSwitchFromSeat() const { return m_flags & VEHICLE_SEAT_FLAG_CAN_SWITCH; } - bool IsUsableByOverride() const { return (m_flags & VEHICLE_SEAT_FLAG_UNCONTROLLED) + bool IsUsableByOverride() const { return (m_flags & (VEHICLE_SEAT_FLAG_UNCONTROLLED | VEHICLE_SEAT_FLAG_UNK18) || (m_flagsB & (VEHICLE_SEAT_FLAG_B_USABLE_FORCED | VEHICLE_SEAT_FLAG_B_USABLE_FORCED_2 | - VEHICLE_SEAT_FLAG_B_USABLE_FORCED_3 | VEHICLE_SEAT_FLAG_B_USABLE_FORCED_4)); } + VEHICLE_SEAT_FLAG_B_USABLE_FORCED_3 | VEHICLE_SEAT_FLAG_B_USABLE_FORCED_4))); } bool IsEjectable() const { return m_flagsB & VEHICLE_SEAT_FLAG_B_EJECTABLE; } }; diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index a957f0fb5ba..a5c9a3f8391 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -523,12 +523,17 @@ void Creature::Update(uint32 diff) if (!IsAlive()) break; - // if creature is charmed, switch to charmed AI + // if creature is charmed, switch to charmed AI (and back) if (NeedChangeAI) { UpdateCharmAI(); NeedChangeAI = false; IsAIEnabled = true; + if (!IsInEvadeMode() && LastCharmerGUID) + if (Unit* charmer = ObjectAccessor::GetUnit(*this, LastCharmerGUID)) + i_AI->AttackStart(charmer); + + LastCharmerGUID = 0; } if (!IsInEvadeMode() && IsAIEnabled) @@ -2529,7 +2534,7 @@ void Creature::SetDisplayId(uint32 modelId) if (CreatureModelInfo const* minfo = sObjectMgr->GetCreatureModelInfo(modelId)) { - SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, minfo->bounding_radius * GetFloatValue(OBJECT_FIELD_SCALE_X)); - SetFloatValue(UNIT_FIELD_COMBATREACH, minfo->combat_reach * GetFloatValue(OBJECT_FIELD_SCALE_X)); + SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, minfo->bounding_radius * GetObjectScale()); + SetFloatValue(UNIT_FIELD_COMBATREACH, minfo->combat_reach * GetObjectScale()); } } diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index 13ed277eda3..365bb05444e 100644 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -193,7 +193,7 @@ struct CreatureBaseStats uint32 GenerateHealth(CreatureTemplate const* info) const { - return uint32((BaseHealth[info->expansion] * info->ModHealth) + 0.5f); + return uint32(ceil(BaseHealth[info->expansion] * info->ModHealth)); } uint32 GenerateMana(CreatureTemplate const* info) const @@ -202,12 +202,12 @@ struct CreatureBaseStats if (!BaseMana) return 0; - return uint32((BaseMana * info->ModMana * info->ModManaExtra) + 0.5f); + return uint32(ceil(BaseMana * info->ModMana * info->ModManaExtra)); } uint32 GenerateArmor(CreatureTemplate const* info) const { - return uint32((BaseArmor * info->ModArmor) + 0.5f); + return uint32(ceil(BaseArmor * info->ModArmor)); } static CreatureBaseStats const* GetBaseStats(uint8 level, uint8 unitClass); diff --git a/src/server/game/Entities/Creature/CreatureGroups.cpp b/src/server/game/Entities/Creature/CreatureGroups.cpp index f8966ba1923..2a3829b7aeb 100644 --- a/src/server/game/Entities/Creature/CreatureGroups.cpp +++ b/src/server/game/Entities/Creature/CreatureGroups.cpp @@ -176,18 +176,20 @@ void CreatureGroup::MemberAttackStart(Creature* member, Unit* target) if (m_leader) // avoid crash if leader was killed and reset. TC_LOG_DEBUG(LOG_FILTER_UNITS, "GROUP ATTACK: group instance id %u calls member instid %u", m_leader->GetInstanceId(), member->GetInstanceId()); - //Skip one check - if (itr->first == member) + Creature* other = itr->first; + + // Skip self + if (other == member) continue; - if (!itr->first->IsAlive()) + if (!other->IsAlive()) continue; - if (itr->first->GetVictim()) + if (other->GetVictim()) continue; - if (itr->first->IsValidAttackTarget(target) && itr->first->AI()) - itr->first->AI()->AttackStart(target); + if (other->IsValidAttackTarget(target)) + other->AI()->AttackStart(target); } } diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index df0a4055beb..f6e6116f391 100644 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -1196,13 +1196,6 @@ void GameObject::Use(Unit* user) // calculate the distance between the player and this slot float thisDistance = player->GetDistance2d(x_i, y_i); - /* debug code. It will spawn a npc on each slot to visualize them. - Creature* helper = player->SummonCreature(14496, x_i, y_i, GetPositionZ(), GetOrientation(), TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 10000); - std::ostringstream output; - output << i << ": thisDist: " << thisDistance; - helper->MonsterSay(output.str().c_str(), LANG_UNIVERSAL, 0); - */ - if (thisDistance <= lowestDist) { nearest_slot = itr->first; @@ -1223,8 +1216,6 @@ void GameObject::Use(Unit* user) return; } } - //else - //player->GetSession()->SendNotification("There's nowhere left for you to sit."); return; } @@ -1267,7 +1258,7 @@ void GameObject::Use(Unit* user) if (Battleground* bg = player->GetBattleground()) bg->EventPlayerUsedGO(player, this); - player->CastedCreatureOrGO(info->entry, GetGUID(), 0); + player->KillCreditGO(info->entry, GetGUID()); } if (uint32 trapEntry = info->goober.linkedTrapId) diff --git a/src/server/game/Entities/Item/Item.cpp b/src/server/game/Entities/Item/Item.cpp index ca87d6b4a19..f1180df1813 100644 --- a/src/server/game/Entities/Item/Item.cpp +++ b/src/server/game/Entities/Item/Item.cpp @@ -1539,7 +1539,7 @@ void Item::ItemContainerSaveLootToDB() trans->Append(stmt_items); // Now insert the items - for (LootItemList::const_iterator _li = loot.items.begin(); _li != loot.items.end(); _li++) + for (LootItemList::const_iterator _li = loot.items.begin(); _li != loot.items.end(); ++_li) { // When an item is looted, it doesn't get removed from the items collection // but we don't want to resave it. diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index 591c83ab71f..0a5eb82a175 100644 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -383,25 +383,15 @@ void Object::BuildMovementUpdate(ByteBuffer* data, uint16 flags) const movementFlagsExtra = self->m_movementInfo.GetExtraMovementFlags(); hasSpline = self->IsSplineEnabled(); - if (GetTypeId() == TYPEID_PLAYER) - { - hasTransportTime2 = self->m_movementInfo.bits.hasTransportTime2; - hasTransportTime3 = self->m_movementInfo.bits.hasTransportTime3; - hasPitch = self->m_movementInfo.bits.hasPitch; - hasFallData = self->m_movementInfo.bits.hasFallData; - hasFallDirection = self->m_movementInfo.bits.hasFallDirection; - hasSplineElevation = self->m_movementInfo.bits.hasSplineElevation; - } - else - { - hasTransportTime2 = self->HasExtraUnitMovementFlag(MOVEMENTFLAG2_INTERPOLATED_MOVEMENT); - hasPitch = ((movementFlags & (MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING)) || - (movementFlagsExtra & MOVEMENTFLAG2_ALWAYS_ALLOW_PITCHING)); - hasFallData = hasFallDirection = movementFlags & MOVEMENTFLAG_FALLING; - hasSplineElevation = movementFlags & MOVEMENTFLAG_SPLINE_ELEVATION; + hasTransportTime2 = self->m_movementInfo.transport.guid != 0 && self->m_movementInfo.transport.time2 != 0; + hasTransportTime3 = false; + hasPitch = self->HasUnitMovementFlag(MovementFlags(MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING)) || self->HasExtraUnitMovementFlag(MOVEMENTFLAG2_ALWAYS_ALLOW_PITCHING); + hasFallDirection = self->HasUnitMovementFlag(MOVEMENTFLAG_FALLING); + hasFallData = hasFallDirection || self->m_movementInfo.jump.fallTime != 0; + hasSplineElevation = self->HasUnitMovementFlag(MOVEMENTFLAG_SPLINE_ELEVATION); + if (GetTypeId() == TYPEID_UNIT) movementFlags &= MOVEMENTFLAG_MASK_CREATURE_ALLOWED; - } data->WriteBit(!movementFlags); data->WriteBit(G3D::fuzzyEq(self->GetOrientation(), 0.0f)); // Has Orientation @@ -504,9 +494,9 @@ void Object::BuildMovementUpdate(ByteBuffer* data, uint16 flags) const { if (hasFallDirection) { - *data << float(self->m_movementInfo.jump.cosAngle); *data << float(self->m_movementInfo.jump.xyspeed); *data << float(self->m_movementInfo.jump.sinAngle); + *data << float(self->m_movementInfo.jump.cosAngle); } *data << uint32(self->m_movementInfo.jump.fallTime); @@ -1256,14 +1246,14 @@ void MovementInfo::OutDebug() TC_LOG_INFO(LOG_FILTER_GENERAL, "time: %u", transport.time); if (flags2 & MOVEMENTFLAG2_INTERPOLATED_MOVEMENT) TC_LOG_INFO(LOG_FILTER_GENERAL, "time2: %u", transport.time2); - if (bits.hasTransportTime3) + if (transport.time3) TC_LOG_INFO(LOG_FILTER_GENERAL, "time3: %u", transport.time3); } if ((flags & (MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING)) || (flags2 & MOVEMENTFLAG2_ALWAYS_ALLOW_PITCHING)) TC_LOG_INFO(LOG_FILTER_GENERAL, "pitch: %f", pitch); - if (flags & MOVEMENTFLAG_FALLING || bits.hasFallData) + if (flags & MOVEMENTFLAG_FALLING || jump.fallTime) { TC_LOG_INFO(LOG_FILTER_GENERAL, "fallTime: %u j_zspeed: %f", jump.fallTime, jump.zspeed); if (flags & MOVEMENTFLAG_FALLING) @@ -2399,8 +2389,6 @@ TempSummon* Map::SummonCreature(uint32 entry, Position const& pos, SummonPropert case UNIT_MASK_MINION: summon = new Minion(properties, summoner, false); break; - default: - return NULL; } if (!summon->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), this, phase, entry, vehId, team, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation())) diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h index 0dbd92d19f5..3c0f7adcfd8 100644 --- a/src/server/game/Entities/Object/Object.h +++ b/src/server/game/Entities/Object/Object.h @@ -55,7 +55,7 @@ enum TypeMask TYPEMASK_DYNAMICOBJECT = 0x0040, TYPEMASK_CORPSE = 0x0080, TYPEMASK_AREATRIGGER = 0x0100, - TYPEMASK_SEER = TYPEMASK_UNIT | TYPEMASK_DYNAMICOBJECT + TYPEMASK_SEER = TYPEMASK_PLAYER | TYPEMASK_UNIT | TYPEMASK_DYNAMICOBJECT }; enum TypeID @@ -192,6 +192,7 @@ class Object uint32 GetEntry() const { return GetUInt32Value(OBJECT_FIELD_ENTRY); } void SetEntry(uint32 entry) { SetUInt32Value(OBJECT_FIELD_ENTRY, entry); } + float GetObjectScale() const { return GetFloatValue(OBJECT_FIELD_SCALE_X); } virtual void SetObjectScale(float scale) { SetFloatValue(OBJECT_FIELD_SCALE_X, scale); } TypeID GetTypeId() const { return m_objectTypeId; } @@ -510,24 +511,12 @@ struct MovementInfo // spline float splineElevation; - // bit markers - struct MovementElementMarkers - { - bool hasTransportTime2; - bool hasTransportTime3; - bool hasPitch; - bool hasFallData; - bool hasFallDirection; - bool hasSplineElevation; - } bits; - MovementInfo() : - guid(0), flags(0), flags2(0), time(0), pitch(0.0f) + guid(0), flags(0), flags2(0), time(0), pitch(0.0f), splineElevation(0.0f) { pos.Relocate(0.0f, 0.0f, 0.0f, 0.0f); transport.Reset(); jump.Reset(); - memset(&bits, 0, sizeof(bits)); } uint32 GetMovementFlags() const { return flags; } @@ -547,15 +536,11 @@ struct MovementInfo void ResetTransport() { transport.Reset(); - bits.hasTransportTime2 = false; - bits.hasTransportTime3 = false; } void ResetJump() { jump.Reset(); - bits.hasFallData = false; - bits.hasFallDirection = false; } void OutDebug(); diff --git a/src/server/game/Entities/Object/Updates/UpdateMask.h b/src/server/game/Entities/Object/Updates/UpdateMask.h index 8be8dfecdaf..72c9e9945d0 100644 --- a/src/server/game/Entities/Object/Updates/UpdateMask.h +++ b/src/server/game/Entities/Object/Updates/UpdateMask.h @@ -36,7 +36,7 @@ class UpdateMask UpdateMask() : _fieldCount(0), _blockCount(0), _bits(NULL) { } - UpdateMask(UpdateMask const& right) + UpdateMask(UpdateMask const& right) : _bits(NULL) { SetCount(right.GetCount()); memcpy(_bits, right._bits, sizeof(uint8) * _blockCount * 32); diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 5a43e87a151..2354db24fb9 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -551,8 +551,11 @@ inline void KillRewarder::_RewardKillCredit(Player* player) { // 4.4. Give kill credit (player must not be in group, or he must be alive or without corpse). if (!_group || player->IsAlive() || !player->GetCorpse()) - if (_victim->GetTypeId() == TYPEID_UNIT) - player->KilledMonster(_victim->ToCreature()->GetCreatureTemplate(), _victim->GetGUID()); + if (Creature* target = _victim->ToCreature()) + { + player->KilledMonster(target->GetCreatureTemplate(), target->GetGUID()); + player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE, target->GetCreatureType(), 1, 0, target); + } } void KillRewarder::_RewardPlayer(Player* player, bool isDungeon) @@ -869,6 +872,8 @@ Player::Player(WorldSession* session): Unit(true), phaseMgr(this) m_WeeklyQuestChanged = false; + m_MonthlyQuestChanged = false; + m_SeasonalQuestChanged = false; SetPendingBind(0, 0); @@ -983,7 +988,7 @@ bool Player::Create(uint32 guidlow, CharacterCreateInfo* createInfo) if (!IsValidGender(createInfo->Gender)) { - TC_LOG_ERROR(LOG_FILTER_PLAYER, "Player::Create: Possible hacking-attempt: Account %u tried creating a character named '%s' with an invalid gender (%hu) - refusing to do so", + TC_LOG_ERROR(LOG_FILTER_PLAYER, "Player::Create: Possible hacking-attempt: Account %u tried creating a character named '%s' with an invalid gender (%u) - refusing to do so", GetSession()->GetAccountId(), m_name.c_str(), createInfo->Gender); return false; } @@ -2151,8 +2156,6 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati // reset movement flags at teleport, because player will continue move with these flags after teleport SetUnitMovementFlags(GetUnitMovementFlags() & MOVEMENTFLAG_MASK_HAS_PLAYER_STATUS_OPCODE); m_movementInfo.ResetJump(); - m_movementInfo.bits.hasPitch = false; - m_movementInfo.bits.hasSplineElevation = false; DisableSpline(); if (m_transport) @@ -4113,7 +4116,7 @@ void Player::removeSpell(uint32 spell_id, bool disabled, bool learn_low_rank) itr->second->state = PLAYERSPELL_REMOVED; } - RemoveAurasDueToSpell(spell_id); + RemoveOwnedAura(spell_id, GetGUID()); // remove pet auras for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) @@ -4759,7 +4762,7 @@ void Player::DeleteFromDB(uint64 playerguid, uint32 accountId, bool updateRealmC if (uint32 guildId = GetGuildIdFromDB(playerguid)) if (Guild* guild = sGuildMgr->GetGuildById(guildId)) - guild->DeleteMember(guid); + guild->DeleteMember(guid, false, false, true); // remove from arena teams LeaveAllArenaTeams(playerguid); @@ -5729,15 +5732,10 @@ void Player::HandleBaseModValue(BaseModGroup modGroup, BaseModType modType, floa return; } - switch (modType) - { - case FLAT_MOD: - m_auraBaseMod[modGroup][modType] += apply ? amount : -amount; - break; - case PCT_MOD: - ApplyPercentModFloatVar(m_auraBaseMod[modGroup][modType], amount, apply); - break; - } + if (modType == FLAT_MOD) + m_auraBaseMod[modGroup][modType] += apply ? amount : -amount; + else // PCT_MOD + ApplyPercentModFloatVar(m_auraBaseMod[modGroup][modType], amount, apply); if (!CanModifyStats()) return; @@ -6667,6 +6665,7 @@ bool Player::IsActionButtonDataValid(uint8 button, uint32 action, uint8 type) case ACTION_BUTTON_CMACRO: case ACTION_BUTTON_MACRO: case ACTION_BUTTON_EQSET: + case ACTION_BUTTON_DROPDOWN: break; default: TC_LOG_ERROR(LOG_FILTER_PLAYER, "Unknown action type %u", type); @@ -6851,10 +6850,8 @@ void Player::CheckAreaExploreAndOutdoor() } else if (diff > 5) { - int32 exploration_percent = (100-((diff-5)*5)); - if (exploration_percent > 100) - exploration_percent = 100; - else if (exploration_percent < 0) + int32 exploration_percent = 100 - ((diff - 5) * 5); + if (exploration_percent < 0) exploration_percent = 0; XP = uint32(sObjectMgr->GetBaseXP(areaEntry->area_level)*exploration_percent/100*sWorld->getRate(RATE_XP_EXPLORE)); @@ -6926,6 +6923,7 @@ int32 Player::CalculateReputationGain(ReputationSource source, uint32 creatureOr case REPUTATION_SOURCE_DAILY_QUEST: case REPUTATION_SOURCE_WEEKLY_QUEST: case REPUTATION_SOURCE_MONTHLY_QUEST: + case REPUTATION_SOURCE_REPEATABLE_QUEST: rate = sWorld->getRate(RATE_REPUTATION_LOWLEVEL_QUEST); break; case REPUTATION_SOURCE_SPELL: @@ -6961,6 +6959,9 @@ int32 Player::CalculateReputationGain(ReputationSource source, uint32 creatureOr case REPUTATION_SOURCE_MONTHLY_QUEST: repRate = repData->questMonthlyRate; break; + case REPUTATION_SOURCE_REPEATABLE_QUEST: + repRate = repData->questRepeatableRate; + break; case REPUTATION_SOURCE_SPELL: repRate = repData->spellRate; break; @@ -7064,6 +7065,8 @@ void Player::RewardReputation(Quest const* quest) rep = CalculateReputationGain(REPUTATION_SOURCE_WEEKLY_QUEST, GetQuestLevel(quest), rep, quest->RewardFactionId[i], noQuestBonus); else if (quest->IsMonthly()) rep = CalculateReputationGain(REPUTATION_SOURCE_MONTHLY_QUEST, GetQuestLevel(quest), rep, quest->RewardFactionId[i], noQuestBonus); + else if (quest->IsRepeatable()) + rep = CalculateReputationGain(REPUTATION_SOURCE_REPEATABLE_QUEST, GetQuestLevel(quest), rep, quest->RewardFactionId[i], noQuestBonus); else rep = CalculateReputationGain(REPUTATION_SOURCE_QUEST, GetQuestLevel(quest), rep, quest->RewardFactionId[i], noQuestBonus); @@ -8280,8 +8283,7 @@ void Player::_ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply ApplyHealthRegenBonus(int32(val), apply); break; case ITEM_MOD_SPELL_PENETRATION: - ApplyModInt32Value(PLAYER_FIELD_MOD_TARGET_RESISTANCE, -val, apply); - m_spellPenetrationItemMod += apply ? val : -val; + ApplySpellPenetrationBonus(val, apply); break; case ITEM_MOD_MASTERY_RATING: ApplyRatingMod(CR_MASTERY, int32(val), apply); @@ -14201,8 +14203,7 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool TC_LOG_DEBUG(LOG_FILTER_PLAYER_ITEMS, "+ %u HEALTH_REGENERATION", enchant_amount); break; case ITEM_MOD_SPELL_PENETRATION: - ApplyModInt32Value(PLAYER_FIELD_MOD_TARGET_RESISTANCE, enchant_amount, apply); - m_spellPenetrationItemMod += apply ? int32(enchant_amount) : -int32(enchant_amount); + ApplySpellPenetrationBonus(enchant_amount, apply); TC_LOG_DEBUG(LOG_FILTER_PLAYER_ITEMS, "+ %u SPELL_PENETRATION", enchant_amount); break; case ITEM_MOD_BLOCK_VALUE: @@ -15003,7 +15004,7 @@ bool Player::CanCompleteQuest(uint32 quest_id) } } - if (qInfo->HasSpecialFlag(QUEST_SPECIAL_FLAGS_KILL_OR_CAST | QUEST_SPECIAL_FLAGS_SPEAKTO)) + if (qInfo->HasSpecialFlag(QUEST_SPECIAL_FLAGS_KILL | QUEST_SPECIAL_FLAGS_CAST | QUEST_SPECIAL_FLAGS_SPEAKTO)) { for (uint8 i = 0; i < QUEST_OBJECTIVES_COUNT; i++) { @@ -15162,7 +15163,7 @@ void Player::AddQuest(Quest const* quest, Object* questGiver) questStatusData.ItemCount[i] = 0; } - if (quest->HasSpecialFlag(QUEST_SPECIAL_FLAGS_KILL_OR_CAST | QUEST_SPECIAL_FLAGS_SPEAKTO)) + if (quest->HasSpecialFlag(QUEST_SPECIAL_FLAGS_KILL | QUEST_SPECIAL_FLAGS_CAST | QUEST_SPECIAL_FLAGS_SPEAKTO)) { for (uint8 i = 0; i < QUEST_OBJECTIVES_COUNT; ++i) questStatusData.CreatureOrGOCount[i] = 0; @@ -16362,7 +16363,7 @@ void Player::KilledMonsterCredit(uint32 entry, uint64 guid /*= 0*/) QuestStatusData& q_status = m_QuestStatus[questid]; if (q_status.Status == QUEST_STATUS_INCOMPLETE && (!GetGroup() || !GetGroup()->isRaidGroup() || qInfo->IsAllowedInRaid(GetMap()->GetDifficulty()))) { - if (qInfo->HasSpecialFlag(QUEST_SPECIAL_FLAGS_KILL_OR_CAST)) + if (qInfo->HasSpecialFlag(QUEST_SPECIAL_FLAGS_KILL) /*&& !qInfo->HasSpecialFlag(QUEST_SPECIAL_FLAGS_CAST)*/) { for (uint8 j = 0; j < QUEST_OBJECTIVES_COUNT; ++j) { @@ -16370,10 +16371,6 @@ void Player::KilledMonsterCredit(uint32 entry, uint64 guid /*= 0*/) if (qInfo->RequiredNpcOrGo[j] <= 0) continue; - // skip Cast at creature objective - if (qInfo->RequiredSpellCast[j] != 0) - continue; - uint32 reqkill = qInfo->RequiredNpcOrGo[j]; if (reqkill == real_entry) @@ -16440,10 +16437,8 @@ void Player::KilledPlayerCredit() } } -void Player::CastedCreatureOrGO(uint32 entry, uint64 guid, uint32 spell_id) +void Player::KillCreditGO(uint32 entry, uint64 guid) { - bool isCreature = IS_CRE_OR_VEH_GUID(guid); - uint16 addCastCount = 1; for (uint8 i = 0; i < MAX_QUEST_LOG_SIZE; ++i) { @@ -16459,45 +16454,16 @@ void Player::CastedCreatureOrGO(uint32 entry, uint64 guid, uint32 spell_id) if (q_status.Status == QUEST_STATUS_INCOMPLETE) { - if (qInfo->HasSpecialFlag(QUEST_SPECIAL_FLAGS_KILL_OR_CAST)) + if (qInfo->HasSpecialFlag(QUEST_SPECIAL_FLAGS_CAST) /*&& !qInfo->HasSpecialFlag(QUEST_SPECIAL_FLAGS_KILL)*/) { for (uint8 j = 0; j < QUEST_OBJECTIVES_COUNT; ++j) { - // skip kill creature objective (0) or wrong spell casts - if (qInfo->RequiredSpellCast[j] != spell_id) - continue; - uint32 reqTarget = 0; - if (isCreature) - { - // creature activate objectives - if (qInfo->RequiredNpcOrGo[j] > 0) - { - // checked at quest_template loading - reqTarget = qInfo->RequiredNpcOrGo[j]; - if (reqTarget != entry) // if entry doesn't match, check for killcredits referenced in template - { - CreatureTemplate const* cinfo = sObjectMgr->GetCreatureTemplate(entry); - if (!cinfo) - { - TC_LOG_ERROR(LOG_FILTER_PLAYER, "Player::CastedCreatureOrGO: GetCreatureTemplate failed for entry %u. Skipping.", entry); - continue; - } - - for (uint8 k = 0; k < MAX_KILL_CREDIT; ++k) - if (cinfo->KillCredit[k] == reqTarget) - entry = cinfo->KillCredit[k]; - } - } - } - else - { - // GO activate objective - if (qInfo->RequiredNpcOrGo[j] < 0) - // checked at quest_template loading - reqTarget = - qInfo->RequiredNpcOrGo[j]; - } + // GO activate objective + if (qInfo->RequiredNpcOrGo[j] < 0) + // checked at quest_template loading + reqTarget = - qInfo->RequiredNpcOrGo[j]; // other not this creature/GO related objectives if (reqTarget != entry) @@ -16542,12 +16508,12 @@ void Player::TalkedToCreature(uint32 entry, uint64 guid) if (q_status.Status == QUEST_STATUS_INCOMPLETE) { - if (qInfo->HasSpecialFlag(QUEST_SPECIAL_FLAGS_KILL_OR_CAST | QUEST_SPECIAL_FLAGS_SPEAKTO)) + if (qInfo->HasSpecialFlag(QUEST_SPECIAL_FLAGS_KILL | QUEST_SPECIAL_FLAGS_CAST | QUEST_SPECIAL_FLAGS_SPEAKTO)) { for (uint8 j = 0; j < QUEST_OBJECTIVES_COUNT; ++j) { - // skip spell casts and Gameobject objectives - if (qInfo->RequiredSpellCast[j] > 0 || qInfo->RequiredNpcOrGo[j] < 0) + // skip gameobject objectives + if (qInfo->RequiredNpcOrGo[j] < 0) continue; uint32 reqTarget = 0; @@ -17131,10 +17097,10 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder) // overwrite possible wrong/corrupted guid SetUInt64Value(OBJECT_FIELD_GUID, MAKE_NEW_GUID(guid, 0, HIGHGUID_PLAYER)); - uint8 Gender = fields[5].GetUInt8(); - if (!IsValidGender(Gender)) + uint8 gender = fields[5].GetUInt8(); + if (!IsValidGender(gender)) { - TC_LOG_ERROR(LOG_FILTER_PLAYER, "Player (GUID: %u) has wrong gender (%hu), can't be loaded.", guid, Gender); + TC_LOG_ERROR(LOG_FILTER_PLAYER, "Player (GUID: %u) has wrong gender (%u), can't be loaded.", guid, gender); return false; } @@ -17142,7 +17108,7 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder) uint32 bytes0 = 0; bytes0 |= fields[3].GetUInt8(); // race bytes0 |= fields[4].GetUInt8() << 8; // class - bytes0 |= Gender << 16; // gender + bytes0 |= gender << 16; // gender SetUInt32Value(UNIT_FIELD_BYTES_0, bytes0); SetUInt32Value(UNIT_FIELD_LEVEL, fields[6].GetUInt8()); @@ -27148,7 +27114,7 @@ float Player::GetCollisionHeight(bool mounted) const CreatureModelDataEntry const* modelData = sCreatureModelDataStore.LookupEntry(displayInfo->ModelId); ASSERT(modelData); - float scaleMod = GetFloatValue(OBJECT_FIELD_SCALE_X); // 99% sure about this + float scaleMod = GetObjectScale(); // 99% sure about this return scaleMod * mountModelData->MountHeight + modelData->CollisionHeight * 0.5f; } @@ -27327,6 +27293,12 @@ void Player::ReadMovementInfo(WorldPacket& data, MovementInfo* mi, Movement::Ext bool hasTimestamp = false; bool hasOrientation = false; bool hasTransportData = false; + bool hasTransportTime2 = false; + bool hasTransportTime3 = false; + bool hasPitch = false; + bool hasFallData = false; + bool hasFallDirection = false; + bool hasSplineElevation = false; ObjectGuid guid; ObjectGuid tguid; @@ -27396,24 +27368,24 @@ void Player::ReadMovementInfo(WorldPacket& data, MovementInfo* mi, Movement::Ext break; case MSEHasTransportTime2: if (hasTransportData) - mi->bits.hasTransportTime2 = data.ReadBit(); + hasTransportTime2 = data.ReadBit(); break; case MSEHasTransportTime3: if (hasTransportData) - mi->bits.hasTransportTime3 = data.ReadBit(); + hasTransportTime3 = data.ReadBit(); break; case MSEHasPitch: - mi->bits.hasPitch = !data.ReadBit(); + hasPitch = !data.ReadBit(); break; case MSEHasFallData: - mi->bits.hasFallData = data.ReadBit(); + hasFallData = data.ReadBit(); break; case MSEHasFallDirection: - if (mi->bits.hasFallData) - mi->bits.hasFallDirection = data.ReadBit(); + if (hasFallData) + hasFallDirection = data.ReadBit(); break; case MSEHasSplineElevation: - mi->bits.hasSplineElevation = !data.ReadBit(); + hasSplineElevation = !data.ReadBit(); break; case MSEHasSpline: data.ReadBit(); @@ -27468,39 +27440,39 @@ void Player::ReadMovementInfo(WorldPacket& data, MovementInfo* mi, Movement::Ext data >> mi->transport.time; break; case MSETransportTime2: - if (hasTransportData && mi->bits.hasTransportTime2) + if (hasTransportData && hasTransportTime2) data >> mi->transport.time2; break; case MSETransportTime3: - if (hasTransportData && mi->bits.hasTransportTime3) + if (hasTransportData && hasTransportTime3) data >> mi->transport.time3; break; case MSEPitch: - if (mi->bits.hasPitch) + if (hasPitch) mi->pitch = G3D::wrap(data.read<float>(), float(-M_PI), float(M_PI)); break; case MSEFallTime: - if (mi->bits.hasFallData) + if (hasFallData) data >> mi->jump.fallTime; break; case MSEFallVerticalSpeed: - if (mi->bits.hasFallData) + if (hasFallData) data >> mi->jump.zspeed; break; case MSEFallCosAngle: - if (mi->bits.hasFallData && mi->bits.hasFallDirection) + if (hasFallData && hasFallDirection) data >> mi->jump.cosAngle; break; case MSEFallSinAngle: - if (mi->bits.hasFallData && mi->bits.hasFallDirection) + if (hasFallData && hasFallDirection) data >> mi->jump.sinAngle; break; case MSEFallHorizontalSpeed: - if (mi->bits.hasFallData && mi->bits.hasFallDirection) + if (hasFallData && hasFallDirection) data >> mi->jump.xyspeed; break; case MSESplineElevation: - if (mi->bits.hasSplineElevation) + if (hasSplineElevation) data >> mi->splineElevation; break; case MSECounter: @@ -27598,13 +27570,13 @@ void Player::ReadMovementInfo(WorldPacket& data, MovementInfo* mi, Movement::Ext REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY | MOVEMENTFLAG_CAN_FLY) && mi->HasMovementFlag(MOVEMENTFLAG_FALLING), MOVEMENTFLAG_FALLING); - REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_FALLING) && (!mi->bits.hasFallData || !mi->bits.hasFallDirection), MOVEMENTFLAG_FALLING); + REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_FALLING) && (!hasFallData || !hasFallDirection), MOVEMENTFLAG_FALLING); REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_SPLINE_ELEVATION) && - (!mi->bits.hasSplineElevation || G3D::fuzzyEq(mi->splineElevation, 0.0f)), MOVEMENTFLAG_SPLINE_ELEVATION); + (!hasSplineElevation || G3D::fuzzyEq(mi->splineElevation, 0.0f)), MOVEMENTFLAG_SPLINE_ELEVATION); // Client first checks if spline elevation != 0, then verifies flag presence - if (mi->bits.hasSplineElevation) + if (hasSplineElevation) mi->AddMovementFlag(MOVEMENTFLAG_SPLINE_ELEVATION); #undef REMOVE_VIOLATING_FLAGS diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 9a2a2c0429d..ff81e0cd6e2 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -307,6 +307,7 @@ enum ActionButtonType ACTION_BUTTON_SPELL = 0x00, ACTION_BUTTON_C = 0x01, // click? ACTION_BUTTON_EQSET = 0x20, + ACTION_BUTTON_DROPDOWN = 0x30, ACTION_BUTTON_MACRO = 0x40, ACTION_BUTTON_CMACRO = ACTION_BUTTON_C | ACTION_BUTTON_MACRO, ACTION_BUTTON_ITEM = 0x80 @@ -319,6 +320,7 @@ enum ReputationSource REPUTATION_SOURCE_DAILY_QUEST, REPUTATION_SOURCE_WEEKLY_QUEST, REPUTATION_SOURCE_MONTHLY_QUEST, + REPUTATION_SOURCE_REPEATABLE_QUEST, REPUTATION_SOURCE_SPELL }; @@ -1591,7 +1593,7 @@ class Player : public Unit, public GridObject<Player> void KilledMonster(CreatureTemplate const* cInfo, uint64 guid); void KilledMonsterCredit(uint32 entry, uint64 guid = 0); void KilledPlayerCredit(); - void CastedCreatureOrGO(uint32 entry, uint64 guid, uint32 spell_id); + void KillCreditGO(uint32 entry, uint64 guid = 0); void TalkedToCreature(uint32 entry, uint64 guid); void MoneyChanged(uint32 value); void ReputationChanged(FactionEntry const* factionEntry); @@ -1957,6 +1959,7 @@ class Player : public Unit, public GridObject<Player> bool UpdateStats(Stats stat); bool UpdateAllStats(); + void ApplySpellPenetrationBonus(int32 amount, bool apply); void UpdateResistances(uint32 school); void UpdateArmor(); void UpdateMaxHealth(); diff --git a/src/server/game/Entities/Unit/StatSystem.cpp b/src/server/game/Entities/Unit/StatSystem.cpp index e319f45f6f2..28e42939287 100644 --- a/src/server/game/Entities/Unit/StatSystem.cpp +++ b/src/server/game/Entities/Unit/StatSystem.cpp @@ -170,6 +170,12 @@ bool Player::UpdateAllStats() return true; } +void Player::ApplySpellPenetrationBonus(int32 amount, bool apply) +{ + ApplyModInt32Value(PLAYER_FIELD_MOD_TARGET_RESISTANCE, -amount, apply); + m_spellPenetrationItemMod += apply ? amount : -amount; +} + void Player::UpdateResistances(uint32 school) { if (school > SPELL_SCHOOL_NORMAL) @@ -967,12 +973,10 @@ bool Guardian::UpdateStats(Stats stat) float mod = 0.75f; if (IsPetGhoul() && (stat == STAT_STAMINA || stat == STAT_STRENGTH)) { - switch (stat) - { - case STAT_STAMINA: mod = 0.3f; break; // Default Owner's Stamina scale - case STAT_STRENGTH: mod = 0.7f; break; // Default Owner's Strength scale - default: break; - } + if (stat == STAT_STAMINA) + mod = 0.3f; // Default Owner's Stamina scale + else + mod = 0.7f; // Default Owner's Strength scale // Check just if owner has Ravenous Dead since it's effect is not an aura AuraEffect const* aurEff = owner->GetAuraEffect(SPELL_AURA_MOD_TOTAL_STAT_PERCENTAGE, SPELLFAMILY_DEATHKNIGHT, 3010, 0); diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index b7c713dd49c..57503737043 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -162,7 +162,7 @@ ProcEventInfo::ProcEventInfo(Unit* actor, Unit* actionTarget, Unit* procTarget, #endif Unit::Unit(bool isWorldObject) : WorldObject(isWorldObject), m_movedPlayer(NULL), m_lastSanctuaryTime(0), - IsAIEnabled(false), NeedChangeAI(false), + IsAIEnabled(false), NeedChangeAI(false), LastCharmerGUID(0), m_ControlledByPlayer(false), movespline(new Movement::MoveSpline()), i_AI(NULL), i_disabledAI(NULL), m_AutoRepeatFirstCast(false), m_procDeep(0), m_removedAurasCount(0), i_motionMaster(this), m_ThreatManager(this), @@ -1488,70 +1488,88 @@ uint32 Unit::CalcArmorReducedDamage(Unit* victim, const uint32 damage, SpellInfo return std::max<uint32>(damage * (1.0f - tmpvalue), 1); } -void Unit::CalcAbsorbResist(Unit* victim, SpellSchoolMask schoolMask, DamageEffectType damagetype, uint32 const damage, uint32 *absorb, uint32 *resist, SpellInfo const* spellInfo) +uint32 Unit::CalcSpellResistance(Unit* victim, SpellSchoolMask schoolMask, SpellInfo const* spellInfo) const { - if (!victim || !victim->IsAlive() || !damage) - return; + // Magic damage, check for resists + if (!(schoolMask & SPELL_SCHOOL_MASK_SPELL)) + return 0; - DamageInfo dmgInfo = DamageInfo(this, victim, damage, spellInfo, schoolMask, damagetype); + // Ignore spells that can't be resisted + if (spellInfo && spellInfo->AttributesEx4 & SPELL_ATTR4_IGNORE_RESISTANCES) + return 0; - // Magic damage, check for resists - // Ignore spells that cant be resisted - if ((schoolMask & SPELL_SCHOOL_MASK_NORMAL) == 0 && (!spellInfo || (spellInfo->AttributesEx4 & SPELL_ATTR4_IGNORE_RESISTANCES) == 0)) - { - float victimResistance = float(victim->GetResistance(schoolMask)); - victimResistance += float(GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_TARGET_RESISTANCE, schoolMask)); + uint8 const bossLevel = 83; + uint32 const bossResistanceConstant = 510; + uint32 resistanceConstant = 0; + uint8 level = victim->getLevel(); - if (Player* player = ToPlayer()) - victimResistance -= float(player->GetSpellPenetrationItemMod()); + if (level == bossLevel) + resistanceConstant = bossResistanceConstant; + else + resistanceConstant = level * 5; - // Resistance can't be lower then 0. - if (victimResistance < 0.0f) - victimResistance = 0.0f; + int32 baseVictimResistance = victim->GetResistance(schoolMask); + baseVictimResistance += GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_TARGET_RESISTANCE, schoolMask); - static uint32 const BOSS_LEVEL = 83; - static float const BOSS_RESISTANCE_CONSTANT = 510.0f; - uint32 level = victim->getLevel(); - float resistanceConstant = 0.0f; + if (Player const* player = ToPlayer()) + baseVictimResistance -= player->GetSpellPenetrationItemMod(); - if (level == BOSS_LEVEL) - resistanceConstant = BOSS_RESISTANCE_CONSTANT; - else - resistanceConstant = level * 5.0f; + // Resistance can't be lower then 0 + int32 victimResistance = std::max<int32>(baseVictimResistance, 0); - float averageResist = victimResistance / (victimResistance + resistanceConstant); - float discreteResistProbability[11]; - for (uint32 i = 0; i < 11; ++i) - { - discreteResistProbability[i] = 0.5f - 2.5f * fabs(0.1f * i - averageResist); - if (discreteResistProbability[i] < 0.0f) - discreteResistProbability[i] = 0.0f; - } + if (victimResistance > 0) + { + int32 ignoredResistance = 0; - if (averageResist <= 0.1f) - { - discreteResistProbability[0] = 1.0f - 7.5f * averageResist; - discreteResistProbability[1] = 5.0f * averageResist; - discreteResistProbability[2] = 2.5f * averageResist; - } + AuraEffectList const& ResIgnoreAuras = GetAuraEffectsByType(SPELL_AURA_MOD_IGNORE_TARGET_RESIST); + for (AuraEffectList::const_iterator itr = ResIgnoreAuras.begin(); itr != ResIgnoreAuras.end(); ++itr) + if ((*itr)->GetMiscValue() & schoolMask) + ignoredResistance += (*itr)->GetAmount(); - float r = float(rand_norm()); - uint32 i = 0; - float probabilitySum = discreteResistProbability[0]; + ignoredResistance = std::min<int32>(ignoredResistance, 100); + ApplyPct(victimResistance, 100 - ignoredResistance); + } - while (r >= probabilitySum && i < 10) - probabilitySum += discreteResistProbability[++i]; + if (victimResistance <= 0) + return 0; - float damageResisted = float(damage * i / 10); + float averageResist = float(victimResistance) / float(victimResistance + resistanceConstant); - AuraEffectList const& ResIgnoreAuras = GetAuraEffectsByType(SPELL_AURA_MOD_IGNORE_TARGET_RESIST); - for (AuraEffectList::const_iterator j = ResIgnoreAuras.begin(); j != ResIgnoreAuras.end(); ++j) - if ((*j)->GetMiscValue() & schoolMask) - AddPct(damageResisted, -(*j)->GetAmount()); + float discreteResistProbability[11]; + for (uint32 i = 0; i < 11; ++i) + { + discreteResistProbability[i] = 0.5f - 2.5f * fabs(0.1f * i - averageResist); + if (discreteResistProbability[i] < 0.0f) + discreteResistProbability[i] = 0.0f; + } - dmgInfo.ResistDamage(uint32(damageResisted)); + if (averageResist <= 0.1f) + { + discreteResistProbability[0] = 1.0f - 7.5f * averageResist; + discreteResistProbability[1] = 5.0f * averageResist; + discreteResistProbability[2] = 2.5f * averageResist; } + uint32 resistance = 0; + float r = float(rand_norm()); + float probabilitySum = discreteResistProbability[0]; + + while (r >= probabilitySum && resistance < 10) + probabilitySum += discreteResistProbability[++resistance]; + + return resistance * 10; +} + +void Unit::CalcAbsorbResist(Unit* victim, SpellSchoolMask schoolMask, DamageEffectType damagetype, uint32 const damage, uint32* absorb, uint32* resist, SpellInfo const* spellInfo /*= NULL*/) +{ + if (!victim || !victim->IsAlive() || !damage) + return; + + DamageInfo dmgInfo = DamageInfo(this, victim, damage, spellInfo, schoolMask, damagetype); + + uint32 spellResistance = CalcSpellResistance(victim, schoolMask, spellInfo); + dmgInfo.ResistDamage(CalculatePct(damage, spellResistance)); + // Ignore Absorption Auras float auraAbsorbMod = 0; AuraEffectList const& AbsIgnoreAurasA = GetAuraEffectsByType(SPELL_AURA_MOD_TARGET_ABSORB_SCHOOL); @@ -1734,7 +1752,7 @@ void Unit::CalcAbsorbResist(Unit* victim, SpellSchoolMask schoolMask, DamageEffe *absorb = dmgInfo.GetAbsorb(); } -void Unit::CalcHealAbsorb(Unit* victim, const SpellInfo* healSpell, uint32 &healAmount, uint32 &absorb) +void Unit::CalcHealAbsorb(Unit* victim, SpellInfo const* healSpell, uint32 &healAmount, uint32 &absorb) { if (!healAmount) return; @@ -2132,24 +2150,26 @@ bool Unit::isBlockCritical() return false; } -int32 Unit::GetMechanicResistChance(const SpellInfo* spell) const +int32 Unit::GetMechanicResistChance(SpellInfo const* spellInfo) const { - if (!spell) + if (!spellInfo) return 0; - int32 resist_mech = 0; + + int32 resistMech = 0; for (uint8 eff = 0; eff < MAX_SPELL_EFFECTS; ++eff) { - if (!spell->Effects[eff].IsEffect()) - break; - int32 effect_mech = spell->GetEffectMechanic(eff); - if (effect_mech) + if (!spellInfo->Effects[eff].IsEffect()) + break; + + int32 effectMech = spellInfo->GetEffectMechanic(eff); + if (effectMech) { - int32 temp = GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_MECHANIC_RESISTANCE, effect_mech); - if (resist_mech < temp) - resist_mech = temp; + int32 temp = GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_MECHANIC_RESISTANCE, effectMech); + if (resistMech < temp) + resistMech = temp; } } - return resist_mech; + return resistMech; } bool Unit::CanUseAttackType(uint8 attacktype) const @@ -2168,23 +2188,24 @@ bool Unit::CanUseAttackType(uint8 attacktype) const } // Melee based spells hit result calculations -SpellMissInfo Unit::MeleeSpellHitResult(Unit* victim, SpellInfo const* spell) +SpellMissInfo Unit::MeleeSpellHitResult(Unit* victim, SpellInfo const* spellInfo) { // Spells with SPELL_ATTR3_IGNORE_HIT_RESULT will additionally fully ignore // resist and deflect chances - if (spell->AttributesEx3 & SPELL_ATTR3_IGNORE_HIT_RESULT) + if (spellInfo->AttributesEx3 & SPELL_ATTR3_IGNORE_HIT_RESULT) return SPELL_MISS_NONE; WeaponAttackType attType = BASE_ATTACK; // Check damage class instead of attack type to correctly handle judgements // - they are meele, but can't be dodged/parried/deflected because of ranged dmg class - if (spell->DmgClass == SPELL_DAMAGE_CLASS_RANGED) + if (spellInfo->DmgClass == SPELL_DAMAGE_CLASS_RANGED) attType = RANGED_ATTACK; - uint32 roll = urand (0, 10000); + uint32 roll = urand(0, 10000); + + uint32 missChance = uint32(MeleeSpellMissChance(victim, attType, spellInfo->Id) * 100.0f); - uint32 missChance = uint32(MeleeSpellMissChance(victim, attType, spell->Id) * 100.0f); // Roll miss uint32 tmp = missChance; if (roll < tmp) @@ -2195,12 +2216,12 @@ SpellMissInfo Unit::MeleeSpellHitResult(Unit* victim, SpellInfo const* spell) // Get effects mechanic and chance for (uint8 eff = 0; eff < MAX_SPELL_EFFECTS; ++eff) { - int32 effect_mech = spell->GetEffectMechanic(eff); + int32 effect_mech = spellInfo->GetEffectMechanic(eff); if (effect_mech) { int32 temp = victim->GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_MECHANIC_RESISTANCE, effect_mech); - if (resist_mech < temp*100) - resist_mech = temp*100; + if (resist_mech < temp * 100) + resist_mech = temp * 100; } } // Roll chance @@ -2210,14 +2231,14 @@ SpellMissInfo Unit::MeleeSpellHitResult(Unit* victim, SpellInfo const* spell) bool canDodge = true; bool canParry = true; - bool canBlock = spell->AttributesEx3 & SPELL_ATTR3_BLOCKABLE_SPELL; + bool canBlock = spellInfo->AttributesEx3 & SPELL_ATTR3_BLOCKABLE_SPELL; // Same spells cannot be parry/dodge - if (spell->Attributes & SPELL_ATTR0_IMPOSSIBLE_DODGE_PARRY_BLOCK) + if (spellInfo->Attributes & SPELL_ATTR0_IMPOSSIBLE_DODGE_PARRY_BLOCK) return SPELL_MISS_NONE; // Chance resist mechanic - int32 resist_chance = victim->GetMechanicResistChance(spell) * 100; + int32 resist_chance = victim->GetMechanicResistChance(spellInfo) * 100; tmp += resist_chance; if (roll < tmp) return SPELL_MISS_RESIST; @@ -2232,7 +2253,7 @@ SpellMissInfo Unit::MeleeSpellHitResult(Unit* victim, SpellInfo const* spell) if (victim->HasInArc(M_PI, this) || victim->HasAuraType(SPELL_AURA_IGNORE_HIT_DIRECTION)) { int32 deflect_chance = victim->GetTotalAuraModifier(SPELL_AURA_DEFLECT_SPELLS) * 100; - tmp+=deflect_chance; + tmp += deflect_chance; if (roll < tmp) return SPELL_MISS_DEFLECT; } @@ -2253,7 +2274,7 @@ SpellMissInfo Unit::MeleeSpellHitResult(Unit* victim, SpellInfo const* spell) } else // Only deterrence as of 3.3.5 { - if (spell->AttributesCu & SPELL_ATTR0_CU_REQ_CASTER_BEHIND_TARGET) + if (spellInfo->AttributesCu & SPELL_ATTR0_CU_REQ_CASTER_BEHIND_TARGET) canParry = false; } } @@ -2271,13 +2292,19 @@ SpellMissInfo Unit::MeleeSpellHitResult(Unit* victim, SpellInfo const* spell) AuraEffectList const& ignore = GetAuraEffectsByType(SPELL_AURA_IGNORE_COMBAT_RESULT); for (AuraEffectList::const_iterator i = ignore.begin(); i != ignore.end(); ++i) { - if (!(*i)->IsAffectingSpell(spell)) + if (!(*i)->IsAffectingSpell(spellInfo)) continue; switch ((*i)->GetMiscValue()) { - case MELEE_HIT_DODGE: canDodge = false; break; - case MELEE_HIT_BLOCK: canBlock = false; break; - case MELEE_HIT_PARRY: canParry = false; break; + case MELEE_HIT_DODGE: + canDodge = false; + break; + case MELEE_HIT_BLOCK: + canBlock = false; + break; + case MELEE_HIT_PARRY: + canParry = false; + break; default: TC_LOG_DEBUG(LOG_FILTER_UNITS, "Spell %u SPELL_AURA_IGNORE_COMBAT_RESULT has unhandled state %d", (*i)->GetId(), (*i)->GetMiscValue()); break; @@ -2335,18 +2362,18 @@ SpellMissInfo Unit::MeleeSpellHitResult(Unit* victim, SpellInfo const* spell) } /// @todo need use unit spell resistances in calculations -SpellMissInfo Unit::MagicSpellHitResult(Unit* victim, SpellInfo const* spell) +SpellMissInfo Unit::MagicSpellHitResult(Unit* victim, SpellInfo const* spellInfo) { // Can`t miss on dead target (on skinning for example) if (!victim->IsAlive() && victim->GetTypeId() != TYPEID_PLAYER) return SPELL_MISS_NONE; - SpellSchoolMask schoolMask = spell->GetSchoolMask(); + SpellSchoolMask schoolMask = spellInfo->GetSchoolMask(); // PvP - PvE spell misschances per leveldif > 2 int32 lchance = victim->GetTypeId() == TYPEID_PLAYER ? 7 : 11; int32 thisLevel = getLevelForTarget(victim); if (GetTypeId() == TYPEID_UNIT && ToCreature()->IsTrigger()) - thisLevel = std::max<int32>(thisLevel, spell->SpellLevel); + thisLevel = std::max<int32>(thisLevel, spellInfo->SpellLevel); int32 leveldif = int32(victim->getLevelForTarget(this)) - thisLevel; // Base hit chance from attacker and victim levels @@ -2358,10 +2385,10 @@ SpellMissInfo Unit::MagicSpellHitResult(Unit* victim, SpellInfo const* spell) // Spellmod from SPELLMOD_RESIST_MISS_CHANCE if (Player* modOwner = GetSpellModOwner()) - modOwner->ApplySpellMod(spell->Id, SPELLMOD_RESIST_MISS_CHANCE, modHitChance); + modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_RESIST_MISS_CHANCE, modHitChance); // Spells with SPELL_ATTR3_IGNORE_HIT_RESULT will ignore target's avoidance effects - if (!(spell->AttributesEx3 & SPELL_ATTR3_IGNORE_HIT_RESULT)) + if (!(spellInfo->AttributesEx3 & SPELL_ATTR3_IGNORE_HIT_RESULT)) { // Chance hit from victim SPELL_AURA_MOD_ATTACKER_SPELL_HIT_CHANCE auras modHitChance += victim->GetTotalAuraModifierByMiscMask(SPELL_AURA_MOD_ATTACKER_SPELL_HIT_CHANCE, schoolMask); @@ -2371,10 +2398,7 @@ SpellMissInfo Unit::MagicSpellHitResult(Unit* victim, SpellInfo const* spell) // Increase hit chance from attacker SPELL_AURA_MOD_SPELL_HIT_CHANCE and attacker ratings HitChance += int32(m_modSpellHitChance * 100.0f); - if (HitChance < 100) - HitChance = 100; - else if (HitChance > 10000) - HitChance = 10000; + RoundToInterval(HitChance, 100, 10000); int32 tmp = 10000 - HitChance; @@ -2385,11 +2409,11 @@ SpellMissInfo Unit::MagicSpellHitResult(Unit* victim, SpellInfo const* spell) // Spells with SPELL_ATTR3_IGNORE_HIT_RESULT will additionally fully ignore // resist and deflect chances - if (spell->AttributesEx3 & SPELL_ATTR3_IGNORE_HIT_RESULT) + if (spellInfo->AttributesEx3 & SPELL_ATTR3_IGNORE_HIT_RESULT) return SPELL_MISS_NONE; // Chance resist mechanic (select max value from every mechanic spell effect) - int32 resist_chance = victim->GetMechanicResistChance(spell) * 100; + int32 resist_chance = victim->GetMechanicResistChance(spellInfo) * 100; tmp += resist_chance; // Roll chance @@ -2416,19 +2440,19 @@ SpellMissInfo Unit::MagicSpellHitResult(Unit* victim, SpellInfo const* spell) // Parry // For spells // Resist -SpellMissInfo Unit::SpellHitResult(Unit* victim, SpellInfo const* spell, bool CanReflect) +SpellMissInfo Unit::SpellHitResult(Unit* victim, SpellInfo const* spellInfo, bool CanReflect) { // Check for immune - if (victim->IsImmunedToSpell(spell)) + if (victim->IsImmunedToSpell(spellInfo)) return SPELL_MISS_IMMUNE; // All positive spells can`t miss /// @todo client not show miss log for this spells - so need find info for this in dbc and use it! - if (spell->IsPositive() - &&(!IsHostileTo(victim))) // prevent from affecting enemy by "positive" spell + if (spellInfo->IsPositive() && !IsHostileTo(victim)) // prevent from affecting enemy by "positive" spell return SPELL_MISS_NONE; + // Check for immune - if (victim->IsImmunedToDamage(spell)) + if (victim->IsImmunedToDamage(spellInfo)) return SPELL_MISS_IMMUNE; if (this == victim) @@ -2444,25 +2468,25 @@ SpellMissInfo Unit::SpellHitResult(Unit* victim, SpellInfo const* spell, bool Ca int32 reflectchance = victim->GetTotalAuraModifier(SPELL_AURA_REFLECT_SPELLS); Unit::AuraEffectList const& mReflectSpellsSchool = victim->GetAuraEffectsByType(SPELL_AURA_REFLECT_SPELLS_SCHOOL); for (Unit::AuraEffectList::const_iterator i = mReflectSpellsSchool.begin(); i != mReflectSpellsSchool.end(); ++i) - if ((*i)->GetMiscValue() & spell->GetSchoolMask()) + if ((*i)->GetMiscValue() & spellInfo->GetSchoolMask()) reflectchance += (*i)->GetAmount(); if (reflectchance > 0 && roll_chance_i(reflectchance)) { // Start triggers for remove charges if need (trigger only for victim, and mark as active spell) - ProcDamageAndSpell(victim, PROC_FLAG_NONE, PROC_FLAG_TAKEN_SPELL_MAGIC_DMG_CLASS_NEG, PROC_EX_REFLECT, 1, BASE_ATTACK, spell); + ProcDamageAndSpell(victim, PROC_FLAG_NONE, PROC_FLAG_TAKEN_SPELL_MAGIC_DMG_CLASS_NEG, PROC_EX_REFLECT, 1, BASE_ATTACK, spellInfo); return SPELL_MISS_REFLECT; } } - switch (spell->DmgClass) + switch (spellInfo->DmgClass) { case SPELL_DAMAGE_CLASS_RANGED: case SPELL_DAMAGE_CLASS_MELEE: - return MeleeSpellHitResult(victim, spell); + return MeleeSpellHitResult(victim, spellInfo); case SPELL_DAMAGE_CLASS_NONE: return SPELL_MISS_NONE; case SPELL_DAMAGE_CLASS_MAGIC: - return MagicSpellHitResult(victim, spell); + return MagicSpellHitResult(victim, spellInfo); } return SPELL_MISS_NONE; } @@ -2788,8 +2812,6 @@ void Unit::SetCurrentCastedSpell(Spell* pSpell) void Unit::InterruptSpell(CurrentSpellTypes spellType, bool withDelayed, bool withInstant) { - ASSERT(spellType < CURRENT_MAX_SPELL); - //TC_LOG_DEBUG(LOG_FILTER_UNITS, "Interrupt spell for unit %u.", GetEntry()); Spell* spell = m_currentSpells[spellType]; if (spell @@ -5458,8 +5480,8 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere // if damage is more than need or target die from damage deal finish spell if (triggeredByAura->GetAmount() <= int32(damage) || GetHealth() <= damage) { - // remember guid before aura delete - uint64 casterGuid = triggeredByAura->GetCasterGUID(); + // remember caster before aura delete + Unit* caster = triggeredByAura->GetCaster(); // Remove aura (before cast for prevent infinite loop handlers) RemoveAurasDueToSpell(triggeredByAura->GetId()); @@ -5467,7 +5489,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere uint32 spell = sSpellMgr->GetSpellWithRank(27285, dummySpell->GetRank()); // Cast finish spell (triggeredByAura already not exist!) - if (Unit* caster = GetUnit(*this, casterGuid)) + if (caster) caster->CastSpell(this, spell, true, castItem); return true; // no hidden cooldown } @@ -5482,14 +5504,14 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere // if damage is more than need deal finish spell if (triggeredByAura->GetAmount() <= int32(damage)) { - // remember guid before aura delete - uint64 casterGuid = triggeredByAura->GetCasterGUID(); + // remember caster before aura delete + Unit* caster = triggeredByAura->GetCaster(); // Remove aura (before cast for prevent infinite loop handlers) RemoveAurasDueToSpell(triggeredByAura->GetId()); // Cast finish spell (triggeredByAura already not exist!) - if (Unit* caster = GetUnit(*this, casterGuid)) + if (caster) caster->CastSpell(this, 32865, true, castItem); return true; // no hidden cooldown } @@ -12236,7 +12258,7 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u Unit* actionTarget = !isVictim ? target : this; DamageInfo damageInfo = DamageInfo(actor, actionTarget, damage, procSpell, procSpell ? SpellSchoolMask(procSpell->SchoolMask) : SPELL_SCHOOL_MASK_NORMAL, SPELL_DIRECT_DAMAGE); - HealInfo healInfo = HealInfo(actor, actionTarget, damage, procSpell, procSpell ? SpellSchoolMask(procSpell->SchoolMask) : SPELL_SCHOOL_MASK_NORMAL); + HealInfo healInfo = HealInfo(damage); ProcEventInfo eventInfo = ProcEventInfo(actor, actionTarget, target, procFlag, 0, 0, procExtra, NULL, &damageInfo, &healInfo); ProcTriggeredList procTriggered; @@ -12814,8 +12836,6 @@ void Unit::UpdateReactives(uint32 p_time) if (getClass() == CLASS_WARRIOR && GetTypeId() == TYPEID_PLAYER) ToPlayer()->ClearComboPoints(); break; - default: - break; } } else @@ -13274,13 +13294,13 @@ bool Unit::IsTriggeredAtSpellProcEvent(Unit* victim, Aura* aura, SpellInfo const { if (!isVictim) { - uint32 WeaponSpeed = GetAttackTime(attType); - chance = GetPPMProcChance(WeaponSpeed, spellProcEvent->ppmRate, spellProto); + uint32 weaponSpeed = GetAttackTime(attType); + chance = GetPPMProcChance(weaponSpeed, spellProcEvent->ppmRate, spellProto); } - else + else if (victim) { - uint32 WeaponSpeed = victim->GetAttackTime(attType); - chance = victim->GetPPMProcChance(WeaponSpeed, spellProcEvent->ppmRate, spellProto); + uint32 weaponSpeed = victim->GetAttackTime(attType); + chance = victim->GetPPMProcChance(weaponSpeed, spellProcEvent->ppmRate, spellProto); } } // Apply chance modifer aura @@ -14072,16 +14092,13 @@ void Unit::RemoveCharmedBy(Unit* charmer) if (Creature* creature = ToCreature()) { + // Creature will restore its old AI on next update if (creature->AI()) creature->AI()->OnCharmed(false); - if (type != CHARM_TYPE_VEHICLE) // Vehicles' AI is never modified - { - creature->AIM_Initialize(); - - if (creature->AI() && charmer && charmer->IsAlive()) - creature->AI()->AttackStart(charmer); - } + // Vehicle should not attack its passenger after he exists the seat + if (type != CHARM_TYPE_VEHICLE) + LastCharmerGUID = charmer->GetGUID(); } else ToPlayer()->SetClientControl(this, 1); @@ -14166,7 +14183,7 @@ void Unit::RestoreFaction() Unit* Unit::GetRedirectThreatTarget() { - return _redirectThreadInfo.GetTargetGUID() ? GetUnit(*this, _redirectThreadInfo.GetTargetGUID()) : NULL; + return _redirectThreadInfo.GetTargetGUID() ? ObjectAccessor::GetUnit(*this, _redirectThreadInfo.GetTargetGUID()) : NULL; } bool Unit::CreateVehicleKit(uint32 id, uint32 creatureEntry) @@ -14914,8 +14931,18 @@ uint32 Unit::GetModelForForm(ShapeshiftForm form) const return 20872; case FORM_FLIGHT_EPIC: if (Player::TeamForRace(getRace()) == ALLIANCE) - return 21243; + return (getRace() == RACE_WORGEN ? 37729 : 21243); + if (getRace() == RACE_TROLL) + return 37730; return 21244; + case FORM_MOONKIN: + if (getRace() == RACE_TROLL) + return 37174; + if (getRace() == RACE_WORGEN) + return 37173; + case FORM_GHOSTWOLF: + if (HasAura(58135)) //! Glyph of Arctic Wolf + return 27312; default: break; } @@ -15320,34 +15347,12 @@ void Unit::WriteMovementInfo(WorldPacket& data, Movement::ExtraMovementStatusEle bool hasTransportData = GetTransGUID() != 0; bool hasSpline = IsSplineEnabled(); - bool hasTransportTime2; - bool hasTransportTime3; - bool hasPitch; - bool hasFallData; - bool hasFallDirection; - bool hasSplineElevation; - - if (GetTypeId() == TYPEID_PLAYER) - { - hasTimestamp = m_movementInfo.time != 0; - hasTransportTime2 = m_movementInfo.bits.hasTransportTime2; - hasTransportTime3 = m_movementInfo.bits.hasTransportTime3; - hasPitch = m_movementInfo.bits.hasPitch; - hasFallData = m_movementInfo.bits.hasFallData; - hasFallDirection = m_movementInfo.bits.hasFallDirection; - hasSplineElevation = m_movementInfo.bits.hasSplineElevation; - } - else - { - hasTransportTime2 = HasExtraUnitMovementFlag(MOVEMENTFLAG2_INTERPOLATED_MOVEMENT); - hasTransportTime3 = false; - hasPitch = HasUnitMovementFlag(MovementFlags(MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING)) || HasExtraUnitMovementFlag(MOVEMENTFLAG2_ALWAYS_ALLOW_PITCHING); - hasFallDirection = HasUnitMovementFlag(MOVEMENTFLAG_FALLING); - hasFallData = hasFallDirection; // FallDirection implies that FallData is set as well - // the only case when hasFallData = 1 && hasFallDirection = 0 - // is for MSG_MOVE_LAND, which is handled above, in player case - hasSplineElevation = HasUnitMovementFlag(MOVEMENTFLAG_SPLINE_ELEVATION); - } + bool hasTransportTime2 = hasTransportData && m_movementInfo.transport.time2 != 0; + bool hasTransportTime3 = false; + bool hasPitch = HasUnitMovementFlag(MovementFlags(MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_FLYING)) || HasExtraUnitMovementFlag(MOVEMENTFLAG2_ALWAYS_ALLOW_PITCHING); + bool hasFallDirection = HasUnitMovementFlag(MOVEMENTFLAG_FALLING); + bool hasFallData = hasFallDirection || m_movementInfo.jump.fallTime != 0; + bool hasSplineElevation = HasUnitMovementFlag(MOVEMENTFLAG_SPLINE_ELEVATION); MovementStatusElements const* sequence = GetMovementStatusElementsSequence(data.GetOpcode()); if (!sequence) @@ -16026,15 +16031,9 @@ bool Unit::SetFall(bool enable) { AddUnitMovementFlag(MOVEMENTFLAG_FALLING); m_movementInfo.SetFallTime(0); - m_movementInfo.bits.hasFallData = true; - m_movementInfo.bits.hasFallDirection = true; } else - { RemoveUnitMovementFlag(MOVEMENTFLAG_FALLING | MOVEMENTFLAG_FALLING_FAR); - m_movementInfo.bits.hasFallDirection = false; - // Do not remove hasFallData marker - } return true; } diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 9aade75a536..8dc4b49eec3 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -481,11 +481,10 @@ enum BaseModGroup enum BaseModType { FLAT_MOD, - PCT_MOD + PCT_MOD, + MOD_END }; -#define MOD_END (PCT_MOD+1) - enum DeathState { ALIVE = 0, @@ -776,7 +775,7 @@ enum MovementFlags2 MOVEMENTFLAG2_UNK7 = 0x00000080, MOVEMENTFLAG2_UNK8 = 0x00000100, MOVEMENTFLAG2_UNK9 = 0x00000200, - MOVEMENTFLAG2_UNK10 = 0x00000400, + MOVEMENTFLAG2_CAN_SWIM_TO_FLY_TRANS = 0x00000400, MOVEMENTFLAG2_UNK11 = 0x00000800, MOVEMENTFLAG2_UNK12 = 0x00001000, MOVEMENTFLAG2_INTERPOLATED_MOVEMENT = 0x00002000, @@ -887,15 +886,11 @@ public: class HealInfo { private: - Unit* const m_healer; - Unit* const m_target; uint32 m_heal; uint32 m_absorb; - SpellInfo const* const m_spellInfo; - SpellSchoolMask const m_schoolMask; public: - explicit HealInfo(Unit* _healer, Unit* _target, uint32 _heal, SpellInfo const* _spellInfo, SpellSchoolMask _schoolMask) - : m_healer(_healer), m_target(_target), m_heal(_heal), m_spellInfo(_spellInfo), m_schoolMask(_schoolMask) + explicit HealInfo(uint32 heal) + : m_heal(heal) { m_absorb = 0; } @@ -1483,16 +1478,16 @@ class Unit : public WorldObject void ApplyResilience(Unit const* victim, int32 * damage, bool isCrit) const; float MeleeSpellMissChance(Unit const* victim, WeaponAttackType attType, uint32 spellId) const; - SpellMissInfo MeleeSpellHitResult(Unit* victim, SpellInfo const* spell); - SpellMissInfo MagicSpellHitResult(Unit* victim, SpellInfo const* spell); - SpellMissInfo SpellHitResult(Unit* victim, SpellInfo const* spell, bool canReflect = false); + SpellMissInfo MeleeSpellHitResult(Unit* victim, SpellInfo const* spellInfo); + SpellMissInfo MagicSpellHitResult(Unit* victim, SpellInfo const* spellInfo); + SpellMissInfo SpellHitResult(Unit* victim, SpellInfo const* spellInfo, bool canReflect = false); float GetUnitDodgeChance() const; float GetUnitParryChance() const; float GetUnitBlockChance() const; float GetUnitMissChance(WeaponAttackType attType) const; float GetUnitCriticalChance(WeaponAttackType attackType, const Unit* victim) const; - int32 GetMechanicResistChance(const SpellInfo* spell) const; + int32 GetMechanicResistChance(SpellInfo const* spellInfo) const; bool CanUseAttackType(uint8 attacktype) const; virtual uint32 GetBlockPercent() const { return 30; } @@ -1989,16 +1984,17 @@ class Unit : public WorldObject void ApplySpellImmune(uint32 spellId, uint32 op, uint32 type, bool apply); void ApplySpellDispelImmunity(const SpellInfo* spellProto, DispelType type, bool apply); - virtual bool IsImmunedToSpell(SpellInfo const* spellInfo) const; - // redefined in Creature + virtual bool IsImmunedToSpell(SpellInfo const* spellInfo) const; // redefined in Creature + bool IsImmunedToDamage(SpellSchoolMask meleeSchoolMask) const; bool IsImmunedToDamage(SpellInfo const* spellInfo) const; - virtual bool IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index) const; - // redefined in Creature + virtual bool IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index) const; // redefined in Creature + static bool IsDamageReducedByArmor(SpellSchoolMask damageSchoolMask, SpellInfo const* spellInfo = NULL, uint8 effIndex = MAX_SPELL_EFFECTS); - uint32 CalcArmorReducedDamage(Unit* victim, const uint32 damage, SpellInfo const* spellInfo, WeaponAttackType attackType=MAX_ATTACK); - void CalcAbsorbResist(Unit* victim, SpellSchoolMask schoolMask, DamageEffectType damagetype, const uint32 damage, uint32 *absorb, uint32 *resist, SpellInfo const* spellInfo = NULL); - void CalcHealAbsorb(Unit* victim, const SpellInfo* spellProto, uint32 &healAmount, uint32 &absorb); + uint32 CalcArmorReducedDamage(Unit* victim, const uint32 damage, SpellInfo const* spellInfo, WeaponAttackType attackType = MAX_ATTACK); + uint32 CalcSpellResistance(Unit* victim, SpellSchoolMask schoolMask, SpellInfo const* spellInfo) const; + void CalcAbsorbResist(Unit* victim, SpellSchoolMask schoolMask, DamageEffectType damagetype, uint32 const damage, uint32* absorb, uint32* resist, SpellInfo const* spellInfo = NULL); + void CalcHealAbsorb(Unit* victim, SpellInfo const* spellInfo, uint32& healAmount, uint32& absorb); void UpdateSpeed(UnitMoveType mtype, bool forced); float GetSpeed(UnitMoveType mtype) const; @@ -2009,7 +2005,7 @@ class Unit : public WorldObject int32 CalculateSpellDamage(Unit const* target, SpellInfo const* spellProto, uint8 effect_index, int32 const* basePoints = NULL) const; int32 CalcSpellDuration(SpellInfo const* spellProto); int32 ModSpellDuration(SpellInfo const* spellProto, Unit const* target, int32 duration, bool positive, uint32 effectMask); - void ModSpellCastTime(SpellInfo const* spellProto, int32 & castTime, Spell* spell=NULL); + void ModSpellCastTime(SpellInfo const* spellProto, int32& castTime, Spell* spell = NULL); float CalculateLevelPenalty(SpellInfo const* spellProto) const; void addFollower(FollowerReference* pRef) { m_FollowingRefManager.insertFirst(pRef); } @@ -2083,6 +2079,7 @@ class Unit : public WorldObject friend class VehicleJoinEvent; bool IsAIEnabled, NeedChangeAI; + uint64 LastCharmerGUID; bool CreateVehicleKit(uint32 id, uint32 creatureEntry); void RemoveVehicleKit(); Vehicle* GetVehicleKit()const { return m_vehicleKit; } diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 038a3147ab6..cbc68d8e6cc 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -586,6 +586,10 @@ void ObjectMgr::LoadCreatureTemplateAddons() TC_LOG_ERROR(LOG_FILTER_SQL, "Creature (Entry: %u) has wrong spell %u defined in `auras` field in `creature_template_addon`.", entry, uint32(atol(*itr))); continue; } + + if (AdditionalSpellInfo->HasAura(SPELL_AURA_CONTROL_VEHICLE)) + TC_LOG_ERROR(LOG_FILTER_SQL, "Creature (Entry: %u) has SPELL_AURA_CONTROL_VEHICLE aura %u defined in `auras` field in `creature_template_addon`.", entry, uint32(atol(*itr))); + creatureAddon.auras[i++] = uint32(atol(*itr)); } @@ -600,7 +604,7 @@ void ObjectMgr::LoadCreatureTemplateAddons() if (!sEmotesStore.LookupEntry(creatureAddon.emote)) { - TC_LOG_ERROR(LOG_FILTER_SQL, "Creature (Entry: %u) has invalid emote (%u) defined in `creature_addon`.", entry, creatureAddon.emote); + TC_LOG_ERROR(LOG_FILTER_SQL, "Creature (Entry: %u) has invalid emote (%u) defined in `creature_template_addon`.", entry, creatureAddon.emote); creatureAddon.emote = 0; } @@ -959,6 +963,10 @@ void ObjectMgr::LoadCreatureAddons() TC_LOG_ERROR(LOG_FILTER_SQL, "Creature (GUID: %u) has wrong spell %u defined in `auras` field in `creature_addon`.", guid, uint32(atol(*itr))); continue; } + + if (AdditionalSpellInfo->HasAura(SPELL_AURA_CONTROL_VEHICLE)) + TC_LOG_ERROR(LOG_FILTER_SQL, "Creature (GUID: %u) has SPELL_AURA_CONTROL_VEHICLE aura %u defined in `auras` field in `creature_addon`.", guid, uint32(atol(*itr))); + creatureAddon.auras[i++] = uint32(atol(*itr)); } @@ -1750,7 +1758,7 @@ uint32 ObjectMgr::AddGOData(uint32 entry, uint32 mapId, float x, float y, float return guid; } -bool ObjectMgr::MoveCreData(uint32 guid, uint32 mapId, Position pos) +bool ObjectMgr::MoveCreData(uint32 guid, uint32 mapId, const Position& pos) { CreatureData& data = NewOrExistCreatureData(guid); if (!data.id) @@ -3552,20 +3560,16 @@ void ObjectMgr::LoadQuests() "RequiredSourceItemId1, RequiredSourceItemId2, RequiredSourceItemId3, RequiredSourceItemId4, RequiredSourceItemCount1, RequiredSourceItemCount2, RequiredSourceItemCount3, RequiredSourceItemCount4, " // 111 112 113 114 115 116 117 118 119 120 121 122 "RequiredItemId1, RequiredItemId2, RequiredItemId3, RequiredItemId4, RequiredItemId5, RequiredItemId6, RequiredItemCount1, RequiredItemCount2, RequiredItemCount3, RequiredItemCount4, RequiredItemCount5, RequiredItemCount6, " - // 123 124 125 126 127 128 129 130 131 - "RequiredSpell, RequiredSpellCast1, RequiredSpellCast2, RequiredSpellCast3, RequiredSpellCast4, ObjectiveText1, ObjectiveText2, ObjectiveText3, ObjectiveText4, " - // 132 133 134 135 136 137 138 139 - "RewardCurrencyId1, RewardCurrencyId2, RewardCurrencyId3, RewardCurrencyId4, RewardCurrencyCount1, RewardCurrencyCount2, RewardCurrencyCount3, RewardCurrencyCount4, " - // 140 141 142 143 144 145 146 147 + // 123 124 125 126 127 128 129 130 131 132 133 134 135 + "RequiredSpell, ObjectiveText1, ObjectiveText2, ObjectiveText3, ObjectiveText4, RewardCurrencyId1, RewardCurrencyId2, RewardCurrencyId3, RewardCurrencyId4, RewardCurrencyCount1, RewardCurrencyCount2, RewardCurrencyCount3, RewardCurrencyCount4, " + // 136 137 138 139 140 141 142 143 "RequiredCurrencyId1, RequiredCurrencyId2, RequiredCurrencyId3, RequiredCurrencyId4, RequiredCurrencyCount1, RequiredCurrencyCount2, RequiredCurrencyCount3, RequiredCurrencyCount4, " - // 148 149 150 151 152 153 + // 144 145 146 147 148 149 "QuestGiverTextWindow, QuestGiverTargetName, QuestTurnTextWindow, QuestTurnTargetName, SoundAccept, SoundTurnIn, " - // 154 155 156 157 158 159 160 161 162 163 + // 150 151 152 153 154 155 156 157 158 159 "DetailsEmote1, DetailsEmote2, DetailsEmote3, DetailsEmote4, DetailsEmoteDelay1, DetailsEmoteDelay2, DetailsEmoteDelay3, DetailsEmoteDelay4, EmoteOnIncomplete, EmoteOnComplete, " - // 164 165 166 167 168 169 170 171 - "OfferRewardEmote1, OfferRewardEmote2, OfferRewardEmote3, OfferRewardEmote4, OfferRewardEmoteDelay1, OfferRewardEmoteDelay2, OfferRewardEmoteDelay3, OfferRewardEmoteDelay4, " - // 173 - "WDBVerified" + // 160 161 162 163 164 165 166 167 168 + "OfferRewardEmote1, OfferRewardEmote2, OfferRewardEmote3, OfferRewardEmote4, OfferRewardEmoteDelay1, OfferRewardEmoteDelay2, OfferRewardEmoteDelay3, OfferRewardEmoteDelay4, WDBVerified" " FROM quest_template"); if (!result) { @@ -3593,7 +3597,7 @@ void ObjectMgr::LoadQuests() if (DisableMgr::IsDisabledFor(DISABLE_TYPE_QUEST, iter->first, NULL)) continue; - Quest * qinfo = iter->second; + Quest* qinfo = iter->second; // additional quest integrity checks (GO, creature_template and item_template must be loaded already) @@ -3631,12 +3635,12 @@ void ObjectMgr::LoadQuests() } } - if (qinfo->Flags & QUEST_SPECIAL_FLAGS_MONTHLY) + if (qinfo->SpecialFlags & QUEST_SPECIAL_FLAGS_MONTHLY) { - if (!(qinfo->Flags & QUEST_SPECIAL_FLAGS_REPEATABLE)) + if (!(qinfo->SpecialFlags & QUEST_SPECIAL_FLAGS_REPEATABLE)) { TC_LOG_ERROR(LOG_FILTER_SQL, "Monthly quest %u not marked as repeatable in `SpecialFlags`, added.", qinfo->GetQuestId()); - qinfo->Flags |= QUEST_SPECIAL_FLAGS_REPEATABLE; + qinfo->SpecialFlags |= QUEST_SPECIAL_FLAGS_REPEATABLE; } } @@ -3703,13 +3707,13 @@ void ObjectMgr::LoadQuests() } // RequiredRaces, can be 0/RACEMASK_ALL_PLAYABLE to allow any race if (qinfo->RequiredRaces) - { + { if (!(qinfo->RequiredRaces & RACEMASK_ALL_PLAYABLE)) { TC_LOG_ERROR(LOG_FILTER_SQL, "Quest %u does not contain any playable races in `RequiredRaces` (%u), value set to 0 (all races).", qinfo->GetQuestId(), qinfo->RequiredRaces); qinfo->RequiredRaces = 0; } - } + } // RequiredSkillId, can be 0 if (qinfo->RequiredSkillId) { @@ -3902,52 +3906,6 @@ void ObjectMgr::LoadQuests() for (uint8 j = 0; j < QUEST_OBJECTIVES_COUNT; ++j) { - uint32 id = qinfo->RequiredSpellCast[j]; - if (id) - { - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(id); - if (!spellInfo) - { - TC_LOG_ERROR(LOG_FILTER_SQL, "Quest %u has `ReqSpellCast%d` = %u but spell %u does not exist, quest can't be done.", - qinfo->GetQuestId(), j+1, id, id); - continue; - } - - if (!qinfo->RequiredNpcOrGo[j]) - { - bool found = false; - for (uint8 k = 0; k < MAX_SPELL_EFFECTS; ++k) - { - if ((spellInfo->Effects[k].Effect == SPELL_EFFECT_QUEST_COMPLETE && uint32(spellInfo->Effects[k].MiscValue) == qinfo->Id) || - spellInfo->Effects[k].Effect == SPELL_EFFECT_SEND_EVENT) - { - found = true; - break; - } - } - - if (found) - { - if (!qinfo->HasSpecialFlag(QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT)) - { - TC_LOG_ERROR(LOG_FILTER_SQL, "Spell (id: %u) have SPELL_EFFECT_QUEST_COMPLETE or SPELL_EFFECT_SEND_EVENT for quest %u and RequiredNpcOrGo%d = 0, but quest not have flag QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT. Quest flags or RequiredNpcOrGo%d must be fixed, quest modified to enable objective.", spellInfo->Id, qinfo->Id, j+1, j+1); - - // this will prevent quest completing without objective - const_cast<Quest*>(qinfo)->SetSpecialFlag(QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT); - } - } - else - { - TC_LOG_ERROR(LOG_FILTER_SQL, "Quest %u has `ReqSpellCast%d` = %u and RequiredNpcOrGo%d = 0 but spell %u does not have SPELL_EFFECT_QUEST_COMPLETE or SPELL_EFFECT_SEND_EVENT effect for this quest, quest can't be done.", - qinfo->GetQuestId(), j+1, id, j+1, id); - // no changes, quest can't be done for this requirement - } - } - } - } - - for (uint8 j = 0; j < QUEST_OBJECTIVES_COUNT; ++j) - { int32 id = qinfo->RequiredNpcOrGo[j]; if (id < 0 && !sObjectMgr->GetGameObjectTemplate(-id)) { @@ -3967,7 +3925,7 @@ void ObjectMgr::LoadQuests() { // In fact SpeakTo and Kill are quite same: either you can speak to mob:SpeakTo or you can't:Kill/Cast - qinfo->SetSpecialFlag(QUEST_SPECIAL_FLAGS_KILL_OR_CAST | QUEST_SPECIAL_FLAGS_SPEAKTO); + qinfo->SetSpecialFlag(QUEST_SPECIAL_FLAGS_KILL | QUEST_SPECIAL_FLAGS_CAST | QUEST_SPECIAL_FLAGS_SPEAKTO); if (!qinfo->RequiredNpcOrGoCount[j]) { @@ -5257,9 +5215,10 @@ void ObjectMgr::ReturnOrDeleteOldMails(bool serverUp) uint32 oldMSTime = getMSTime(); time_t curTime = time(NULL); - tm* lt = localtime(&curTime); + tm lt; + ACE_OS::localtime_r(&curTime, <); uint64 basetime(curTime); - TC_LOG_INFO(LOG_FILTER_GENERAL, "Returning mails current time: hour: %d, minute: %d, second: %d ", lt->tm_hour, lt->tm_min, lt->tm_sec); + TC_LOG_INFO(LOG_FILTER_GENERAL, "Returning mails current time: hour: %d, minute: %d, second: %d ", lt.tm_hour, lt.tm_min, lt.tm_sec); // Delete all old mails without item and without body immediately, if starting server if (!serverUp) @@ -6622,17 +6581,20 @@ void ObjectMgr::LoadPetNumber() std::string ObjectMgr::GeneratePetName(uint32 entry) { - StringVector & list0 = _petHalfName0[entry]; - StringVector & list1 = _petHalfName1[entry]; + StringVector& list0 = _petHalfName0[entry]; + StringVector& list1 = _petHalfName1[entry]; if (list0.empty() || list1.empty()) { CreatureTemplate const* cinfo = GetCreatureTemplate(entry); - const char* petname = GetPetName(cinfo->family, sWorld->GetDefaultDbcLocale()); - if (!petname) - return cinfo->Name; + if (!cinfo) + return std::string(); - return std::string(petname); + char const* petname = GetPetName(cinfo->family, sWorld->GetDefaultDbcLocale()); + if (petname) + return std::string(petname); + else + return cinfo->Name; } return *(list0.begin()+urand(0, list0.size()-1)) + *(list1.begin()+urand(0, list1.size()-1)); @@ -6695,8 +6657,8 @@ void ObjectMgr::LoadReputationRewardRate() _repRewardRateStore.clear(); // for reload case - uint32 count = 0; // 0 1 2 3 4 5 6 - QueryResult result = WorldDatabase.Query("SELECT faction, quest_rate, quest_daily_rate, quest_weekly_rate, quest_monthly_rate, creature_rate, spell_rate FROM reputation_reward_rate"); + uint32 count = 0; // 0 1 2 3 4 5 6 7 + QueryResult result = WorldDatabase.Query("SELECT faction, quest_rate, quest_daily_rate, quest_weekly_rate, quest_monthly_rate, quest_repeatable_rate, creature_rate, spell_rate FROM reputation_reward_rate"); if (!result) { TC_LOG_ERROR(LOG_FILTER_SERVER_LOADING, ">> Loaded `reputation_reward_rate`, table is empty!"); @@ -6715,8 +6677,9 @@ void ObjectMgr::LoadReputationRewardRate() repRate.questDailyRate = fields[2].GetFloat(); repRate.questWeeklyRate = fields[3].GetFloat(); repRate.questMonthlyRate = fields[4].GetFloat(); - repRate.creatureRate = fields[5].GetFloat(); - repRate.spellRate = fields[6].GetFloat(); + repRate.questRepeatableRate = fields[5].GetFloat(); + repRate.creatureRate = fields[6].GetFloat(); + repRate.spellRate = fields[7].GetFloat(); FactionEntry const* factionEntry = sFactionStore.LookupEntry(factionId); if (!factionEntry) @@ -6749,6 +6712,12 @@ void ObjectMgr::LoadReputationRewardRate() continue; } + if (repRate.questRepeatableRate < 0.0f) + { + TC_LOG_ERROR(LOG_FILTER_SQL, "Table reputation_reward_rate has quest_repeatable_rate with invalid rate %f, skipping data for faction %u", repRate.questRepeatableRate, factionId); + continue; + } + if (repRate.creatureRate < 0.0f) { TC_LOG_ERROR(LOG_FILTER_SQL, "Table reputation_reward_rate has creature_rate with invalid rate %f, skipping data for faction %u", repRate.creatureRate, factionId); @@ -7363,7 +7332,7 @@ static LanguageType GetRealmLanguageType(bool create) } } -bool isValidString(std::wstring wstr, uint32 strictMask, bool numericOrSpace, bool create = false) +bool isValidString(const std::wstring& wstr, uint32 strictMask, bool numericOrSpace, bool create = false) { if (strictMask == 0) // any language, ignore realm { @@ -7667,7 +7636,7 @@ void ObjectMgr::LoadFishingBaseSkillLevel() TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, ">> Loaded %u areas for fishing base skill level in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); } -bool ObjectMgr::CheckDeclinedNames(std::wstring w_ownname, DeclinedName const& names) +bool ObjectMgr::CheckDeclinedNames(const std::wstring& w_ownname, DeclinedName const& names) { // get main part of the name std::wstring mainpart = GetMainPartOfName(w_ownname, 0); @@ -8211,10 +8180,8 @@ void ObjectMgr::LoadGossipMenuItems() _gossipMenuItemsStore.clear(); QueryResult result = WorldDatabase.Query( - // 0 1 2 3 4 5 - "SELECT menu_id, id, option_icon, option_text, option_id, npc_option_npcflag, " - // 6 7 8 9 10 - "action_menu_id, action_poi_id, box_coded, box_money, box_text " + // 0 1 2 3 4 5 6 7 8 9 10 + "SELECT menu_id, id, option_icon, option_text, option_id, npc_option_npcflag, action_menu_id, action_poi_id, box_coded, box_money, box_text " "FROM gossip_menu_option ORDER BY menu_id, id"); if (!result) diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h index 4779700c092..99833a0a264 100644 --- a/src/server/game/Globals/ObjectMgr.h +++ b/src/server/game/Globals/ObjectMgr.h @@ -485,6 +485,7 @@ struct RepRewardRate float questDailyRate; float questWeeklyRate; float questMonthlyRate; + float questRepeatableRate; float creatureRate; // no reputation are given at all for this faction/rate type. float spellRate; }; @@ -1133,7 +1134,7 @@ class ObjectMgr void RemoveGameobjectFromGrid(uint32 guid, GameObjectData const* data); uint32 AddGOData(uint32 entry, uint32 map, float x, float y, float z, float o, uint32 spawntimedelay = 0, float rotation0 = 0, float rotation1 = 0, float rotation2 = 0, float rotation3 = 0); uint32 AddCreData(uint32 entry, uint32 team, uint32 map, float x, float y, float z, float o, uint32 spawntimedelay = 0); - bool MoveCreData(uint32 guid, uint32 map, Position pos); + bool MoveCreData(uint32 guid, uint32 map, const Position& pos); // reserved names void LoadReservedPlayersNames(); @@ -1144,7 +1145,7 @@ class ObjectMgr static PetNameInvalidReason CheckPetName(std::string const& name); static bool IsValidCharterName(std::string const& name); - static bool CheckDeclinedNames(std::wstring w_ownname, DeclinedName const& names); + static bool CheckDeclinedNames(const std::wstring& w_ownname, DeclinedName const& names); GameTele const* GetGameTele(uint32 id) const { diff --git a/src/server/game/Grids/Notifiers/GridNotifiers.h b/src/server/game/Grids/Notifiers/GridNotifiers.h index 10ccd6a77f3..813499e91d7 100644 --- a/src/server/game/Grids/Notifiers/GridNotifiers.h +++ b/src/server/game/Grids/Notifiers/GridNotifiers.h @@ -740,13 +740,12 @@ namespace Trinity class GameObjectWithDbGUIDCheck { public: - GameObjectWithDbGUIDCheck(WorldObject const& obj, uint32 db_guid) : i_obj(obj), i_db_guid(db_guid) {} + GameObjectWithDbGUIDCheck(WorldObject const& /*obj*/, uint32 db_guid) : i_db_guid(db_guid) {} bool operator()(GameObject const* go) const { return go->GetDBTableGUIDLow() == i_db_guid; } private: - WorldObject const& i_obj; uint32 i_db_guid; }; @@ -874,13 +873,12 @@ namespace Trinity class CreatureWithDbGUIDCheck { public: - CreatureWithDbGUIDCheck(WorldObject const* obj, uint32 lowguid) : i_obj(obj), i_lowguid(lowguid) {} + CreatureWithDbGUIDCheck(WorldObject const* /*obj*/, uint32 lowguid) : i_lowguid(lowguid) {} bool operator()(Creature* u) { return u->GetDBTableGUIDLow() == i_lowguid; } private: - WorldObject const* i_obj; uint32 i_lowguid; }; diff --git a/src/server/game/Grids/ObjectGridLoader.cpp b/src/server/game/Grids/ObjectGridLoader.cpp index 50a54cd7263..9d1e179db6f 100644 --- a/src/server/game/Grids/ObjectGridLoader.cpp +++ b/src/server/game/Grids/ObjectGridLoader.cpp @@ -50,7 +50,7 @@ class ObjectWorldLoader { public: explicit ObjectWorldLoader(ObjectGridLoader& gloader) - : i_cell(gloader.i_cell), i_grid(gloader.i_grid), i_map(gloader.i_map), i_corpses (0) + : i_cell(gloader.i_cell), i_map(gloader.i_map), i_corpses (0) {} void Visit(CorpseMapType &m); @@ -59,7 +59,6 @@ class ObjectWorldLoader private: Cell i_cell; - NGridType &i_grid; Map* i_map; public: uint32 i_corpses; @@ -218,8 +217,7 @@ void ObjectGridStoper::Visit(CreatureMapType &m) { iter->GetSource()->CombatStop(); iter->GetSource()->DeleteThreatList(); - if (iter->GetSource()->IsAIEnabled) - iter->GetSource()->AI()->EnterEvadeMode(); + iter->GetSource()->AI()->EnterEvadeMode(); } } } diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp index 03bfe56ac3e..c7bc229f4a9 100644 --- a/src/server/game/Groups/Group.cpp +++ b/src/server/game/Groups/Group.cpp @@ -1991,10 +1991,22 @@ void Group::ResetInstances(uint8 method, bool isRaid, Player* SendMsgTo) if (SendMsgTo) { - if (isEmpty) - SendMsgTo->SendResetInstanceSuccess(instanceSave->GetMapId()); - else + if (!isEmpty) SendMsgTo->SendResetInstanceFailed(0, instanceSave->GetMapId()); + else if (sWorld->getBoolConfig(CONFIG_INSTANCES_RESET_ANNOUNCE)) + { + if (Group* group = SendMsgTo->GetGroup()) + { + for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next()) + if (Player* player = itr->GetSource()) + player->SendResetInstanceSuccess(instanceSave->GetMapId()); + } + + else + SendMsgTo->SendResetInstanceSuccess(instanceSave->GetMapId()); + } + else + SendMsgTo->SendResetInstanceSuccess(instanceSave->GetMapId()); } if (isEmpty || method == INSTANCE_RESET_GROUP_DISBAND || method == INSTANCE_RESET_CHANGE_DIFFICULTY) diff --git a/src/server/game/Guilds/Guild.cpp b/src/server/game/Guilds/Guild.cpp index d963750094c..80d5175123d 100644 --- a/src/server/game/Guilds/Guild.cpp +++ b/src/server/game/Guilds/Guild.cpp @@ -1679,7 +1679,7 @@ void Guild::HandleSetMemberNote(WorldSession* session, std::string const& note, } } -void Guild::HandleSetRankInfo(WorldSession* session, uint8 rankId, std::string const& name, uint32 rights, uint32 moneyPerDay, GuildBankRightsAndSlotsVec rightsAndSlots) +void Guild::HandleSetRankInfo(WorldSession* session, uint8 rankId, std::string const& name, uint32 rights, uint32 moneyPerDay, const GuildBankRightsAndSlotsVec& rightsAndSlots) { // Only leader can modify ranks if (!_IsLeader(session->GetPlayer())) @@ -1859,6 +1859,8 @@ void Guild::HandleAcceptMember(WorldSession* session) void Guild::HandleLeaveMember(WorldSession* session) { Player* player = session->GetPlayer(); + bool disband = false; + // If leader is leaving if (_IsLeader(player)) { @@ -1868,7 +1870,11 @@ void Guild::HandleLeaveMember(WorldSession* session) else if (GetLevel() >= sWorld->getIntConfig(CONFIG_GUILD_UNDELETABLE_LEVEL)) SendCommandResult(session, GUILD_COMMAND_QUIT, ERR_GUILD_UNDELETABLE_DUE_TO_LEVEL); else - Disband(); // Guild is disbanded if leader leaves. + { + // Guild is disbanded if leader leaves. + Disband(); + disband = true; + } } else { @@ -1881,6 +1887,9 @@ void Guild::HandleLeaveMember(WorldSession* session) } sCalendarMgr->RemovePlayerGuildEventsAndSignups(player->GetGUID(), GetId()); + + if (disband) + delete this; } void Guild::HandleRemoveMember(WorldSession* session, uint64 guid) @@ -2063,6 +2072,9 @@ void Guild::HandleMemberDepositMoney(WorldSession* session, uint64 amount, bool bool Guild::HandleMemberWithdrawMoney(WorldSession* session, uint64 amount, bool repair) { + // clamp amount to MAX_MONEY_AMOUNT, Players can't hold more than that anyway + amount = std::min(amount, uint64(MAX_MONEY_AMOUNT)); + if (m_bankMoney < amount) // Not enough money in bank return false; @@ -2123,6 +2135,7 @@ void Guild::HandleDisband(WorldSession* session) { Disband(); TC_LOG_DEBUG(LOG_FILTER_GUILD, "Guild Successfully Disbanded"); + delete this; } } @@ -2706,7 +2719,7 @@ bool Guild::AddMember(uint64 guid, uint8 rankId) return true; } -void Guild::DeleteMember(uint64 guid, bool isDisbanding, bool isKicked) +void Guild::DeleteMember(uint64 guid, bool isDisbanding, bool isKicked, bool canDeleteGuild) { uint32 lowguid = GUID_LOPART(guid); Player* player = ObjectAccessor::FindPlayer(guid); @@ -2728,6 +2741,8 @@ void Guild::DeleteMember(uint64 guid, bool isDisbanding, bool isKicked) if (!newLeader) { Disband(); + if (canDeleteGuild) + delete this; return; } @@ -2827,10 +2842,10 @@ void Guild::SetBankTabText(uint8 tabId, std::string const& text) // Private methods void Guild::_CreateLogHolders() { - m_eventLog = new LogHolder(m_id, sWorld->getIntConfig(CONFIG_GUILD_EVENT_LOG_COUNT)); - m_newsLog = new LogHolder(m_id, sWorld->getIntConfig(CONFIG_GUILD_NEWS_LOG_COUNT)); + m_eventLog = new LogHolder(sWorld->getIntConfig(CONFIG_GUILD_EVENT_LOG_COUNT)); + m_newsLog = new LogHolder(sWorld->getIntConfig(CONFIG_GUILD_NEWS_LOG_COUNT)); for (uint8 tabId = 0; tabId <= GUILD_BANK_MAX_TABS; ++tabId) - m_bankEventLog[tabId] = new LogHolder(m_id, sWorld->getIntConfig(CONFIG_GUILD_BANK_EVENT_LOG_COUNT)); + m_bankEventLog[tabId] = new LogHolder(sWorld->getIntConfig(CONFIG_GUILD_BANK_EVENT_LOG_COUNT)); } void Guild::_CreateNewBankTab() diff --git a/src/server/game/Guilds/Guild.h b/src/server/game/Guilds/Guild.h index cf03cb58748..cd4b3fe5252 100644 --- a/src/server/game/Guilds/Guild.h +++ b/src/server/game/Guilds/Guild.h @@ -548,7 +548,7 @@ private: class LogHolder { public: - LogHolder(uint32 guildId, uint32 maxRecords) : m_guildId(guildId), m_maxRecords(maxRecords), m_nextGUID(uint32(GUILD_EVENT_LOG_GUID_UNDEFINED)) { } + LogHolder(uint32 maxRecords) : m_maxRecords(maxRecords), m_nextGUID(uint32(GUILD_EVENT_LOG_GUID_UNDEFINED)) { } ~LogHolder(); uint8 GetSize() const { return uint8(m_log.size()); } @@ -565,7 +565,6 @@ private: private: GuildLog m_log; - uint32 m_guildId; uint32 m_maxRecords; uint32 m_nextGUID; }; @@ -779,7 +778,7 @@ public: void HandleSetNewGuildMaster(WorldSession* session, std::string const& name); void HandleSetBankTabInfo(WorldSession* session, uint8 tabId, std::string const& name, std::string const& icon); void HandleSetMemberNote(WorldSession* session, std::string const& note, uint64 guid, bool isPublic); - void HandleSetRankInfo(WorldSession* session, uint8 rankId, std::string const& name, uint32 rights, uint32 moneyPerDay, GuildBankRightsAndSlotsVec rightsAndSlots); + void HandleSetRankInfo(WorldSession* session, uint8 rankId, std::string const& name, uint32 rights, uint32 moneyPerDay, GuildBankRightsAndSlotsVec const& rightsAndSlots); void HandleBuyBankTab(WorldSession* session, uint8 tabId); void HandleInviteMember(WorldSession* session, std::string const& name); void HandleAcceptMember(WorldSession* session); @@ -843,7 +842,7 @@ public: // Members // Adds member to guild. If rankId == GUILD_RANK_NONE, lowest rank is assigned. bool AddMember(uint64 guid, uint8 rankId = GUILD_RANK_NONE); - void DeleteMember(uint64 guid, bool isDisbanding = false, bool isKicked = false); + void DeleteMember(uint64 guid, bool isDisbanding = false, bool isKicked = false, bool canDeleteGuild = false); bool ChangeMemberRank(uint64 guid, uint8 newRank); bool IsMember(uint64 guid) const; uint32 GetMembersCount() { return m_members.size(); } diff --git a/src/server/game/Guilds/GuildMgr.cpp b/src/server/game/Guilds/GuildMgr.cpp index f6a3304c0ec..0d90c34b860 100644 --- a/src/server/game/Guilds/GuildMgr.cpp +++ b/src/server/game/Guilds/GuildMgr.cpp @@ -451,20 +451,13 @@ void GuildMgr::LoadGuilds() TC_LOG_INFO(LOG_FILTER_GENERAL, "Validating data of loaded guilds..."); { uint32 oldMSTime = getMSTime(); - std::set<Guild*> rm; // temporary storage to avoid modifying GuildStore with RemoveGuild() while iterating - for (GuildContainer::iterator itr = GuildStore.begin(); itr != GuildStore.end(); ++itr) + for (GuildContainer::iterator itr = GuildStore.begin(); itr != GuildStore.end();) { Guild* guild = itr->second; + ++itr; if (guild && !guild->Validate()) - rm.insert(guild); - } - - for (std::set<Guild*>::iterator itr = rm.begin(); itr != rm.end(); ++itr) - { - Guild* guild = *itr; - RemoveGuild(guild->GetId()); - delete guild; + delete guild; } TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, ">> Validated data of loaded guilds in %u ms", GetMSTimeDiffToNow(oldMSTime)); diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index 15676d17c43..81bf31dcf3a 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -245,7 +245,10 @@ void WorldSession::HandleCharEnum(PreparedQueryResult result) Player::BuildEnumData(result, &dataBuffer, &bitBuffer); - _legitCharacters.insert(guidLow); + // Do not allow banned characters to log in + if (!(*result)[20].GetUInt32()) + _legitCharacters.insert(guidLow); + if (!sWorld->HasCharacterNameData(guidLow)) // This can happen if characters are inserted into the database manually. Core hasn't loaded name data yet. sWorld->AddCharacterNameData(guidLow, (*result)[1].GetString(), (*result)[4].GetUInt8(), (*result)[2].GetUInt8(), (*result)[3].GetUInt8(), (*result)[7].GetUInt8()); } while (result->NextRow()); @@ -265,6 +268,8 @@ void WorldSession::HandleCharEnum(PreparedQueryResult result) void WorldSession::HandleCharEnumOpcode(WorldPacket & /*recvData*/) { + AntiDOS.AllowOpcode(CMSG_CHAR_ENUM, false); + // remove expired bans PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_EXPIRED_BANS); CharacterDatabase.Execute(stmt); @@ -701,6 +706,7 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, Characte data << uint8(CHAR_CREATE_SUCCESS); SendPacket(&data); + AntiDOS.AllowOpcode(CMSG_CHAR_ENUM, true); std::string IP_str = GetRemoteAddress(); TC_LOG_INFO(LOG_FILTER_CHARACTER, "Account: %d (IP: %s) Create Character:[%s] (GUID: %u)", GetAccountId(), IP_str.c_str(), createInfo->Name.c_str(), newChar.GetGUIDLow()); sScriptMgr->OnPlayerCreate(&newChar); @@ -778,6 +784,8 @@ void WorldSession::HandleCharDeleteOpcode(WorldPacket& recvData) WorldPacket data(SMSG_CHAR_DELETE, 1); data << uint8(CHAR_DELETE_SUCCESS); SendPacket(&data); + + AntiDOS.AllowOpcode(CMSG_CHAR_ENUM, true); } void WorldSession::HandlePlayerLoginOpcode(WorldPacket& recvData) @@ -1271,6 +1279,7 @@ void WorldSession::HandleCharRenameOpcode(WorldPacket& recvData) void WorldSession::HandleChangePlayerNameOpcodeCallBack(PreparedQueryResult result, std::string const& newName) { + AntiDOS.AllowOpcode(CMSG_CHAR_ENUM, true); if (!result) { WorldPacket data(SMSG_CHAR_RENAME, 1); @@ -1520,6 +1529,9 @@ void WorldSession::HandleCharCustomize(WorldPacket& recvData) PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_AT_LOGIN); stmt->setUInt32(0, GUID_LOPART(guid)); + // TODO: Make async with callback + // TODO 2: Allow opcode at end of callback + AntiDOS.AllowOpcode(CMSG_CHAR_ENUM, true); PreparedQueryResult result = CharacterDatabase.Query(stmt); if (!result) @@ -1773,6 +1785,8 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recvData) uint8 playerClass = nameData->m_class; uint8 level = nameData->m_level; + // TO Do: Make async and allow opcode on callback + AntiDOS.AllowOpcode(CMSG_CHAR_ENUM, true); PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_AT_LOGIN_TITLES); stmt->setUInt32(0, lowGuid); PreparedQueryResult result = CharacterDatabase.Query(stmt); @@ -2018,7 +2032,7 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recvData) PreparedQueryResult result = CharacterDatabase.Query(stmt); if (result) if (Guild* guild = sGuildMgr->GetGuildById((result->Fetch()[0]).GetUInt32())) - guild->DeleteMember(MAKE_NEW_GUID(lowGuid, 0, HIGHGUID_PLAYER)); + guild->DeleteMember(MAKE_NEW_GUID(lowGuid, 0, HIGHGUID_PLAYER), false, false, true); } if (!HasPermission(RBAC_PERM_TWO_SIDE_ADD_FRIEND)) diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp index 5ad39188fbd..dc3679e021f 100644 --- a/src/server/game/Handlers/MiscHandler.cpp +++ b/src/server/game/Handlers/MiscHandler.cpp @@ -1680,9 +1680,13 @@ void WorldSession::HandleRequestPetInfoOpcode(WorldPacket& /*recvData */) void WorldSession::HandleSetTaxiBenchmarkOpcode(WorldPacket& recvData) { + TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: CMSG_SET_TAXI_BENCHMARK_MODE"); + uint8 mode; recvData >> mode; + mode ? _player->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_TAXI_BENCHMARK) : _player->RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_TAXI_BENCHMARK); + TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "Client used \"/timetest %d\" command", mode); } diff --git a/src/server/game/Handlers/PetHandler.cpp b/src/server/game/Handlers/PetHandler.cpp index 2e7ca070924..d65653ae242 100644 --- a/src/server/game/Handlers/PetHandler.cpp +++ b/src/server/game/Handlers/PetHandler.cpp @@ -647,7 +647,9 @@ void WorldSession::HandlePetRename(WorldPacket& recvData) } std::wstring wname; - Utf8toWStr(name, wname); + if (!Utf8toWStr(name, wname)) + return; + if (!ObjectMgr::CheckDeclinedNames(wname, declinedname)) { SendPetNameInvalid(PET_NAME_DECLENSION_DOESNT_MATCH_BASE_NAME, name, &declinedname); diff --git a/src/server/game/Instances/InstanceSaveMgr.cpp b/src/server/game/Instances/InstanceSaveMgr.cpp index a422fd8531c..6370eda6568 100644 --- a/src/server/game/Instances/InstanceSaveMgr.cpp +++ b/src/server/game/Instances/InstanceSaveMgr.cpp @@ -156,14 +156,14 @@ void InstanceSaveManager::RemoveInstanceSave(uint32 InstanceId) CharacterDatabase.Execute(stmt); } - delete itr->second; + itr->second->SetToDelete(true); m_instanceSaveById.erase(itr); } } InstanceSave::InstanceSave(uint16 MapId, uint32 InstanceId, Difficulty difficulty, time_t resetTime, bool canReset) : m_resetTime(resetTime), m_instanceid(InstanceId), m_mapid(MapId), - m_difficulty(difficulty), m_canReset(canReset) + m_difficulty(difficulty), m_canReset(canReset), m_toDelete(false) { } diff --git a/src/server/game/Instances/InstanceSaveMgr.h b/src/server/game/Instances/InstanceSaveMgr.h index c5dcaf32463..e3717a934c3 100644 --- a/src/server/game/Instances/InstanceSaveMgr.h +++ b/src/server/game/Instances/InstanceSaveMgr.h @@ -81,10 +81,29 @@ class InstanceSave /* online players bound to the instance (perm/solo) does not include the members of the group unless they have permanent saves */ void AddPlayer(Player* player) { TRINITY_GUARD(ACE_Thread_Mutex, _lock); m_playerList.push_back(player); } - bool RemovePlayer(Player* player) { TRINITY_GUARD(ACE_Thread_Mutex, _lock); m_playerList.remove(player); return UnloadIfEmpty(); } + bool RemovePlayer(Player* player) + { + _lock.acquire(); + m_playerList.remove(player); + bool isStillValid = UnloadIfEmpty(); + _lock.release(); + + //delete here if needed, after releasing the lock + if (m_toDelete) + delete this; + + return isStillValid; + } /* all groups bound to the instance */ void AddGroup(Group* group) { m_groupList.push_back(group); } - bool RemoveGroup(Group* group) { m_groupList.remove(group); return UnloadIfEmpty(); } + bool RemoveGroup(Group* group) + { + m_groupList.remove(group); + bool isStillValid = UnloadIfEmpty(); + if (m_toDelete) + delete this; + return isStillValid; + } /* instances cannot be reset (except at the global reset time) if there are players permanently bound to it @@ -96,6 +115,12 @@ class InstanceSave but that would depend on a lot of things that can easily change in future */ Difficulty GetDifficulty() const { return m_difficulty; } + /* used to flag the InstanceSave as to be deleted, so the caller can delete it */ + void SetToDelete(bool toDelete) + { + m_toDelete = toDelete; + } + typedef std::list<Player*> PlayerListType; typedef std::list<Group*> GroupListType; private: @@ -110,6 +135,7 @@ class InstanceSave uint32 m_mapid; Difficulty m_difficulty; bool m_canReset; + bool m_toDelete; ACE_Thread_Mutex _lock; }; diff --git a/src/server/game/Instances/InstanceScript.h b/src/server/game/Instances/InstanceScript.h index 2d77f6792c6..44c149ba9ac 100644 --- a/src/server/game/Instances/InstanceScript.h +++ b/src/server/game/Instances/InstanceScript.h @@ -22,8 +22,6 @@ #include "ZoneScript.h" #include "World.h" #include "ObjectMgr.h" -//#include "GameObject.h" -//#include "Map.h" #define OUT_SAVE_INST_DATA TC_LOG_DEBUG(LOG_FILTER_TSCR, "Saving Instance Data for Instance %s (Map %d, Instance Id %d)", instance->GetMapName(), instance->GetId(), instance->GetInstanceId()) #define OUT_SAVE_INST_DATA_COMPLETE TC_LOG_DEBUG(LOG_FILTER_TSCR, "Saving Instance Data for Instance %s (Map %d, Instance Id %d) completed.", instance->GetMapName(), instance->GetId(), instance->GetInstanceId()) @@ -241,4 +239,16 @@ class InstanceScript : public ZoneScript MinionInfoMap minions; uint32 completedEncounters; // completed encounter mask, bit indexes are DungeonEncounter.dbc boss numbers, used for packets }; -#endif + +template<class AI, class T> +AI* GetInstanceAI(T* obj, char const* scriptName) +{ + if (InstanceMap* instance = obj->GetMap()->ToInstanceMap()) + if (instance->GetInstanceScript()) + if (instance->GetScriptId() == sObjectMgr->GetScriptId(scriptName)) + return new AI(obj); + + return NULL; +} + +#endif // TRINITY_INSTANCE_DATA_H diff --git a/src/server/game/Loot/LootMgr.cpp b/src/server/game/Loot/LootMgr.cpp index 75655dca170..037127d160e 100644 --- a/src/server/game/Loot/LootMgr.cpp +++ b/src/server/game/Loot/LootMgr.cpp @@ -1253,7 +1253,7 @@ void LootTemplate::AddEntry(LootStoreItem* item) Entries.push_back(item); } -void LootTemplate::CopyConditions(ConditionList conditions) +void LootTemplate::CopyConditions(const ConditionList& conditions) { for (LootStoreItemList::iterator i = Entries.begin(); i != Entries.end(); ++i) (*i)->conditions.clear(); diff --git a/src/server/game/Loot/LootMgr.h b/src/server/game/Loot/LootMgr.h index d338f6f503b..c2f74aab701 100644 --- a/src/server/game/Loot/LootMgr.h +++ b/src/server/game/Loot/LootMgr.h @@ -228,7 +228,7 @@ class LootTemplate void AddEntry(LootStoreItem* item); // Rolls for every item in the template and adds the rolled items the the loot void Process(Loot& loot, bool rate, uint16 lootMode, uint8 groupId = 0) const; - void CopyConditions(ConditionList conditions); + void CopyConditions(const ConditionList& conditions); void CopyConditions(LootItem* li) const; // True if template includes at least 1 quest drop entry diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index 56330c503de..1fd762e7446 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -2114,6 +2114,10 @@ void Map::AddObjectToRemoveList(WorldObject* obj) void Map::AddObjectToSwitchList(WorldObject* obj, bool on) { ASSERT(obj->GetMapId() == GetId() && obj->GetInstanceId() == GetInstanceId()); + // i_objectsToSwitch is iterated only in Map::RemoveAllObjectsInRemoveList() and it uses + // the contained objects only if GetTypeId() == TYPEID_UNIT , so we can return in all other cases + if (obj->GetTypeId() != TYPEID_UNIT) + return; std::map<WorldObject*, bool>::iterator itr = i_objectsToSwitch.find(obj); if (itr == i_objectsToSwitch.end()) @@ -2408,6 +2412,8 @@ bool InstanceMap::AddPlayerToMap(Player* player) mapSave = sInstanceSaveMgr->AddInstanceSave(GetId(), GetInstanceId(), Difficulty(GetSpawnMode()), 0, true); } + ASSERT(mapSave); + // check for existing instance binds InstancePlayerBind* playerBind = player->GetBoundInstance(GetId(), Difficulty(GetSpawnMode())); if (playerBind && playerBind->perm) @@ -2442,10 +2448,7 @@ bool InstanceMap::AddPlayerToMap(Player* player) if (groupBind->save != mapSave) { TC_LOG_ERROR(LOG_FILTER_MAPS, "InstanceMap::Add: player %s(%d) is being put into instance %d, %d, %d but he is in group %d which is bound to instance %d, %d, %d!", player->GetName().c_str(), player->GetGUIDLow(), mapSave->GetMapId(), mapSave->GetInstanceId(), mapSave->GetDifficulty(), GUID_LOPART(group->GetLeaderGUID()), groupBind->save->GetMapId(), groupBind->save->GetInstanceId(), groupBind->save->GetDifficulty()); - if (mapSave) - TC_LOG_ERROR(LOG_FILTER_MAPS, "MapSave players: %d, group count: %d", mapSave->GetPlayerCount(), mapSave->GetGroupCount()); - else - TC_LOG_ERROR(LOG_FILTER_MAPS, "MapSave NULL"); + TC_LOG_ERROR(LOG_FILTER_MAPS, "MapSave players: %d, group count: %d", mapSave->GetPlayerCount(), mapSave->GetGroupCount()); if (groupBind->save) TC_LOG_ERROR(LOG_FILTER_MAPS, "GroupBind save players: %d, group count: %d", groupBind->save->GetPlayerCount(), groupBind->save->GetGroupCount()); else diff --git a/src/server/game/Miscellaneous/Language.h b/src/server/game/Miscellaneous/Language.h index efc6423bb5c..c30795de475 100644 --- a/src/server/game/Miscellaneous/Language.h +++ b/src/server/game/Miscellaneous/Language.h @@ -819,6 +819,7 @@ enum TrinityStrings LANG_PINFO_ACC_ACCOUNT = 714, LANG_PINFO_ACC_LASTLOGIN = 716, LANG_PINFO_ACC_OS = 749, + LANG_PINFO_ACC_REGMAILS = 879, LANG_PINFO_ACC_IP = 752, LANG_PINFO_CHR_LEVEL_LOW = 843, LANG_PINFO_CHR_RACE = 844, @@ -852,7 +853,17 @@ enum TrinityStrings LANG_ARENA_INFO_MEMBERS = 869, LANG_ARENA_LOOKUP = 870, // = 871, see LANG_PINFO_CHR_LEVEL_HIGH - // Room for in-game strings 872-999 not used + LANG_COMMAND_WRONGEMAIL = 872, + LANG_NEW_EMAILS_NOT_MATCH = 873, + LANG_COMMAND_EMAIL = 874, + LANG_EMAIL_TOO_LONG = 875, + LANG_COMMAND_NOTCHANGEEMAIL = 876, + LANG_OLD_EMAIL_IS_NEW_EMAIL = 877, + LANG_COMMAND_EMAIL_OUTPUT = 878, + // = 879, see LANG_PINFO_CHR_REGMAILS + LANG_ACCOUNT_SEC_TYPE = 880, + LANG_RBAC_EMAIL_REQUIRED = 881, + // Room for in-game strings 882-999 not used // Level 4 (CLI only commands) LANG_COMMAND_EXIT = 1000, diff --git a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp index 1e275b0be9f..31da239670b 100755 --- a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp @@ -218,6 +218,8 @@ void FlightPathMovementGenerator::DoFinalize(Player* player) // when client side flight end early in comparison server side player->StopMoving(); } + + player->RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_TAXI_BENCHMARK); } #define PLAYER_FLIGHT_SPEED 32.0f diff --git a/src/server/game/Movement/MovementStructures.cpp b/src/server/game/Movement/MovementStructures.cpp index a0f70c7b96c..db305e52454 100644 --- a/src/server/game/Movement/MovementStructures.cpp +++ b/src/server/game/Movement/MovementStructures.cpp @@ -54,8 +54,8 @@ MovementStatusElements const PlayerMove[] = MSEHasPitch, MSEGuidByte5, MSEFallHorizontalSpeed, - MSEFallCosAngle, MSEFallSinAngle, + MSEFallCosAngle, MSEFallVerticalSpeed, MSEFallTime, MSESplineElevation, @@ -153,9 +153,9 @@ MovementStatusElements const MovementFallLand[] = MSETransportGuidByte2, MSEFallVerticalSpeed, MSEFallTime, - MSEFallCosAngle, - MSEFallHorizontalSpeed, MSEFallSinAngle, + MSEFallHorizontalSpeed, + MSEFallCosAngle, MSESplineElevation, MSETimestamp, MSEPitch, @@ -227,8 +227,8 @@ MovementStatusElements const MovementHeartBeat[] = MSEFallVerticalSpeed, MSEFallTime, MSEFallHorizontalSpeed, - MSEFallSinAngle, MSEFallCosAngle, + MSEFallSinAngle, MSEPitch, MSESplineElevation, MSETimestamp, @@ -297,8 +297,8 @@ MovementStatusElements const MovementJump[] = MSETransportGuidByte5, MSEPitch, MSETimestamp, - MSEFallCosAngle, MSEFallSinAngle, + MSEFallCosAngle, MSEFallHorizontalSpeed, MSEFallVerticalSpeed, MSEFallTime, @@ -368,8 +368,8 @@ MovementStatusElements const MovementSetFacing[] = MSETransportTime, MSETransportGuidByte7, MSEFallHorizontalSpeed, - MSEFallSinAngle, MSEFallCosAngle, + MSEFallSinAngle, MSEFallTime, MSEFallVerticalSpeed, MSESplineElevation, @@ -442,8 +442,8 @@ MovementStatusElements const MovementSetPitch[] = MSEFallVerticalSpeed, MSEFallTime, MSEFallHorizontalSpeed, - MSEFallCosAngle, MSEFallSinAngle, + MSEFallCosAngle, MSEPitch, MSESplineElevation, MSETimestamp, @@ -514,8 +514,8 @@ MovementStatusElements const MovementStartBackward[] = MSEPitch, MSETimestamp, MSEFallHorizontalSpeed, - MSEFallSinAngle, MSEFallCosAngle, + MSEFallSinAngle, MSEFallVerticalSpeed, MSEFallTime, MSEOrientation, @@ -569,8 +569,8 @@ MovementStatusElements const MovementStartForward[] = MSEGuidByte0, MSEFallVerticalSpeed, MSEFallHorizontalSpeed, - MSEFallCosAngle, MSEFallSinAngle, + MSEFallCosAngle, MSEFallTime, MSETransportGuidByte3, MSETransportPositionY, @@ -640,9 +640,9 @@ MovementStatusElements const MovementStartStrafeLeft[] = MSEGuidByte7, MSEGuidByte4, MSEGuidByte5, - MSEFallSinAngle, - MSEFallHorizontalSpeed, MSEFallCosAngle, + MSEFallHorizontalSpeed, + MSEFallSinAngle, MSEFallTime, MSEFallVerticalSpeed, MSETransportSeat, @@ -730,8 +730,8 @@ MovementStatusElements const MovementStartStrafeRight[] = MSETransportGuidByte3, MSEPitch, MSEOrientation, - MSEFallCosAngle, MSEFallSinAngle, + MSEFallCosAngle, MSEFallHorizontalSpeed, MSEFallTime, MSEFallVerticalSpeed, @@ -784,8 +784,8 @@ MovementStatusElements const MovementStartTurnLeft[] = MSEGuidByte3, MSEGuidByte2, MSEGuidByte1, - MSEFallSinAngle, MSEFallCosAngle, + MSEFallSinAngle, MSEFallHorizontalSpeed, MSEFallVerticalSpeed, MSEFallTime, @@ -873,8 +873,8 @@ MovementStatusElements const MovementStartTurnRight[] = MSETransportGuidByte3, MSETransportTime2, MSEFallHorizontalSpeed, - MSEFallSinAngle, MSEFallCosAngle, + MSEFallSinAngle, MSEFallTime, MSEFallVerticalSpeed, MSEPitch, @@ -948,8 +948,8 @@ MovementStatusElements const MovementStop[] = MSEOrientation, MSEPitch, MSESplineElevation, - MSEFallCosAngle, MSEFallSinAngle, + MSEFallCosAngle, MSEFallHorizontalSpeed, MSEFallVerticalSpeed, MSEFallTime, @@ -1016,9 +1016,9 @@ MovementStatusElements const MovementStopStrafe[] = MSETransportPositionY, MSETransportTime2, MSETransportGuidByte7, - MSEFallCosAngle, - MSEFallHorizontalSpeed, MSEFallSinAngle, + MSEFallHorizontalSpeed, + MSEFallCosAngle, MSEFallTime, MSEFallVerticalSpeed, MSESplineElevation, @@ -1091,8 +1091,8 @@ MovementStatusElements const MovementStopTurn[] = MSETransportGuidByte6, MSEFallTime, MSEFallHorizontalSpeed, - MSEFallCosAngle, MSEFallSinAngle, + MSEFallCosAngle, MSEFallVerticalSpeed, MSETimestamp, MSEPitch, @@ -1160,8 +1160,8 @@ MovementStatusElements const MovementStartAscend[] = MSETransportGuidByte0, MSETransportGuidByte1, MSETransportPositionX, - MSEFallCosAngle, MSEFallSinAngle, + MSEFallCosAngle, MSEFallHorizontalSpeed, MSEFallTime, MSEFallVerticalSpeed, @@ -1234,8 +1234,8 @@ MovementStatusElements const MovementStartDescend[] = MSETransportOrientation, MSETransportGuidByte0, MSEFallTime, - MSEFallSinAngle, MSEFallCosAngle, + MSEFallSinAngle, MSEFallHorizontalSpeed, MSEFallVerticalSpeed, MSETimestamp, @@ -1305,9 +1305,9 @@ MovementStatusElements const MovementStartSwim[] = MSETransportGuidByte7, MSETransportGuidByte0, MSETransportSeat, - MSEFallCosAngle, - MSEFallHorizontalSpeed, MSEFallSinAngle, + MSEFallHorizontalSpeed, + MSEFallCosAngle, MSEFallVerticalSpeed, MSEFallTime, MSEOrientation, @@ -1377,9 +1377,9 @@ MovementStatusElements const MovementStopSwim[] = MSETransportGuidByte0, MSETransportOrientation, MSEFallVerticalSpeed, - MSEFallCosAngle, - MSEFallHorizontalSpeed, MSEFallSinAngle, + MSEFallHorizontalSpeed, + MSEFallCosAngle, MSEFallTime, MSETimestamp, MSEPitch, @@ -1450,8 +1450,8 @@ MovementStatusElements const MovementStopAscend[] = MSETransportPositionZ, MSEFallTime, MSEFallVerticalSpeed, - MSEFallCosAngle, MSEFallSinAngle, + MSEFallCosAngle, MSEFallHorizontalSpeed, MSEPitch, MSESplineElevation, @@ -1506,8 +1506,8 @@ MovementStatusElements const MovementStopPitch[] = MSEGuidByte2, MSETimestamp, MSEFallHorizontalSpeed, - MSEFallSinAngle, MSEFallCosAngle, + MSEFallSinAngle, MSEFallVerticalSpeed, MSEFallTime, MSETransportGuidByte5, @@ -1592,9 +1592,9 @@ MovementStatusElements const MovementStartPitchDown[] = MSETransportGuidByte2, MSETransportGuidByte7, MSETransportOrientation, - MSEFallSinAngle, - MSEFallHorizontalSpeed, MSEFallCosAngle, + MSEFallHorizontalSpeed, + MSEFallSinAngle, MSEFallVerticalSpeed, MSEFallTime, MSEPitch, @@ -1665,8 +1665,8 @@ MovementStatusElements const MovementStartPitchUp[] = MSETransportPositionY, MSETransportGuidByte4, MSEFallTime, - MSEFallCosAngle, MSEFallSinAngle, + MSEFallCosAngle, MSEFallHorizontalSpeed, MSEFallVerticalSpeed, MSEOrientation, @@ -1699,7 +1699,6 @@ MovementStatusElements const MoveChngTransport[]= MSEHasFallData, MSEHasMovementFlags, MSEHasMovementFlags2, - MSEHasTransportGuidByte3, MSEHasTransportTime3, MSEHasTransportGuidByte4, @@ -1710,11 +1709,9 @@ MovementStatusElements const MoveChngTransport[]= MSEHasTransportGuidByte0, MSEHasTransportGuidByte7, MSEHasTransportGuidByte5, - MSEMovementFlags, MSEMovementFlags2, MSEHasFallDirection, - MSEGuidByte7, MSEGuidByte5, MSEGuidByte1, @@ -1723,7 +1720,6 @@ MovementStatusElements const MoveChngTransport[]= MSEGuidByte4, MSEGuidByte0, MSEGuidByte3, - MSETransportPositionY, MSETransportSeat, MSETransportGuidByte1, @@ -1740,13 +1736,11 @@ MovementStatusElements const MoveChngTransport[]= MSETransportGuidByte4, MSETransportOrientation, MSETransportTime2, - MSEFallTime, MSEFallHorizontalSpeed, - MSEFallCosAngle, MSEFallSinAngle, + MSEFallCosAngle, MSEFallVerticalSpeed, - MSEOrientation, MSEPitch, MSESplineElevation, @@ -1803,8 +1797,8 @@ MovementStatusElements const MoveSplineDone[] = MSEGuidByte3, MSEFallVerticalSpeed, - MSEFallSinAngle, MSEFallCosAngle, + MSEFallSinAngle, MSEFallHorizontalSpeed, MSEFallTime, @@ -1882,8 +1876,8 @@ MovementStatusElements const MoveNotActiveMover[] = MSEGuidByte3, MSEFallVerticalSpeed, - MSEFallCosAngle, MSEFallSinAngle, + MSEFallCosAngle, MSEFallHorizontalSpeed, MSEFallTime, @@ -1981,8 +1975,8 @@ MovementStatusElements const DismissControlledVehicle[] = MSEFallTime, MSEFallHorizontalSpeed, - MSEFallSinAngle, MSEFallCosAngle, + MSEFallSinAngle, MSEFallVerticalSpeed, MSEOrientation, @@ -2061,8 +2055,8 @@ MovementStatusElements const MoveUpdateTeleport[] = MSEFallTime, MSEFallHorizontalSpeed, - MSEFallSinAngle, MSEFallCosAngle, + MSEFallSinAngle, MSEFallVerticalSpeed, MSEGuidByte5, @@ -2134,9 +2128,9 @@ MovementStatusElements const MovementSetRunMode[] = MSETransportGuidByte0, MSETransportPositionY, MSETransportGuidByte6, - MSEFallSinAngle, - MSEFallHorizontalSpeed, MSEFallCosAngle, + MSEFallHorizontalSpeed, + MSEFallSinAngle, MSEFallTime, MSEFallVerticalSpeed, MSESplineElevation, @@ -2205,9 +2199,9 @@ MovementStatusElements const MovementSetWalkMode[] = MSETransportGuidByte7, MSETransportPositionY, MSETransportGuidByte1, - MSEFallCosAngle, - MSEFallHorizontalSpeed, MSEFallSinAngle, + MSEFallHorizontalSpeed, + MSEFallCosAngle, MSEFallVerticalSpeed, MSEFallTime, MSESplineElevation, @@ -2278,8 +2272,8 @@ MovementStatusElements const MovementSetCanFly[] = MSETransportGuidByte6, MSETransportTime3, MSESplineElevation, - MSEFallCosAngle, MSEFallSinAngle, + MSEFallCosAngle, MSEFallHorizontalSpeed, MSEFallVerticalSpeed, MSEFallTime, @@ -2336,8 +2330,8 @@ MovementStatusElements const MovementSetCanTransitionBetweenSwimAndFlyAck[] = MSEGuidByte6, MSEFallTime, MSEFallHorizontalSpeed, - MSEFallSinAngle, MSEFallCosAngle, + MSEFallSinAngle, MSEFallVerticalSpeed, MSETransportPositionY, MSETransportPositionZ, @@ -2400,9 +2394,9 @@ MovementStatusElements const MovementUpdateSwimSpeed[] = MSETransportGuidByte3, MSETransportGuidByte5, MSEPositionX, - MSEFallCosAngle, - MSEFallHorizontalSpeed, MSEFallSinAngle, + MSEFallHorizontalSpeed, + MSEFallCosAngle, MSEFallTime, MSEFallVerticalSpeed, MSEGuidByte7, @@ -2476,9 +2470,9 @@ MovementStatusElements const MovementUpdateRunSpeed[] = MSETransportTime3, MSETransportPositionZ, MSETimestamp, - MSEFallSinAngle, - MSEFallHorizontalSpeed, MSEFallCosAngle, + MSEFallHorizontalSpeed, + MSEFallSinAngle, MSEFallVerticalSpeed, MSEFallTime, MSEPitch, @@ -2539,9 +2533,9 @@ MovementStatusElements const MovementUpdateFlightSpeed[] = MSETransportGuidByte1, MSETransportSeat, MSETransportPositionX, - MSEFallCosAngle, - MSEFallHorizontalSpeed, MSEFallSinAngle, + MSEFallHorizontalSpeed, + MSEFallCosAngle, MSEFallVerticalSpeed, MSEFallTime, MSEGuidByte1, @@ -2599,8 +2593,8 @@ MovementStatusElements const MovementUpdateCollisionHeight[] = MSETransportSeat, MSEPitch, MSEGuidByte6, - MSEFallCosAngle, MSEFallSinAngle, + MSEFallCosAngle, MSEFallHorizontalSpeed, MSEFallVerticalSpeed, MSEFallTime, @@ -2679,8 +2673,8 @@ MovementStatusElements const MovementForceRunSpeedChangeAck[] = MSETransportGuidByte4, MSEFallVerticalSpeed, MSEFallHorizontalSpeed, - MSEFallCosAngle, MSEFallSinAngle, + MSEFallCosAngle, MSEFallTime, MSESplineElevation, MSEPitch, @@ -2755,8 +2749,8 @@ MovementStatusElements const MovementSetCollisionHeightAck[] = MSETransportPositionZ, MSEFallVerticalSpeed, MSEFallTime, - MSEFallSinAngle, MSEFallCosAngle, + MSEFallSinAngle, MSEFallHorizontalSpeed, MSETimestamp, MSESplineElevation, @@ -2829,8 +2823,8 @@ MovementStatusElements const MovementForceFlightSpeedChangeAck[] = MSETransportPositionY, MSETimestamp, MSESplineElevation, - MSEFallCosAngle, MSEFallSinAngle, + MSEFallCosAngle, MSEFallHorizontalSpeed, MSEFallTime, MSEFallVerticalSpeed, @@ -2901,9 +2895,9 @@ MovementStatusElements const MovementSetCanFlyAck[] = MSETransportGuidByte0, MSETransportGuidByte4, MSEFallTime, - MSEFallCosAngle, - MSEFallHorizontalSpeed, MSEFallSinAngle, + MSEFallHorizontalSpeed, + MSEFallCosAngle, MSEFallVerticalSpeed, MSEPitch, MSEOrientation, @@ -2975,8 +2969,8 @@ MovementStatusElements const MovementForceSwimSpeedChangeAck[] = MSETransportGuidByte1, MSETransportGuidByte4, MSEFallTime, - MSEFallCosAngle, MSEFallSinAngle, + MSEFallCosAngle, MSEFallHorizontalSpeed, MSEFallVerticalSpeed, MSEOrientation, @@ -3033,9 +3027,9 @@ MovementStatusElements const MovementForceWalkSpeedChangeAck[] = MSEGuidByte4, MSEGuidByte0, MSEFallVerticalSpeed, - MSEFallSinAngle, - MSEFallHorizontalSpeed, MSEFallCosAngle, + MSEFallHorizontalSpeed, + MSEFallSinAngle, MSEFallTime, MSETransportPositionZ, MSETransportGuidByte7, @@ -3108,8 +3102,8 @@ MovementStatusElements const MovementForceRunBackSpeedChangeAck[] = MSEGuidByte1, MSEFallTime, MSEFallHorizontalSpeed, - MSEFallCosAngle, MSEFallSinAngle, + MSEFallCosAngle, MSEFallVerticalSpeed, MSETransportGuidByte5, MSETransportSeat, @@ -3174,8 +3168,8 @@ MovementStatusElements const MovementUpdateRunBackSpeed[] = MSEGuidByte4, MSEFallTime, MSEFallHorizontalSpeed, - MSEFallCosAngle, MSEFallSinAngle, + MSEFallCosAngle, MSEFallVerticalSpeed, MSETimestamp, MSEGuidByte1, @@ -3234,8 +3228,8 @@ MovementStatusElements const MovementUpdateWalkSpeed[] = MSETransportGuidByte3, MSEFallVerticalSpeed, MSEFallHorizontalSpeed, - MSEFallCosAngle, MSEFallSinAngle, + MSEFallCosAngle, MSEFallTime, MSEGuidByte1, MSEGuidByte4, @@ -3318,8 +3312,8 @@ MovementStatusElements const ForceMoveRootAck[] = MSETimestamp, MSEFallVerticalSpeed, MSEFallHorizontalSpeed, - MSEFallSinAngle, MSEFallCosAngle, + MSEFallSinAngle, MSEFallTime, MSEOrientation, MSESplineElevation, @@ -3388,9 +3382,9 @@ MovementStatusElements const ForceMoveUnrootAck[] = MSETransportPositionX, MSETransportGuidByte1, MSETransportGuidByte7, - MSEFallCosAngle, - MSEFallHorizontalSpeed, MSEFallSinAngle, + MSEFallHorizontalSpeed, + MSEFallCosAngle, MSEFallVerticalSpeed, MSEFallTime, MSETimestamp, @@ -3461,8 +3455,8 @@ MovementStatusElements const MovementFallReset[] = MSETransportGuidByte4, MSETransportGuidByte1, MSEFallVerticalSpeed, - MSEFallCosAngle, MSEFallSinAngle, + MSEFallCosAngle, MSEFallHorizontalSpeed, MSEFallTime, MSEOrientation, @@ -3537,9 +3531,9 @@ MovementStatusElements const MovementFeatherFallAck[] = MSESplineElevation, MSEOrientation, MSEFallVerticalSpeed, - MSEFallCosAngle, - MSEFallHorizontalSpeed, MSEFallSinAngle, + MSEFallHorizontalSpeed, + MSEFallCosAngle, MSEFallTime, MSEPitch, MSEEnd, @@ -3606,8 +3600,8 @@ MovementStatusElements const MovementGravityDisableAck[] = MSETransportPositionX, MSETransportGuidByte7, MSETransportTime3, - MSEFallCosAngle, MSEFallSinAngle, + MSEFallCosAngle, MSEFallHorizontalSpeed, MSEFallTime, MSEFallVerticalSpeed, @@ -3665,8 +3659,8 @@ MovementStatusElements const MovementGravityEnableAck[] = MSEGuidByte6, MSEFallTime, MSEFallHorizontalSpeed, - MSEFallSinAngle, MSEFallCosAngle, + MSEFallSinAngle, MSEFallVerticalSpeed, MSETransportGuidByte1, MSETransportPositionX, @@ -3737,8 +3731,8 @@ MovementStatusElements const MovementHoverAck[] = MSEGuidByte3, MSEGuidByte0, MSETimestamp, - MSEFallCosAngle, MSEFallSinAngle, + MSEFallCosAngle, MSEFallHorizontalSpeed, MSEFallTime, MSEFallVerticalSpeed, @@ -3809,9 +3803,9 @@ MovementStatusElements const MovementKnockBackAck[] = MSEGuidByte3, MSEGuidByte2, MSEGuidByte7, - MSEFallCosAngle, - MSEFallHorizontalSpeed, MSEFallSinAngle, + MSEFallHorizontalSpeed, + MSEFallCosAngle, MSEFallTime, MSEFallVerticalSpeed, MSETimestamp, @@ -3899,9 +3893,9 @@ MovementStatusElements const MovementWaterWalkAck[] = MSETransportGuidByte6, MSETransportGuidByte4, MSESplineElevation, - MSEFallCosAngle, - MSEFallHorizontalSpeed, MSEFallSinAngle, + MSEFallHorizontalSpeed, + MSEFallCosAngle, MSEFallVerticalSpeed, MSEFallTime, MSEOrientation, @@ -3934,9 +3928,9 @@ MovementStatusElements const MovementUpdateKnockBack[] = MSEHasFallDirection, MSEHasOrientation, MSEOrientation, - MSEFallCosAngle, - MSEFallHorizontalSpeed, MSEFallSinAngle, + MSEFallHorizontalSpeed, + MSEFallCosAngle, MSEFallTime, MSEFallVerticalSpeed, MSEGuidByte3, @@ -5017,8 +5011,8 @@ MovementStatusElements const ChangeSeatsOnControlledVehicle[] = MSEExtraElement, MSEGuidByte2, MSEPitch, - MSEFallSinAngle, MSEFallCosAngle, + MSEFallSinAngle, MSEFallHorizontalSpeed, MSEFallTime, MSEFallVerticalSpeed, @@ -5108,8 +5102,8 @@ MovementStatusElements const CastSpellEmbeddedMovement[] = MSESplineElevation, MSEFallTime, MSEFallHorizontalSpeed, - MSEFallCosAngle, MSEFallSinAngle, + MSEFallCosAngle, MSEFallVerticalSpeed, MSETimestamp, MSEPitch, diff --git a/src/server/game/Movement/PathGenerator.cpp b/src/server/game/Movement/PathGenerator.cpp index ed30b59f0ec..c902eb850f6 100644 --- a/src/server/game/Movement/PathGenerator.cpp +++ b/src/server/game/Movement/PathGenerator.cpp @@ -548,7 +548,9 @@ void PathGenerator::UpdateFilter() NavTerrain PathGenerator::GetNavTerrain(float x, float y, float z) { LiquidData data; - _sourceUnit->GetBaseMap()->getLiquidStatus(x, y, z, MAP_ALL_LIQUIDS, &data); + ZLiquidStatus liquidStatus = _sourceUnit->GetBaseMap()->getLiquidStatus(x, y, z, MAP_ALL_LIQUIDS, &data); + if (liquidStatus == LIQUID_MAP_NO_WATER) + return NAV_GROUND; switch (data.type_flags) { diff --git a/src/server/game/Movement/Spline/Spline.h b/src/server/game/Movement/Spline/Spline.h index 42090cae71b..d4b100ee46e 100644 --- a/src/server/game/Movement/Spline/Spline.h +++ b/src/server/game/Movement/Spline/Spline.h @@ -21,6 +21,7 @@ #include "MovementTypedefs.h" #include <G3D/Vector3.h> +#include <limits> namespace Movement { @@ -184,6 +185,9 @@ public: while (i < index_hi) { new_length = cacher(*this, i); + // length overflowed, assign to max positive value + if (new_length < 0) + new_length = std::numeric_limits<length_type>::max(); lengths[++i] = new_length; ASSERT(prev_length <= new_length); diff --git a/src/server/game/Quests/QuestDef.cpp b/src/server/game/Quests/QuestDef.cpp index 8d4f3b42e72..d377aa0a197 100644 --- a/src/server/game/Quests/QuestDef.cpp +++ b/src/server/game/Quests/QuestDef.cpp @@ -72,7 +72,6 @@ Quest::Quest(Field* questRecord) RewardReputationMask = questRecord[46].GetUInt8(); QuestGiverPortrait = questRecord[47].GetUInt32(); QuestTurnInPortrait = questRecord[48].GetUInt32(); - for (int i = 0; i < QUEST_REWARDS_COUNT; ++i) RewardItemId[i] = questRecord[49+i].GetUInt32(); @@ -126,82 +125,78 @@ Quest::Quest(Field* questRecord) RequiredSpell = questRecord[123].GetUInt32(); - for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i) // To be removed - RequiredSpellCast[i] = questRecord[124+i].GetUInt32(); - for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i) - ObjectiveText[i] = questRecord[128+i].GetString(); + ObjectiveText[i] = questRecord[124+i].GetString(); for (int i = 0; i < QUEST_REWARD_CURRENCY_COUNT; ++i) - RewardCurrencyId[i] = questRecord[132+i].GetUInt16(); + RewardCurrencyId[i] = questRecord[128+i].GetUInt16(); for (int i = 0; i < QUEST_REWARD_CURRENCY_COUNT; ++i) - RewardCurrencyCount[i] = questRecord[136+i].GetUInt8(); + RewardCurrencyCount[i] = questRecord[132+i].GetUInt8(); for (int i = 0; i < QUEST_REQUIRED_CURRENCY_COUNT; ++i) - RequiredCurrencyId[i] = questRecord[140+i].GetUInt16(); + RequiredCurrencyId[i] = questRecord[136+i].GetUInt16(); for (int i = 0; i < QUEST_REQUIRED_CURRENCY_COUNT; ++i) - RequiredCurrencyCount[i] = questRecord[144+i].GetUInt8(); + RequiredCurrencyCount[i] = questRecord[140+i].GetUInt8(); - QuestGiverTextWindow = questRecord[148].GetString(); - QuestGiverTargetName = questRecord[149].GetString(); - QuestTurnTextWindow = questRecord[150].GetString(); - QuestTurnTargetName = questRecord[151].GetString(); - SoundAccept = questRecord[152].GetUInt16(); - SoundTurnIn = questRecord[153].GetUInt16(); + QuestGiverTextWindow = questRecord[144].GetString(); + QuestGiverTargetName = questRecord[145].GetString(); + QuestTurnTextWindow = questRecord[146].GetString(); + QuestTurnTargetName = questRecord[147].GetString(); + SoundAccept = questRecord[148].GetUInt16(); + SoundTurnIn = questRecord[149].GetUInt16(); for (int i = 0; i < QUEST_EMOTE_COUNT; ++i) - DetailsEmote[i] = questRecord[154+i].GetUInt16(); + DetailsEmote[i] = questRecord[150+i].GetUInt16(); for (int i = 0; i < QUEST_EMOTE_COUNT; ++i) - DetailsEmoteDelay[i] = questRecord[158+i].GetUInt32(); + DetailsEmoteDelay[i] = questRecord[154+i].GetUInt32(); - EmoteOnIncomplete = questRecord[162].GetUInt16(); - EmoteOnComplete = questRecord[163].GetUInt16(); + EmoteOnIncomplete = questRecord[158].GetUInt16(); + EmoteOnComplete = questRecord[159].GetUInt16(); for (int i = 0; i < QUEST_EMOTE_COUNT; ++i) - OfferRewardEmote[i] = questRecord[164+i].GetInt16(); + OfferRewardEmote[i] = questRecord[160+i].GetInt16(); for (int i = 0; i < QUEST_EMOTE_COUNT; ++i) - OfferRewardEmoteDelay[i] = questRecord[168+i].GetInt32(); + OfferRewardEmoteDelay[i] = questRecord[164+i].GetInt32(); - // int32 WDBVerified = questRecord[172].GetInt32(); + // int32 WDBVerified = questRecord[168].GetInt32(); if (SpecialFlags & QUEST_SPECIAL_FLAGS_AUTO_ACCEPT) Flags |= QUEST_FLAGS_AUTO_ACCEPT; - m_reqItemsCount = 0; - m_reqNpcOrGoCount = 0; - m_rewItemsCount = 0; - m_rewChoiceItemsCount = 0; - m_rewCurrencyCount = 0; - m_reqCurrencyCount = 0; + _reqItemsCount = 0; + _reqNpcOrGoCount = 0; + _rewItemsCount = 0; + _rewChoiceItemsCount = 0; + _rewCurrencyCount = 0; + _reqCurrencyCount = 0; for (int i = 0; i < QUEST_ITEM_OBJECTIVES_COUNT; ++i) if (RequiredItemId[i]) - ++m_reqItemsCount; + ++_reqItemsCount; for (int i = 0; i < QUEST_OBJECTIVES_COUNT; ++i) if (RequiredNpcOrGo[i]) - ++m_reqNpcOrGoCount; + ++_reqNpcOrGoCount; for (int i = 0; i < QUEST_REWARDS_COUNT; ++i) if (RewardItemId[i]) - ++m_rewItemsCount; + ++_rewItemsCount; for (int i = 0; i < QUEST_REWARD_CHOICES_COUNT; ++i) if (RewardChoiceItemId[i]) - ++m_rewChoiceItemsCount; + ++_rewChoiceItemsCount; for (int i = 0; i < QUEST_REWARD_CURRENCY_COUNT; ++i) if (RewardCurrencyId[i]) - ++m_rewCurrencyCount; + ++_rewCurrencyCount; for (int i = 0; i < QUEST_REQUIRED_CURRENCY_COUNT; ++i) if (RequiredCurrencyId[i]) - ++m_reqCurrencyCount; - + ++_reqCurrencyCount; } uint32 Quest::XPValue(Player* player) const diff --git a/src/server/game/Quests/QuestDef.h b/src/server/game/Quests/QuestDef.h index 93db5c0ce65..599780d5cbe 100644 --- a/src/server/game/Quests/QuestDef.h +++ b/src/server/game/Quests/QuestDef.h @@ -78,7 +78,7 @@ enum QuestShareMessages QUEST_PARTY_MSG_NOT_IN_PARTY = 10 }; -enum __QuestTradeSkill +enum QuestTradeSkill { QUEST_TRSKILL_NONE = 0, QUEST_TRSKILL_ALCHEMY = 1, @@ -109,7 +109,7 @@ enum QuestStatus MAX_QUEST_STATUS }; -enum __QuestGiverStatus +enum QuestGiverStatus { DIALOG_STATUS_NONE = 0x000, DIALOG_STATUS_UNK = 0x001, @@ -156,22 +156,23 @@ enum QuestFlags // ... 4.x added flags up to 0x80000000 - all unknown for now }; -enum __QuestSpecialFlags +enum QuestSpecialFlags { QUEST_SPECIAL_FLAGS_NONE = 0x000, // Trinity flags for set SpecialFlags in DB if required but used only at server - QUEST_SPECIAL_FLAGS_REPEATABLE = 0x001, - QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT = 0x002, // if required area explore, spell SPELL_EFFECT_QUEST_COMPLETE casting, table `*_script` command SCRIPT_COMMAND_QUEST_EXPLORED use, set from script) - QUEST_SPECIAL_FLAGS_AUTO_ACCEPT = 0x004, // quest is to be auto-accepted. - QUEST_SPECIAL_FLAGS_DF_QUEST = 0x008, // quest is used by Dungeon Finder. - QUEST_SPECIAL_FLAGS_MONTHLY = 0x010, // quest is reset at the begining of the month + QUEST_SPECIAL_FLAGS_REPEATABLE = 0x001, // Set by 1 in SpecialFlags from DB + QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT = 0x002, // Set by 2 in SpecialFlags from DB (if required area explore, spell SPELL_EFFECT_QUEST_COMPLETE casting, table `FECT_QUEST_COMPLETE casting, table `*_script` command SCRIPT_COMMAND_QUEST_EXPLORED use, set from script) + QUEST_SPECIAL_FLAGS_AUTO_ACCEPT = 0x004, // Set by 4 in SpecialFlags in DB if the quest is to be auto-accepted. + QUEST_SPECIAL_FLAGS_DF_QUEST = 0x008, // Set by 8 in SpecialFlags in DB if the quest is used by Dungeon Finder. + QUEST_SPECIAL_FLAGS_MONTHLY = 0x010, // Set by 16 in SpecialFlags in DB if the quest is reset at the begining of the month + QUEST_SPECIAL_FLAGS_CAST = 0x020, // Set by 32 in SpecialFlags in DB if the quest requires RequiredOrNpcGo killcredit but NOT kill (a spell cast) // room for more custom flags - QUEST_SPECIAL_FLAGS_DB_ALLOWED = QUEST_SPECIAL_FLAGS_REPEATABLE | QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT | QUEST_SPECIAL_FLAGS_AUTO_ACCEPT | QUEST_SPECIAL_FLAGS_DF_QUEST | QUEST_SPECIAL_FLAGS_MONTHLY, + QUEST_SPECIAL_FLAGS_DB_ALLOWED = QUEST_SPECIAL_FLAGS_REPEATABLE | QUEST_SPECIAL_FLAGS_EXPLORATION_OR_EVENT | QUEST_SPECIAL_FLAGS_AUTO_ACCEPT | QUEST_SPECIAL_FLAGS_DF_QUEST | QUEST_SPECIAL_FLAGS_MONTHLY | QUEST_SPECIAL_FLAGS_CAST, QUEST_SPECIAL_FLAGS_DELIVER = 0x080, // Internal flag computed only QUEST_SPECIAL_FLAGS_SPEAKTO = 0x100, // Internal flag computed only - QUEST_SPECIAL_FLAGS_KILL_OR_CAST = 0x200, // Internal flag computed only + QUEST_SPECIAL_FLAGS_KILL = 0x200, // Internal flag computed only QUEST_SPECIAL_FLAGS_TIMED = 0x400, // Internal flag computed only QUEST_SPECIAL_FLAGS_PLAYER_KILL = 0x800 // Internal flag computed only }; @@ -286,7 +287,7 @@ class Quest uint32 GetQuestTurnInPortrait() const { return QuestTurnInPortrait; } bool IsDaily() const { return Flags & QUEST_FLAGS_DAILY; } bool IsWeekly() const { return Flags & QUEST_FLAGS_WEEKLY; } - bool IsMonthly() const { return Flags & QUEST_SPECIAL_FLAGS_MONTHLY; } + bool IsMonthly() const { return SpecialFlags & QUEST_SPECIAL_FLAGS_MONTHLY; } bool IsSeasonal() const { return (ZoneOrSort == -QUEST_SORT_SEASONAL || ZoneOrSort == -QUEST_SORT_SPECIAL || ZoneOrSort == -QUEST_SORT_LUNAR_FESTIVAL || ZoneOrSort == -QUEST_SORT_MIDSUMMER || ZoneOrSort == -QUEST_SORT_BREWFEST || ZoneOrSort == -QUEST_SORT_LOVE_IS_IN_THE_AIR || ZoneOrSort == -QUEST_SORT_NOBLEGARDEN) && !IsRepeatable(); } bool IsDailyOrWeekly() const { return Flags & (QUEST_FLAGS_DAILY | QUEST_FLAGS_WEEKLY); } bool IsRaidQuest(Difficulty difficulty) const; @@ -302,7 +303,6 @@ class Quest uint32 RequiredSourceItemCount[QUEST_SOURCE_ITEM_IDS_COUNT]; int32 RequiredNpcOrGo[QUEST_OBJECTIVES_COUNT]; // >0 Creature <0 Gameobject uint32 RequiredNpcOrGoCount[QUEST_OBJECTIVES_COUNT]; - uint32 RequiredSpellCast[QUEST_OBJECTIVES_COUNT]; uint32 RewardChoiceItemId[QUEST_REWARD_CHOICES_COUNT]; uint32 RewardChoiceItemCount[QUEST_REWARD_CHOICES_COUNT]; uint32 RewardItemId[QUEST_REWARDS_COUNT]; @@ -320,12 +320,12 @@ class Quest uint32 RequiredCurrencyId[QUEST_REQUIRED_CURRENCY_COUNT]; uint32 RequiredCurrencyCount[QUEST_REQUIRED_CURRENCY_COUNT]; - uint32 GetReqItemsCount() const { return m_reqItemsCount; } - uint32 GetReqCreatureOrGOcount() const { return m_reqNpcOrGoCount; } - uint32 GetRewChoiceItemsCount() const { return m_rewChoiceItemsCount; } - uint32 GetRewItemsCount() const { return m_rewItemsCount; } - uint32 GetRewCurrencyCount() const { return m_rewCurrencyCount; } - uint32 GetReqCurrencyCount() const { return m_reqCurrencyCount; } + uint32 GetReqItemsCount() const { return _reqItemsCount; } + uint32 GetReqCreatureOrGOcount() const { return _reqNpcOrGoCount; } + uint32 GetRewChoiceItemsCount() const { return _rewChoiceItemsCount; } + uint32 GetRewItemsCount() const { return _rewItemsCount; } + uint32 GetRewCurrencyCount() const { return _rewCurrencyCount; } + uint32 GetReqCurrencyCount() const { return _reqCurrencyCount; } void BuildExtraQuestInfo(WorldPacket& data, Player* player) const; @@ -336,12 +336,12 @@ class Quest // cached data private: - uint32 m_reqItemsCount; - uint32 m_reqNpcOrGoCount; - uint32 m_rewChoiceItemsCount; - uint32 m_rewItemsCount; - uint32 m_rewCurrencyCount; - uint32 m_reqCurrencyCount; + uint32 _reqItemsCount; + uint32 _reqNpcOrGoCount; + uint32 _rewChoiceItemsCount; + uint32 _rewItemsCount; + uint32 _rewCurrencyCount; + uint32 _reqCurrencyCount; // table data protected: diff --git a/src/server/game/Scripting/ScriptLoader.cpp b/src/server/game/Scripting/ScriptLoader.cpp index 8d155badd6d..0eb96bc52e9 100644 --- a/src/server/game/Scripting/ScriptLoader.cpp +++ b/src/server/game/Scripting/ScriptLoader.cpp @@ -59,6 +59,7 @@ void AddSC_event_commandscript(); void AddSC_gm_commandscript(); void AddSC_go_commandscript(); void AddSC_gobject_commandscript(); +void AddSC_group_commandscript(); void AddSC_guild_commandscript(); void AddSC_honor_commandscript(); void AddSC_instance_commandscript(); @@ -71,10 +72,12 @@ void AddSC_misc_commandscript(); void AddSC_mmaps_commandscript(); void AddSC_modify_commandscript(); void AddSC_npc_commandscript(); +void AddSC_pet_commandscript(); void AddSC_quest_commandscript(); void AddSC_rbac_commandscript(); void AddSC_reload_commandscript(); void AddSC_reset_commandscript(); +void AddSC_send_commandscript(); void AddSC_server_commandscript(); void AddSC_tele_commandscript(); void AddSC_ticket_commandscript(); @@ -176,6 +179,7 @@ void AddSC_boss_sulfuron(); void AddSC_boss_majordomo(); void AddSC_boss_ragnaros(); void AddSC_instance_molten_core(); +void AddSC_instance_ragefire_chasm(); //Ragefire Chasm void AddSC_the_scarlet_enclave(); //Scarlet Enclave void AddSC_the_scarlet_enclave_c1(); void AddSC_the_scarlet_enclave_c2(); @@ -234,6 +238,7 @@ void AddSC_boss_archaedas(); //Uldaman void AddSC_boss_ironaya(); void AddSC_uldaman(); void AddSC_instance_uldaman(); +void AddSC_instance_the_stockade(); //The Stockade void AddSC_boss_akilzon(); //Zul'Aman void AddSC_boss_halazzi(); void AddSC_boss_hex_lord_malacrass(); @@ -307,10 +312,12 @@ void AddSC_boss_mal_ganis(); void AddSC_boss_meathook(); void AddSC_culling_of_stratholme(); void AddSC_instance_culling_of_stratholme(); +void AddSC_instance_dire_maul(); //Dire Maul void AddSC_boss_celebras_the_cursed(); //Maraudon void AddSC_boss_landslide(); void AddSC_boss_noxxion(); void AddSC_boss_ptheradras(); +void AddSC_instance_maraudon(); void AddSC_boss_onyxia(); //Onyxia's Lair void AddSC_instance_onyxias_lair(); void AddSC_boss_amnennar_the_coldbringer(); //Razorfen Downs @@ -371,23 +378,36 @@ void AddSC_thunder_bluff(); void AddSC_ungoro_crater(); void AddSC_winterspring(); -//northrend +// Northrend + void AddSC_boss_slad_ran(); void AddSC_boss_moorabi(); void AddSC_boss_drakkari_colossus(); void AddSC_boss_gal_darah(); void AddSC_boss_eck(); void AddSC_instance_gundrak(); -void AddSC_boss_krik_thir(); //Azjol-Nerub + +// Azjol-Nerub - Azjol-Nerub +void AddSC_boss_krik_thir(); void AddSC_boss_hadronox(); void AddSC_boss_anub_arak(); void AddSC_instance_azjol_nerub(); -void AddSC_instance_ahnkahet(); //Azjol-Nerub Ahn'kahet -void AddSC_boss_amanitar(); + +// Azjol-Nerub - Ahn'kahet +void AddSC_boss_elder_nadox(); void AddSC_boss_taldaram(); +void AddSC_boss_amanitar(); void AddSC_boss_jedoga_shadowseeker(); -void AddSC_boss_elder_nadox(); void AddSC_boss_volazj(); +void AddSC_instance_ahnkahet(); + +// Drak'Tharon Keep +void AddSC_boss_trollgore(); +void AddSC_boss_novos(); +void AddSC_boss_king_dred(); +void AddSC_boss_tharon_ja(); +void AddSC_instance_drak_tharon_keep(); + void AddSC_boss_argent_challenge(); //Trial of the Champion void AddSC_boss_black_knight(); void AddSC_boss_grand_champions(); @@ -456,26 +476,28 @@ void AddSC_boss_freya(); void AddSC_boss_yogg_saron(); void AddSC_boss_algalon_the_observer(); void AddSC_instance_ulduar(); -void AddSC_boss_keleseth(); //Utgarde Keep + +// Utgarde Keep - Utgarde Keep +void AddSC_boss_keleseth(); void AddSC_boss_skarvald_dalronn(); void AddSC_boss_ingvar_the_plunderer(); void AddSC_instance_utgarde_keep(); -void AddSC_boss_svala(); //Utgarde pinnacle +void AddSC_utgarde_keep(); + +// Utgarde Keep - Utgarde Pinnacle +void AddSC_boss_svala(); void AddSC_boss_palehoof(); void AddSC_boss_skadi(); void AddSC_boss_ymiron(); void AddSC_instance_utgarde_pinnacle(); -void AddSC_utgarde_keep(); -void AddSC_boss_archavon(); //Vault of Archavon + +// Vault of Archavon +void AddSC_boss_archavon(); void AddSC_boss_emalon(); void AddSC_boss_koralon(); void AddSC_boss_toravon(); -void AddSC_instance_archavon(); -void AddSC_boss_trollgore(); //Drak'Tharon Keep -void AddSC_boss_novos(); -void AddSC_boss_king_dred(); -void AddSC_boss_tharon_ja(); -void AddSC_instance_drak_tharon_keep(); +void AddSC_instance_vault_of_archavon(); + void AddSC_boss_cyanigosa(); //Violet Hold void AddSC_boss_erekem(); void AddSC_boss_ichoron(); @@ -532,20 +554,31 @@ void AddSC_zuldrak(); void AddSC_crystalsong_forest(); void AddSC_isle_of_conquest(); -//outland -void AddSC_boss_exarch_maladaar(); //Auchindoun Auchenai Crypts +// Outland + +// Auchindoun - Auchenai Crypts void AddSC_boss_shirrak_the_dead_watcher(); -void AddSC_boss_nexusprince_shaffar(); //Auchindoun Mana Tombs +void AddSC_boss_exarch_maladaar(); +void AddSC_instance_auchenai_crypts(); + +// Auchindoun - Mana Tombs void AddSC_boss_pandemonius(); -void AddSC_boss_darkweaver_syth(); //Auchindoun Sekketh Halls +void AddSC_boss_nexusprince_shaffar(); +void AddSC_instance_mana_tombs(); + +// Auchindoun - Sekketh Halls +void AddSC_boss_darkweaver_syth(); void AddSC_boss_talon_king_ikiss(); void AddSC_boss_anzu(); void AddSC_instance_sethekk_halls(); -void AddSC_instance_shadow_labyrinth(); //Auchindoun Shadow Labyrinth + +// Auchindoun - Shadow Labyrinth void AddSC_boss_ambassador_hellmaw(); void AddSC_boss_blackheart_the_inciter(); void AddSC_boss_grandmaster_vorpil(); void AddSC_boss_murmur(); +void AddSC_instance_shadow_labyrinth(); + void AddSC_black_temple(); //Black Temple void AddSC_boss_illidan(); void AddSC_boss_shade_of_akama(); @@ -568,8 +601,10 @@ void AddSC_boss_hydromancer_thespia(); //CR Steam Vault void AddSC_boss_mekgineer_steamrigger(); void AddSC_boss_warlord_kalithresh(); void AddSC_instance_steam_vault(); +void AddSC_instance_the_slave_pens(); //The Slave Pens void AddSC_boss_hungarfen(); //CR Underbog void AddSC_boss_the_black_stalker(); +void AddSC_instance_the_underbog(); void AddSC_boss_gruul(); //Gruul's Lair void AddSC_boss_high_king_maulgar(); void AddSC_instance_gruuls_lair(); @@ -628,6 +663,7 @@ void AddSC_event_childrens_week(); // Pets void AddSC_deathknight_pet_scripts(); +void AddSC_generic_pet_scripts(); void AddSC_hunter_pet_scripts(); void AddSC_mage_pet_scripts(); void AddSC_priest_pet_scripts(); @@ -713,6 +749,7 @@ void AddCommandScripts() AddSC_gm_commandscript(); AddSC_go_commandscript(); AddSC_gobject_commandscript(); + AddSC_group_commandscript(); AddSC_guild_commandscript(); AddSC_honor_commandscript(); AddSC_instance_commandscript(); @@ -726,9 +763,11 @@ void AddCommandScripts() AddSC_modify_commandscript(); AddSC_npc_commandscript(); AddSC_quest_commandscript(); + AddSC_pet_commandscript(); AddSC_rbac_commandscript(); AddSC_reload_commandscript(); AddSC_reset_commandscript(); + AddSC_send_commandscript(); AddSC_server_commandscript(); AddSC_tele_commandscript(); AddSC_ticket_commandscript(); @@ -837,6 +876,7 @@ void AddEasternKingdomsScripts() AddSC_boss_majordomo(); AddSC_boss_ragnaros(); AddSC_instance_molten_core(); + AddSC_instance_ragefire_chasm(); //Ragefire Chasm AddSC_the_scarlet_enclave(); //Scarlet Enclave AddSC_the_scarlet_enclave_c1(); AddSC_the_scarlet_enclave_c2(); @@ -891,6 +931,7 @@ void AddEasternKingdomsScripts() AddSC_boss_muru(); AddSC_boss_kiljaeden(); AddSC_sunwell_plateau(); + AddSC_instance_the_stockade(); //The Stockade AddSC_boss_archaedas(); //Uldaman AddSC_boss_ironaya(); AddSC_uldaman(); @@ -973,10 +1014,12 @@ void AddKalimdorScripts() AddSC_boss_meathook(); AddSC_culling_of_stratholme(); AddSC_instance_culling_of_stratholme(); + AddSC_instance_dire_maul(); //Dire Maul AddSC_boss_celebras_the_cursed(); //Maraudon AddSC_boss_landslide(); AddSC_boss_noxxion(); AddSC_boss_ptheradras(); + AddSC_instance_maraudon(); AddSC_boss_onyxia(); //Onyxia's Lair AddSC_instance_onyxias_lair(); AddSC_boss_amnennar_the_coldbringer(); //Razorfen Downs @@ -1044,19 +1087,29 @@ void AddKalimdorScripts() void AddOutlandScripts() { #ifdef SCRIPTS - AddSC_boss_exarch_maladaar(); //Auchindoun Auchenai Crypts + // Auchindoun - Auchenai Crypts AddSC_boss_shirrak_the_dead_watcher(); - AddSC_boss_nexusprince_shaffar(); //Auchindoun Mana Tombs + AddSC_boss_exarch_maladaar(); + AddSC_instance_auchenai_crypts(); + + // Auchindoun - Mana Tombs AddSC_boss_pandemonius(); - AddSC_boss_darkweaver_syth(); //Auchindoun Sekketh Halls + AddSC_boss_nexusprince_shaffar(); + AddSC_instance_mana_tombs(); + + // Auchindoun - Sekketh Halls + AddSC_boss_darkweaver_syth(); AddSC_boss_talon_king_ikiss(); AddSC_boss_anzu(); AddSC_instance_sethekk_halls(); - AddSC_instance_shadow_labyrinth(); //Auchindoun Shadow Labyrinth + + // Auchindoun - Shadow Labyrinth AddSC_boss_ambassador_hellmaw(); AddSC_boss_blackheart_the_inciter(); AddSC_boss_grandmaster_vorpil(); AddSC_boss_murmur(); + AddSC_instance_shadow_labyrinth(); + AddSC_black_temple(); //Black Temple AddSC_boss_illidan(); AddSC_boss_shade_of_akama(); @@ -1079,8 +1132,10 @@ void AddOutlandScripts() AddSC_boss_mekgineer_steamrigger(); AddSC_boss_warlord_kalithresh(); AddSC_instance_steam_vault(); + AddSC_instance_the_slave_pens(); //The Slave Pens AddSC_boss_hungarfen(); //CR Underbog AddSC_boss_the_black_stalker(); + AddSC_instance_the_underbog(); AddSC_boss_gruul(); //Gruul's Lair AddSC_boss_high_king_maulgar(); AddSC_instance_gruuls_lair(); @@ -1142,12 +1197,28 @@ void AddNorthrendScripts() AddSC_boss_gal_darah(); AddSC_boss_eck(); AddSC_instance_gundrak(); - AddSC_boss_amanitar(); - AddSC_boss_taldaram(); //Azjol-Nerub Ahn'kahet + + // Azjol-Nerub - Ahn'kahet AddSC_boss_elder_nadox(); + AddSC_boss_taldaram(); + AddSC_boss_amanitar(); AddSC_boss_jedoga_shadowseeker(); AddSC_boss_volazj(); AddSC_instance_ahnkahet(); + + // Azjol-Nerub - Azjol-Nerub + AddSC_boss_krik_thir(); + AddSC_boss_hadronox(); + AddSC_boss_anub_arak(); + AddSC_instance_azjol_nerub(); + + // Drak'Tharon Keep + AddSC_boss_trollgore(); + AddSC_boss_novos(); + AddSC_boss_king_dred(); + AddSC_boss_tharon_ja(); + AddSC_instance_drak_tharon_keep(); + AddSC_boss_argent_challenge(); //Trial of the Champion AddSC_boss_black_knight(); AddSC_boss_grand_champions(); @@ -1160,10 +1231,6 @@ void AddNorthrendScripts() AddSC_boss_twin_valkyr(); AddSC_boss_northrend_beasts(); AddSC_instance_trial_of_the_crusader(); - AddSC_boss_krik_thir(); //Azjol-Nerub Azjol-Nerub - AddSC_boss_hadronox(); - AddSC_boss_anub_arak(); - AddSC_instance_azjol_nerub(); AddSC_boss_anubrekhan(); //Naxxramas AddSC_boss_maexxna(); AddSC_boss_patchwerk(); @@ -1220,26 +1287,28 @@ void AddNorthrendScripts() AddSC_boss_yogg_saron(); AddSC_boss_algalon_the_observer(); AddSC_instance_ulduar(); - AddSC_boss_keleseth(); //Utgarde Keep + + // Utgarde Keep - Utgarde Keep + AddSC_boss_keleseth(); AddSC_boss_skarvald_dalronn(); AddSC_boss_ingvar_the_plunderer(); AddSC_instance_utgarde_keep(); - AddSC_boss_svala(); //Utgarde pinnacle + AddSC_utgarde_keep(); + + // Utgarde Keep - Utgarde Pinnacle + AddSC_boss_svala(); AddSC_boss_palehoof(); AddSC_boss_skadi(); AddSC_boss_ymiron(); AddSC_instance_utgarde_pinnacle(); - AddSC_utgarde_keep(); - AddSC_boss_archavon(); //Vault of Archavon + + // Vault of Archavon + AddSC_boss_archavon(); AddSC_boss_emalon(); AddSC_boss_koralon(); AddSC_boss_toravon(); - AddSC_instance_archavon(); - AddSC_boss_trollgore(); //Drak'Tharon Keep - AddSC_boss_novos(); - AddSC_boss_king_dred(); - AddSC_boss_tharon_ja(); - AddSC_instance_drak_tharon_keep(); + AddSC_instance_vault_of_archavon(); + AddSC_boss_cyanigosa(); //Violet Hold AddSC_boss_erekem(); AddSC_boss_ichoron(); @@ -1317,6 +1386,7 @@ void AddPetScripts() { #ifdef SCRIPTS AddSC_deathknight_pet_scripts(); + AddSC_generic_pet_scripts(); AddSC_hunter_pet_scripts(); AddSC_mage_pet_scripts(); AddSC_priest_pet_scripts(); diff --git a/src/server/game/Scripting/ScriptMgr.cpp b/src/server/game/Scripting/ScriptMgr.cpp index 3272498662b..65ddb3a8d05 100644 --- a/src/server/game/Scripting/ScriptMgr.cpp +++ b/src/server/game/Scripting/ScriptMgr.cpp @@ -29,10 +29,16 @@ #include "SpellInfo.h" #include "SpellScript.h" #include "GossipDef.h" -#include "CreatureAI.h" +#include "CreatureAIImpl.h" #include "Player.h" #include "WorldPacket.h" +namespace +{ + typedef std::set<ScriptObject*> ExampleScriptContainer; + ExampleScriptContainer ExampleScripts; +} + // This is the global static registry of scripts. template<class TScript> class ScriptRegistry @@ -104,6 +110,9 @@ class ScriptRegistry if (script->GetName().find("example") == std::string::npos && script->GetName().find("Smart") == std::string::npos) TC_LOG_ERROR(LOG_FILTER_SQL, "Script named '%s' does not have a script name assigned in database.", script->GetName().c_str()); + + // These scripts don't get stored anywhere so throw them into this to avoid leaking memory + ExampleScripts.insert(script); } } else @@ -160,7 +169,11 @@ class ScriptRegistry if (!V) \ return R; - +struct TSpellSummary +{ + uint8 Targets; // set of enum SelectTarget + uint8 Effects; // set of enum SelectEffect +} *SpellSummary; ScriptMgr::ScriptMgr() : _scriptCount(0), _scheduledScripts(0) @@ -220,6 +233,13 @@ void ScriptMgr::Unload() SCR_CLEAR(UnitScript); #undef SCR_CLEAR + + for (ExampleScriptContainer::iterator itr = ExampleScripts.begin(); itr != ExampleScripts.end(); ++itr) + delete *itr; + ExampleScripts.clear(); + + delete[] SpellSummary; + delete[] UnitAI::AISpellInfo; } void ScriptMgr::LoadDatabase() @@ -227,14 +247,10 @@ void ScriptMgr::LoadDatabase() sScriptSystemMgr->LoadScriptWaypoints(); } -struct TSpellSummary -{ - uint8 Targets; // set of enum SelectTarget - uint8 Effects; // set of enum SelectEffect -} *SpellSummary; - void ScriptMgr::FillSpellSummary() { + UnitAI::FillAISpellInfo(); + SpellSummary = new TSpellSummary[sSpellMgr->GetSpellInfoStoreSize()]; SpellInfo const* pTempSpell; diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp index 1b4762330c4..275349c83cb 100644 --- a/src/server/game/Server/WorldSession.cpp +++ b/src/server/game/Server/WorldSession.cpp @@ -102,6 +102,7 @@ bool WorldSessionFilter::Process(WorldPacket* packet) WorldSession::WorldSession(uint32 id, WorldSocket* sock, AccountTypes sec, uint8 expansion, time_t mute_time, LocaleConstant locale, uint32 recruiter, bool isARecruiter): m_muteTime(mute_time), m_timeOutTime(0), + AntiDOS(this), _player(NULL), m_Socket(sock), _security(sec), @@ -172,10 +173,7 @@ WorldSession::~WorldSession() int32 z_res = deflateEnd(_compressionStream); if (z_res != Z_OK && z_res != Z_DATA_ERROR) // Z_DATA_ERROR signals that internal state was BUSY - { TC_LOG_ERROR(LOG_FILTER_NETWORKIO, "Can't close packet compression stream (zlib: deflateEnd) Error code: %i (%s)", z_res, zError(z_res)); - return; - } delete _compressionStream; } @@ -318,8 +316,10 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater) !_recvQueue.empty() && _recvQueue.peek(true) != firstDelayedPacket && _recvQueue.next(packet, updater)) { - OpcodeHandler const* opHandle = opcodeTable[packet->GetOpcode()]; + if (!AntiDOS.EvaluateOpcode(*packet)) + KickPlayer(); + OpcodeHandler const* opHandle = opcodeTable[packet->GetOpcode()]; try { switch (opHandle->Status) @@ -402,7 +402,7 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater) break; } } - catch(ByteBufferException &) + catch (ByteBufferException const&) { TC_LOG_ERROR(LOG_FILTER_NETWORKIO, "WorldSession::Update ByteBufferException occured while parsing a packet (opcode: %u) from client %s, accountid=%i. Skipped packet.", packet->GetOpcode(), GetRemoteAddress().c_str(), GetAccountId()); @@ -411,6 +411,8 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater) if (deletePacket) delete packet; + + deletePacket = true; } if (m_Socket && !m_Socket->IsClosed() && _warden) @@ -583,6 +585,7 @@ void WorldSession::LogoutPlayer(bool save) m_playerLogout = false; m_playerSave = false; m_playerRecentlyLogout = true; + AntiDOS.AllowOpcode(CMSG_CHAR_ENUM, true); LogoutRequest(0); } @@ -1157,3 +1160,40 @@ void WorldSession::InvalidateRBACData() delete _RBACData; _RBACData = NULL; } + +bool WorldSession::DosProtection::EvaluateOpcode(WorldPacket& p) const +{ + if (IsOpcodeAllowed(p.GetOpcode())) + return true; + + // Opcode not allowed, let the punishment begin + TC_LOG_INFO(LOG_FILTER_NETWORKIO, "AntiDOS: Account %u, IP: %s, sent unacceptable packet (opc: %u, size: %u)", + Session->GetAccountId(), Session->GetRemoteAddress().c_str(), p.GetOpcode(), (uint32)p.size()); + + switch (_policy) + { + case POLICY_LOG: + return true; + case POLICY_KICK: + TC_LOG_INFO(LOG_FILTER_NETWORKIO, "AntiDOS: Player kicked!"); + return false; + case POLICY_BAN: + { + BanMode bm = (BanMode)sWorld->getIntConfig(CONFIG_PACKET_SPOOF_BANMODE); + uint32 duration = sWorld->getIntConfig(CONFIG_PACKET_SPOOF_BANDURATION); // in seconds + std::string nameOrIp = ""; + switch (bm) + { + case BAN_CHARACTER: // not supported, ban account + case BAN_ACCOUNT: (void)sAccountMgr->GetName(Session->GetAccountId(), nameOrIp); break; + case BAN_IP: nameOrIp = Session->GetRemoteAddress(); break; + } + sWorld->BanAccount(bm, nameOrIp, duration, "DOS (Packet Flooding/Spoofing", "Server: AutoDOS"); + TC_LOG_INFO(LOG_FILTER_NETWORKIO, "AntiDOS: Player automatically banned for %u seconds.", duration); + + return false; + } + default: // invalid policy + return true; + } +} diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index 646007a34e2..871f1df4d05 100644 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -31,6 +31,7 @@ #include "WorldPacket.h" #include "Cryptography/BigNumber.h" #include "Opcodes.h" +#include "AccountMgr.h" class Creature; class GameObject; @@ -966,6 +967,40 @@ class WorldSession QueryCallback<PreparedQueryResult, CharacterCreateInfo*, true> _charCreateCallback; QueryResultHolderFuture _charLoginCallback; + friend class World; + protected: + class DosProtection + { + friend class World; + public: + DosProtection(WorldSession* s) : Session(s), _policy((Policy)sWorld->getIntConfig(CONFIG_PACKET_SPOOF_POLICY)) {} + bool EvaluateOpcode(WorldPacket& p) const; + void AllowOpcode(uint16 opcode, bool allow) { _isOpcodeAllowed[opcode] = allow; } + protected: + enum Policy + { + POLICY_LOG, + POLICY_KICK, + POLICY_BAN, + }; + + bool IsOpcodeAllowed(uint16 opcode) const + { + OpcodeStatusMap::const_iterator itr = _isOpcodeAllowed.find(opcode); + if (itr == _isOpcodeAllowed.end()) + return true; // No presence in the map indicates this is the first time the opcode was sent this session, so allow + + return itr->second; + } + + WorldSession* Session; + + private: + typedef UNORDERED_MAP<uint16, bool> OpcodeStatusMap; + OpcodeStatusMap _isOpcodeAllowed; // could be bool array, but wouldn't be practical for game versions with non-linear opcodes + Policy _policy; + } AntiDOS; + private: // private trade methods void moveItems(Item* myItems[], Item* hisItems[]); diff --git a/src/server/game/Server/WorldSocket.cpp b/src/server/game/Server/WorldSocket.cpp index 2b5c22c1b14..a1e084bc286 100644 --- a/src/server/game/Server/WorldSocket.cpp +++ b/src/server/game/Server/WorldSocket.cpp @@ -457,9 +457,15 @@ int WorldSocket::Update (void) if (closing_) return -1; - if (m_OutActive || (m_OutBuffer->length() == 0 && msg_queue()->is_empty())) + if (m_OutActive) return 0; + { + ACE_GUARD_RETURN (LockType, Guard, m_OutBufferLock, 0); + if (m_OutBuffer->length() == 0 && msg_queue()->is_empty()) + return 0; + } + int ret; do ret = handle_output(get_handle()); @@ -773,11 +779,11 @@ int WorldSocket::HandleSendAuthSession() WorldPacket packet(SMSG_AUTH_CHALLENGE, 37); BigNumber seed1; seed1.SetRand(16 * 8); - packet.append(seed1.AsByteArray(16), 16); // new encryption seeds + packet.append(seed1.AsByteArray(16).get(), 16); // new encryption seeds BigNumber seed2; seed2.SetRand(16 * 8); - packet.append(seed2.AsByteArray(16), 16); // new encryption seeds + packet.append(seed2.AsByteArray(16).get(), 16); // new encryption seeds packet << m_Seed; packet << uint8(1); diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index d44845a389e..ed279258da4 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -681,7 +681,6 @@ void AuraEffect::CalculateSpellMod() { m_spellmod = new SpellModifier(GetBase()); m_spellmod->op = SpellModOp(GetMiscValue()); - ASSERT(m_spellmod->op < MAX_SPELLMOD); m_spellmod->type = SpellModType(uint32(GetAuraType())); // SpellModType value == spell aura types m_spellmod->spellId = GetId(); @@ -1340,9 +1339,9 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const else { if (spellId) - target->RemoveAurasDueToSpell(spellId); + target->RemoveOwnedAura(spellId, target->GetGUID()); if (spellId2) - target->RemoveAurasDueToSpell(spellId2); + target->RemoveOwnedAura(spellId2, target->GetGUID()); Unit::AuraEffectList const& shapeshifts = target->GetAuraEffectsByType(SPELL_AURA_MOD_SHAPESHIFT); AuraEffect* newAura = NULL; @@ -2113,7 +2112,7 @@ void AuraEffect::HandleAuraModScale(AuraApplication const* aurApp, uint8 mode, b Unit* target = aurApp->GetTarget(); - float scale = target->GetFloatValue(OBJECT_FIELD_SCALE_X); + float scale = target->GetObjectScale(); ApplyPercentModFloatVar(scale, float(GetAmount()), apply); target->SetObjectScale(scale); } @@ -2133,7 +2132,7 @@ void AuraEffect::HandleAuraCloneCaster(AuraApplication const* aurApp, uint8 mode // What must be cloned? at least display and scale target->SetDisplayId(caster->GetDisplayId()); - //target->SetObjectScale(caster->GetFloatValue(OBJECT_FIELD_SCALE_X)); // we need retail info about how scaling is handled (aura maybe?) + //target->SetObjectScale(caster->GetObjectScale()); // we need retail info about how scaling is handled (aura maybe?) target->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_MIRROR_IMAGE); } else @@ -2154,9 +2153,6 @@ void AuraEffect::HandleFeignDeath(AuraApplication const* aurApp, uint8 mode, boo Unit* target = aurApp->GetTarget(); - if (target->GetTypeId() != TYPEID_PLAYER) - return; - if (apply) { /* @@ -2194,14 +2190,14 @@ void AuraEffect::HandleFeignDeath(AuraApplication const* aurApp, uint8 mode, boo // stop handling the effect if it was removed by linked event if (aurApp->GetRemoveMode()) return; - // blizz like 2.0.x - target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_29); - // blizz like 2.0.x - target->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH); - // blizz like 2.0.x - target->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD); + target->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_29); // blizz like 2.0.x + target->SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH); // blizz like 2.0.x + target->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD); // blizz like 2.0.x target->AddUnitState(UNIT_STATE_DIED); + + if (Creature* creature = target->ToCreature()) + creature->SetReactState(REACT_PASSIVE); } else { @@ -2209,14 +2205,14 @@ void AuraEffect::HandleFeignDeath(AuraApplication const* aurApp, uint8 mode, boo WorldPacket data(SMSG_FEIGN_DEATH_RESISTED, 0); target->SendMessageToSet(&data, true); */ - // blizz like 2.0.x - target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_29); - // blizz like 2.0.x - target->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH); - // blizz like 2.0.x - target->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD); + target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_29); // blizz like 2.0.x + target->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH); // blizz like 2.0.x + target->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD); // blizz like 2.0.x target->ClearUnitState(UNIT_STATE_DIED); + + if (Creature* creature = target->ToCreature()) + creature->InitializeReactState(); } } @@ -2287,14 +2283,15 @@ void AuraEffect::HandleAuraModDisarm(AuraApplication const* aurApp, uint8 mode, // Handle damage modification, shapeshifted druids are not affected if (target->GetTypeId() == TYPEID_PLAYER && !target->IsInFeralForm()) { - if (Item* pItem = target->ToPlayer()->GetItemByPos(INVENTORY_SLOT_BAG_0, slot)) + Player* player = target->ToPlayer(); + if (Item* item = player->GetItemByPos(INVENTORY_SLOT_BAG_0, slot)) { uint8 attacktype = Player::GetAttackBySlot(slot); if (attacktype < MAX_ATTACK) { - target->ToPlayer()->_ApplyWeaponDamage(slot, pItem->GetTemplate(), NULL, !apply); - target->ToPlayer()->_ApplyWeaponDependentAuraMods(pItem, WeaponAttackType(attacktype), !apply); + player->_ApplyWeaponDamage(slot, item->GetTemplate(), NULL, !apply); + player->_ApplyWeaponDependentAuraMods(item, WeaponAttackType(attacktype), !apply); } } } @@ -5083,7 +5080,7 @@ void AuraEffect::HandleAuraLinked(AuraApplication const* aurApp, uint8 mode, boo { if (apply) { - Unit* caster = triggeredSpellInfo->NeedsToBeTriggeredByCaster() ? GetCaster() : target; + Unit* caster = triggeredSpellInfo->NeedsToBeTriggeredByCaster(m_spellInfo) ? GetCaster() : target; if (!caster) return; @@ -5095,13 +5092,13 @@ void AuraEffect::HandleAuraLinked(AuraApplication const* aurApp, uint8 mode, boo } else { - uint64 casterGUID = triggeredSpellInfo->NeedsToBeTriggeredByCaster() ? GetCasterGUID() : target->GetGUID(); + uint64 casterGUID = triggeredSpellInfo->NeedsToBeTriggeredByCaster(m_spellInfo) ? GetCasterGUID() : target->GetGUID(); target->RemoveAura(triggeredSpellId, casterGUID, 0, aurApp->GetRemoveMode()); } } else if (mode & AURA_EFFECT_HANDLE_REAPPLY && apply) { - uint64 casterGUID = triggeredSpellInfo->NeedsToBeTriggeredByCaster() ? GetCasterGUID() : target->GetGUID(); + uint64 casterGUID = triggeredSpellInfo->NeedsToBeTriggeredByCaster(m_spellInfo) ? GetCasterGUID() : target->GetGUID(); // change the stack amount to be equal to stack amount of our aura if (Aura* triggeredAura = target->GetAura(triggeredSpellId, casterGUID)) triggeredAura->ModStackAmount(GetBase()->GetStackAmount() - triggeredAura->GetStackAmount()); @@ -5701,7 +5698,7 @@ void AuraEffect::HandlePeriodicTriggerSpellAuraTick(Unit* target, Unit* caster) if (triggeredSpellInfo) { - if (Unit* triggerCaster = triggeredSpellInfo->NeedsToBeTriggeredByCaster() ? caster : target) + if (Unit* triggerCaster = triggeredSpellInfo->NeedsToBeTriggeredByCaster(m_spellInfo) ? caster : target) { triggerCaster->CastSpell(target, triggeredSpellInfo, true, NULL, this); TC_LOG_DEBUG(LOG_FILTER_SPELLS_AURAS, "AuraEffect::HandlePeriodicTriggerSpellAuraTick: Spell %u Trigger %u", GetId(), triggeredSpellInfo->Id); @@ -5721,7 +5718,7 @@ void AuraEffect::HandlePeriodicTriggerSpellWithValueAuraTick(Unit* target, Unit* uint32 triggerSpellId = GetSpellInfo()->Effects[m_effIndex].TriggerSpell; if (SpellInfo const* triggeredSpellInfo = sSpellMgr->GetSpellInfo(triggerSpellId)) { - if (Unit* triggerCaster = triggeredSpellInfo->NeedsToBeTriggeredByCaster() ? caster : target) + if (Unit* triggerCaster = triggeredSpellInfo->NeedsToBeTriggeredByCaster(m_spellInfo) ? caster : target) { int32 basepoints = GetAmount(); triggerCaster->CastCustomSpell(target, triggerSpellId, &basepoints, &basepoints, &basepoints, true, 0, this); diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp index 1ca3e08a8b4..363446a72d3 100644 --- a/src/server/game/Spells/Auras/SpellAuras.cpp +++ b/src/server/game/Spells/Auras/SpellAuras.cpp @@ -1027,8 +1027,7 @@ int32 Aura::CalcDispelChance(Unit* auraTarget, bool offensive) const if (offensive && auraTarget) resistChance += auraTarget->GetTotalAuraModifier(SPELL_AURA_MOD_DISPEL_RESIST); - resistChance = resistChance < 0 ? 0 : resistChance; - resistChance = resistChance > 100 ? 100 : resistChance; + RoundToInterval(resistChance, 0, 100); return 100 - resistChance; } @@ -2237,6 +2236,7 @@ void UnitAura::FillTargetMap(std::map<Unit*, uint8> & targets, Unit* caster) } case SPELL_EFFECT_APPLY_AREA_AURA_PET: targetList.push_back(GetUnitOwner()); + // no break case SPELL_EFFECT_APPLY_AREA_AURA_OWNER: { if (Unit* owner = GetUnitOwner()->GetCharmerOrOwner()) diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index ef30e99dcfc..fb739ba61c1 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -2565,17 +2565,9 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target) { //AI functions if (spellHitTarget->GetTypeId() == TYPEID_UNIT) - { if (spellHitTarget->ToCreature()->IsAIEnabled) spellHitTarget->ToCreature()->AI()->SpellHit(m_caster, m_spellInfo); - // cast at creature (or GO) quest objectives update at successful cast finished (+channel finished) - // ignore pets or autorepeat/melee casts for speed (not exist quest for spells (hm...) - if (m_originalCaster && m_originalCaster->IsControlledByPlayer() && !spellHitTarget->ToCreature()->IsPet() && !IsAutoRepeat() && !IsNextMeleeSwingSpell() && !IsChannelActive()) - if (Player* p = m_originalCaster->GetCharmerOrOwnerPlayerOrPlayerItself()) - p->CastedCreatureOrGO(spellHitTarget->GetEntry(), spellHitTarget->GetGUID(), m_spellInfo->Id); - } - if (m_caster->GetTypeId() == TYPEID_UNIT && m_caster->ToCreature()->IsAIEnabled) m_caster->ToCreature()->AI()->SpellHitTarget(spellHitTarget, m_spellInfo); @@ -2817,7 +2809,7 @@ void Spell::DoTriggersOnSpellHit(Unit* unit, uint8 effMask) { if (CanExecuteTriggersOnHit(effMask, i->triggeredByAura) && roll_chance_i(i->chance)) { - m_caster->CastSpell(unit, i->triggeredSpell, true); + m_caster->CastSpell(unit, i->triggeredSpell, TRIGGERED_FULL_MASK & ~TRIGGERED_IGNORE_TARGET_CHECK); TC_LOG_DEBUG(LOG_FILTER_SPELLS_AURAS, "Spell %d triggered spell %d by SPELL_AURA_ADD_TARGET_TRIGGER aura", m_spellInfo->Id, i->triggeredSpell->Id); // SPELL_AURA_ADD_TARGET_TRIGGER auras shouldn't trigger auras without duration @@ -2875,12 +2867,6 @@ void Spell::DoAllEffectOnTarget(GOTargetInfo* target) HandleEffects(NULL, NULL, go, effectNumber, SPELL_EFFECT_HANDLE_HIT_TARGET); CallScriptOnHitHandlers(); - - // cast at creature (or GO) quest objectives update at successful cast finished (+channel finished) - // ignore autorepeat/melee casts for speed (not exist quest for spells (hm...) - if (m_originalCaster && m_originalCaster->IsControlledByPlayer() && !IsAutoRepeat() && !IsNextMeleeSwingSpell() && !IsChannelActive()) - if (Player* p = m_originalCaster->GetCharmerOrOwnerPlayerOrPlayerItself()) - p->CastedCreatureOrGO(go->GetEntry(), go->GetGUID(), m_spellInfo->Id); CallScriptAfterHitHandlers(); } @@ -3053,12 +3039,12 @@ void Spell::prepare(SpellCastTargets const* targets, AuraEffect const* triggered if (Player* player = m_caster->ToPlayer()) { - if (!m_caster->ToPlayer()->GetCommandStatus(CHEAT_CASTTIME)) + if (!player->GetCommandStatus(CHEAT_CASTTIME)) { - m_caster->ToPlayer()->SetSpellModTakingSpell(this, true); + player->SetSpellModTakingSpell(this, true); // calculate cast time (calculated after first CheckCast check to prevent charge counting for first CheckCast fail) - m_casttime = m_spellInfo->CalcCastTime(m_caster->getLevel(), this); - m_caster->ToPlayer()->SetSpellModTakingSpell(this, false); + m_casttime = m_spellInfo->CalcCastTime(player->getLevel(), this); + player->SetSpellModTakingSpell(this, false); } else m_casttime = 0; // Set cast time to 0 if .cheat casttime is enabled. @@ -3645,40 +3631,6 @@ void Spell::update(uint32 difftime) if (m_timer == 0) { SendChannelUpdate(0); - - // channeled spell processed independently for quest targeting - // cast at creature (or GO) quest objectives update at successful cast channel finished - // ignore autorepeat/melee casts for speed (not exist quest for spells (hm...) - if (!IsAutoRepeat() && !IsNextMeleeSwingSpell()) - { - if (Player* p = m_caster->GetCharmerOrOwnerPlayerOrPlayerItself()) - { - for (std::list<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit) - { - TargetInfo* target = &*ihit; - if (!IS_CRE_OR_VEH_GUID(target->targetGUID)) - continue; - - Unit* unit = m_caster->GetGUID() == target->targetGUID ? m_caster : ObjectAccessor::GetUnit(*m_caster, target->targetGUID); - if (unit == NULL) - continue; - - p->CastedCreatureOrGO(unit->GetEntry(), unit->GetGUID(), m_spellInfo->Id); - } - - for (std::list<GOTargetInfo>::iterator ihit = m_UniqueGOTargetInfo.begin(); ihit != m_UniqueGOTargetInfo.end(); ++ihit) - { - GOTargetInfo* target = &*ihit; - - GameObject* go = m_caster->GetMap()->GetGameObject(target->targetGUID); - if (!go) - continue; - - p->CastedCreatureOrGO(go->GetEntry(), go->GetGUID(), m_spellInfo->Id); - } - } - } - finish(); } break; @@ -6200,6 +6152,7 @@ SpellCastResult Spell::CheckItems() return SPELL_FAILED_DONT_REPORT; } } + // no break case SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC: { Item* targetItem = m_targets.GetItemTarget(); diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index cc6a584847d..764fe302069 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -781,13 +781,13 @@ void Spell::EffectTriggerSpell(SpellEffIndex effIndex) SpellCastTargets targets; if (effectHandleMode == SPELL_EFFECT_HANDLE_LAUNCH_TARGET) { - if (!spellInfo->NeedsToBeTriggeredByCaster()) + if (!spellInfo->NeedsToBeTriggeredByCaster(m_spellInfo)) return; targets.SetUnitTarget(unitTarget); } else //if (effectHandleMode == SPELL_EFFECT_HANDLE_LAUNCH) { - if (spellInfo->NeedsToBeTriggeredByCaster() && (m_spellInfo->Effects[effIndex].GetProvidedTargetMask() & TARGET_FLAG_UNIT_MASK)) + if (spellInfo->NeedsToBeTriggeredByCaster(m_spellInfo) && (m_spellInfo->Effects[effIndex].GetProvidedTargetMask() & TARGET_FLAG_UNIT_MASK)) return; if (spellInfo->GetExplicitTargetMask() & TARGET_FLAG_DEST_LOCATION) @@ -833,13 +833,13 @@ void Spell::EffectTriggerMissileSpell(SpellEffIndex effIndex) SpellCastTargets targets; if (effectHandleMode == SPELL_EFFECT_HANDLE_HIT_TARGET) { - if (!spellInfo->NeedsToBeTriggeredByCaster()) + if (!spellInfo->NeedsToBeTriggeredByCaster(m_spellInfo)) return; targets.SetUnitTarget(unitTarget); } else //if (effectHandleMode == SPELL_EFFECT_HANDLE_HIT) { - if (spellInfo->NeedsToBeTriggeredByCaster() && (m_spellInfo->Effects[effIndex].GetProvidedTargetMask() & TARGET_FLAG_UNIT_MASK)) + if (spellInfo->NeedsToBeTriggeredByCaster(m_spellInfo) && (m_spellInfo->Effects[effIndex].GetProvidedTargetMask() & TARGET_FLAG_UNIT_MASK)) return; if (spellInfo->GetExplicitTargetMask() & TARGET_FLAG_DEST_LOCATION) @@ -898,6 +898,9 @@ void Spell::EffectForceCast(SpellEffIndex effIndex) case 52349: // Overtake unitTarget->CastCustomSpell(unitTarget, spellInfo->Id, &damage, NULL, NULL, true, NULL, NULL, m_originalCasterGUID); return; + case 72299: // Malleable Goo Summon Trigger + unitTarget->CastSpell(unitTarget, spellInfo->Id, true, NULL, NULL, m_originalCasterGUID); + return; } } @@ -994,29 +997,6 @@ void Spell::EffectTeleportUnits(SpellEffIndex /*effIndex*/) if (!unitTarget || unitTarget->IsInFlight()) return; - // Pre effects - switch (m_spellInfo->Id) - { - case 66550: // teleports outside (Isle of Conquest) - if (Player* target = unitTarget->ToPlayer()) - { - if (target->GetTeamId() == TEAM_ALLIANCE) - m_targets.SetDst(442.24f, -835.25f, 44.30f, 0.06f, 628); - else - m_targets.SetDst(1120.43f, -762.11f, 47.92f, 2.94f, 628); - } - break; - case 66551: // teleports inside (Isle of Conquest) - if (Player* target = unitTarget->ToPlayer()) - { - if (target->GetTeamId() == TEAM_ALLIANCE) - m_targets.SetDst(389.57f, -832.38f, 48.65f, 3.00f, 628); - else - m_targets.SetDst(1174.85f, -763.24f, 48.72f, 6.26f, 628); - } - break; - } - // If not exist data for dest location - return if (!m_targets.HasDst()) { @@ -3598,15 +3578,6 @@ void Spell::EffectScriptEffect(SpellEffIndex effIndex) npc->LoadEquipment(); return; } - // Emblazon Runeblade - case 51770: - { - if (!m_originalCaster) - return; - - m_originalCaster->CastSpell(m_originalCaster, damage, false); - break; - } // Deathbolt from Thalgran Blightbringer // reflected by Freya's Ward // Retribution by Sevenfold Retribution @@ -3681,26 +3652,6 @@ void Spell::EffectScriptEffect(SpellEffIndex effIndex) return; } - case 58941: // Rock Shards - if (unitTarget && m_originalCaster) - { - for (uint32 i = 0; i < 3; ++i) - { - m_originalCaster->CastSpell(unitTarget, 58689, true); - m_originalCaster->CastSpell(unitTarget, 58692, true); - } - if (((InstanceMap*)m_originalCaster->GetMap())->GetDifficulty() == REGULAR_DIFFICULTY) - { - m_originalCaster->CastSpell(unitTarget, 58695, true); - m_originalCaster->CastSpell(unitTarget, 58696, true); - } - else - { - m_originalCaster->CastSpell(unitTarget, 60883, true); - m_originalCaster->CastSpell(unitTarget, 60884, true); - } - } - return; case 58983: // Big Blizzard Bear { if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) @@ -5366,7 +5317,7 @@ void Spell::EffectActivateRune(SpellEffIndex effIndex) // Blood Tap if (m_spellInfo->Id == 45529 && count > 0) { - for (uint32 l = 0; l < MAX_RUNES && count > 0; ++l) + for (uint32 l = 0; l + 1 < MAX_RUNES && count > 0; ++l) { // Check if both runes are on cd as that is the only time when this needs to come into effect if ((player->GetRuneCooldown(l) && player->GetCurrentRune(l) == RuneType(m_spellInfo->Effects[effIndex].MiscValueB)) && (player->GetRuneCooldown(l+1) && player->GetCurrentRune(l+1) == RuneType(m_spellInfo->Effects[effIndex].MiscValueB))) diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp index 4254be1c968..b74ed66a953 100644 --- a/src/server/game/Spells/SpellInfo.cpp +++ b/src/server/game/Spells/SpellInfo.cpp @@ -1170,14 +1170,12 @@ bool SpellInfo::NeedsExplicitUnitTarget() const return GetExplicitTargetMask() & TARGET_FLAG_UNIT_MASK; } -bool SpellInfo::NeedsToBeTriggeredByCaster() const +bool SpellInfo::NeedsToBeTriggeredByCaster(SpellInfo const* triggeringSpell) const { - if (AttributesCu & SPELL_ATTR0_CU_TRIGGERED_BY_CASTER) - return true; - if (NeedsExplicitUnitTarget()) return true; + /* for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) { if (Effects[i].IsEffect()) @@ -1187,6 +1185,23 @@ bool SpellInfo::NeedsToBeTriggeredByCaster() const return true; } } + */ + + if (triggeringSpell->IsChanneled()) + { + uint32 mask = 0; + for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + { + if (Effects[i].TargetA.GetTarget() != TARGET_UNIT_CASTER && Effects[i].TargetA.GetTarget() != TARGET_DEST_CASTER + && Effects[i].TargetB.GetTarget() != TARGET_UNIT_CASTER && Effects[i].TargetB.GetTarget() != TARGET_DEST_CASTER) + { + mask |= Effects[i].GetProvidedTargetMask(); + } + } + + if (mask & TARGET_FLAG_UNIT_MASK) + return true; + } return false; } diff --git a/src/server/game/Spells/SpellInfo.h b/src/server/game/Spells/SpellInfo.h index a7021dbabcc..1c3fbd70022 100644 --- a/src/server/game/Spells/SpellInfo.h +++ b/src/server/game/Spells/SpellInfo.h @@ -179,7 +179,6 @@ enum SpellCustomAttributes SPELL_ATTR0_CU_CONE_LINE = 0x00000004, SPELL_ATTR0_CU_SHARE_DAMAGE = 0x00000008, SPELL_ATTR0_CU_NO_INITIAL_THREAT = 0x00000010, - SPELL_ATTR0_CU_TRIGGERED_BY_CASTER = 0x00000020, // @todo: need generic solution, some triggered spells will be casted by target instead of caster SPELL_ATTR0_CU_AURA_CC = 0x00000040, SPELL_ATTR0_CU_DIRECT_DAMAGE = 0x00000100, SPELL_ATTR0_CU_CHARGE = 0x00000200, @@ -437,7 +436,7 @@ public: bool IsAffectingArea() const; bool IsTargetingArea() const; bool NeedsExplicitUnitTarget() const; - bool NeedsToBeTriggeredByCaster() const; + bool NeedsToBeTriggeredByCaster(SpellInfo const* triggeringSpell) const; bool IsPassive() const; bool IsAutocastable() const; diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index cb0ba654b42..8b26244d0a5 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -27,7 +27,6 @@ #include "Chat.h" #include "Spell.h" #include "BattlegroundMgr.h" -#include "CreatureAI.h" #include "MapManager.h" #include "BattlefieldWG.h" #include "BattlefieldMgr.h" @@ -128,6 +127,9 @@ DiminishingGroup GetDiminishingReturnsGroupForSpell(SpellInfo const* spellproto, // Seduction else if (spellproto->SpellFamilyFlags[1] & 0x10000000) return DIMINISHING_FEAR; + // Sin and Punishment (Priest spell, don't ask) + else if (spellproto->SpellIconID == 1869) + return DIMINISHING_NONE; break; } case SPELLFAMILY_DRUID: @@ -287,7 +289,7 @@ int32 GetDiminishingReturnsLimitDuration(DiminishingGroup group, SpellInfo const return 6 * IN_MILLISECONDS; // Hunter's Mark if (spellproto->SpellFamilyFlags[0] & 0x400) - return 120 * IN_MILLISECONDS; + return 30 * IN_MILLISECONDS; break; } case SPELLFAMILY_PALADIN: @@ -1224,7 +1226,7 @@ void SpellMgr::LoadSpellTalentRanks() node.rank = rank + 1; node.prev = prevSpell; - node.next = node.rank < MAX_TALENT_RANK ? GetSpellInfo(talentInfo->RankID[rank + 1]) : NULL; + node.next = node.rank < MAX_TALENT_RANK ? GetSpellInfo(talentInfo->RankID[node.rank]) : NULL; mSpellChains[spellId] = node; mSpellInfoMap[spellId]->ChainEntry = &mSpellChains[spellId]; @@ -2858,6 +2860,9 @@ void SpellMgr::LoadSpellInfoCustomAttributes() { uint32 enchantId = spellInfo->Effects[j].MiscValue; SpellItemEnchantmentEntry const* enchant = sSpellItemEnchantmentStore.LookupEntry(enchantId); + if (!enchant) + break; + for (uint8 s = 0; s < MAX_ITEM_ENCHANTMENT_EFFECTS; ++s) { if (enchant->type[s] != ITEM_ENCHANTMENT_TYPE_COMBAT_SPELL) @@ -3047,11 +3052,6 @@ void SpellMgr::LoadSpellInfoCustomAttributes() break; case 72293: // Mark of the Fallen Champion (Deathbringer Saurfang) spellInfo->AttributesCu |= SPELL_ATTR0_CU_NEGATIVE_EFF0; - break; - case 38729: // Rod of Purification - case 96946: // Gaze of Occu'thar - case 101005: // Gaze of Occu'thar - spellInfo->AttributesCu |= SPELL_ATTR0_CU_TRIGGERED_BY_CASTER; break; default: break; @@ -3076,8 +3076,6 @@ void SpellMgr::LoadSpellInfoCustomAttributes() spellInfo->_InitializeExplicitTargetMask(); } - CreatureAI::FillAISpellInfo(); - TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, ">> Loaded SpellInfo custom attributes in %u ms", GetMSTimeDiffToNow(oldMSTime)); } @@ -3386,10 +3384,6 @@ void SpellMgr::LoadSpellInfoCorrections() case 45602: // Ride Carpet spellInfo->Effects[EFFECT_0].BasePoints = 0; // force seat 0, vehicle doesn't have the required seat flags for "no seat specified (-1)" break; - case 59414: // Pulsing Shockwave Aura (Loken) - // this flag breaks movement, remove it - spellInfo->AttributesEx &= ~SPELL_ATTR1_CHANNELED_1; - break; case 61719: // Easter Lay Noblegarden Egg Aura - Interrupt flags copied from aura which this aura is linked with spellInfo->AuraInterruptFlags = AURA_INTERRUPT_FLAG_HITBYSPELL | AURA_INTERRUPT_FLAG_TAKE_DAMAGE; break; @@ -3766,6 +3760,13 @@ void SpellMgr::LoadSpellInfoCorrections() case 101009: // Gaze of Occu'thar spellInfo->AttributesEx &= ~SPELL_ATTR1_CHANNELED_1; break; + // ISLE OF CONQUEST SPELLS + // + case 66551: // Teleport + spellInfo->RangeEntry = sSpellRangeStore.LookupEntry(13); // 50000yd + break; + // ENDOF ISLE OF CONQUEST SPELLS + // default: break; } @@ -3785,10 +3786,10 @@ void SpellMgr::LoadSpellInfoCorrections() } } - SummonPropertiesEntry* properties = const_cast<SummonPropertiesEntry*>(sSummonPropertiesStore.LookupEntry(121)); - properties->Type = SUMMON_TYPE_TOTEM; - properties = const_cast<SummonPropertiesEntry*>(sSummonPropertiesStore.LookupEntry(647)); // 52893 - properties->Type = SUMMON_TYPE_TOTEM; + if (SummonPropertiesEntry* properties = const_cast<SummonPropertiesEntry*>(sSummonPropertiesStore.LookupEntry(121))) + properties->Type = SUMMON_TYPE_TOTEM; + if (SummonPropertiesEntry* properties = const_cast<SummonPropertiesEntry*>(sSummonPropertiesStore.LookupEntry(647))) // 52893 + properties->Type = SUMMON_TYPE_TOTEM; TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, ">> Loaded SpellInfo corrections in %u ms", GetMSTimeDiffToNow(oldMSTime)); } diff --git a/src/server/game/Spells/SpellScript.h b/src/server/game/Spells/SpellScript.h index 6f1df2560dc..f7940b2b8da 100644 --- a/src/server/game/Spells/SpellScript.h +++ b/src/server/game/Spells/SpellScript.h @@ -74,9 +74,9 @@ class _SpellScript EffectHook(uint8 _effIndex); virtual ~EffectHook() { } - uint8 GetAffectedEffectsMask(SpellInfo const* spellEntry); - bool IsEffectAffected(SpellInfo const* spellEntry, uint8 effIndex); - virtual bool CheckEffect(SpellInfo const* spellEntry, uint8 effIndex) = 0; + uint8 GetAffectedEffectsMask(SpellInfo const* spellInfo); + bool IsEffectAffected(SpellInfo const* spellInfo, uint8 effIndex); + virtual bool CheckEffect(SpellInfo const* spellInfo, uint8 effIndex) = 0; std::string EffIndexToString(); protected: uint8 effIndex; @@ -86,7 +86,7 @@ class _SpellScript { public: EffectNameCheck(uint16 _effName) { effName = _effName; } - bool Check(SpellInfo const* spellEntry, uint8 effIndex); + bool Check(SpellInfo const* spellInfo, uint8 effIndex); std::string ToString(); private: uint16 effName; @@ -96,7 +96,7 @@ class _SpellScript { public: EffectAuraNameCheck(uint16 _effAurName) { effAurName = _effAurName; } - bool Check(SpellInfo const* spellEntry, uint8 effIndex); + bool Check(SpellInfo const* spellInfo, uint8 effIndex); std::string ToString(); private: uint16 effAurName; @@ -114,7 +114,7 @@ class _SpellScript virtual void Register() = 0; // Function called on server startup, if returns false script won't be used in core // use for: dbc/template data presence/correctness checks - virtual bool Validate(SpellInfo const* /*spellEntry*/) { return true; } + virtual bool Validate(SpellInfo const* /*spellInfo*/) { return true; } // Function called when script is created, if returns false script will be unloaded afterwards // use for: initializing local script variables (DO NOT USE CONSTRUCTOR FOR THIS PURPOSE!) virtual bool Load() { return true; } @@ -185,7 +185,7 @@ class SpellScript : public _SpellScript public: EffectHandler(SpellEffectFnType _pEffectHandlerScript, uint8 _effIndex, uint16 _effName); std::string ToString(); - bool CheckEffect(SpellInfo const* spellEntry, uint8 effIndex); + bool CheckEffect(SpellInfo const* spellInfo, uint8 effIndex); void Call(SpellScript* spellScript, SpellEffIndex effIndex); private: SpellEffectFnType pEffectHandlerScript; @@ -204,7 +204,7 @@ class SpellScript : public _SpellScript { public: TargetHook(uint8 _effectIndex, uint16 _targetType, bool _area); - bool CheckEffect(SpellInfo const* spellEntry, uint8 effIndex); + bool CheckEffect(SpellInfo const* spellInfo, uint8 effIndex); std::string ToString(); protected: uint16 targetType; @@ -488,7 +488,7 @@ class AuraScript : public _SpellScript public: EffectBase(uint8 _effIndex, uint16 _effName); std::string ToString(); - bool CheckEffect(SpellInfo const* spellEntry, uint8 effIndex); + bool CheckEffect(SpellInfo const* spellInfo, uint8 effIndex); }; class EffectPeriodicHandler : public EffectBase { diff --git a/src/server/game/Warden/WardenCheckMgr.cpp b/src/server/game/Warden/WardenCheckMgr.cpp index 51bb2e52342..a8bcd61db73 100644 --- a/src/server/game/Warden/WardenCheckMgr.cpp +++ b/src/server/game/Warden/WardenCheckMgr.cpp @@ -94,7 +94,7 @@ void WardenCheckMgr::LoadWardenChecks() { uint8 temp[24]; memset(temp, 0, len); - memcpy(temp, wardenCheck->Data.AsByteArray(), wardenCheck->Data.GetNumBytes()); + memcpy(temp, wardenCheck->Data.AsByteArray().get(), wardenCheck->Data.GetNumBytes()); std::reverse(temp, temp + len); wardenCheck->Data.SetBinary((uint8*)temp, len); } @@ -126,7 +126,7 @@ void WardenCheckMgr::LoadWardenChecks() { uint8 *temp = new uint8[len]; memset(temp, 0, len); - memcpy(temp, wr->Result.AsByteArray(), wr->Result.GetNumBytes()); + memcpy(temp, wr->Result.AsByteArray().get(), wr->Result.GetNumBytes()); std::reverse(temp, temp + len); wr->Result.SetBinary((uint8*)temp, len); delete [] temp; diff --git a/src/server/game/Warden/WardenMac.cpp b/src/server/game/Warden/WardenMac.cpp index 74ca285c525..27e859e741d 100644 --- a/src/server/game/Warden/WardenMac.cpp +++ b/src/server/game/Warden/WardenMac.cpp @@ -42,7 +42,7 @@ void WardenMac::Init(WorldSession* pClient, BigNumber* K) { _session = pClient; // Generate Warden Key - SHA1Randx WK(K->AsByteArray(), K->GetNumBytes()); + SHA1Randx WK(K->AsByteArray().get(), K->GetNumBytes()); WK.Generate(_inputKey, 16); WK.Generate(_outputKey, 16); /* diff --git a/src/server/game/Warden/WardenWin.cpp b/src/server/game/Warden/WardenWin.cpp index 1ce96b44ee6..60a1fecedc9 100644 --- a/src/server/game/Warden/WardenWin.cpp +++ b/src/server/game/Warden/WardenWin.cpp @@ -46,7 +46,7 @@ void WardenWin::Init(WorldSession* session, BigNumber* k) { _session = session; // Generate Warden Key - SHA1Randx WK(k->AsByteArray(), k->GetNumBytes()); + SHA1Randx WK(k->AsByteArray().get(), k->GetNumBytes()); WK.Generate(_inputKey, 16); WK.Generate(_outputKey, 16); @@ -266,7 +266,7 @@ void WardenWin::RequestData() case PAGE_CHECK_A: case PAGE_CHECK_B: { - buff.append(wd->Data.AsByteArray(0, false), wd->Data.GetNumBytes()); + buff.append(wd->Data.AsByteArray(0, false).get(), wd->Data.GetNumBytes()); buff << uint32(wd->Address); buff << uint8(wd->Length); break; @@ -279,7 +279,7 @@ void WardenWin::RequestData() } case DRIVER_CHECK: { - buff.append(wd->Data.AsByteArray(0, false), wd->Data.GetNumBytes()); + buff.append(wd->Data.AsByteArray(0, false).get(), wd->Data.GetNumBytes()); buff << uint8(index++); break; } @@ -295,7 +295,7 @@ void WardenWin::RequestData() } /*case PROC_CHECK: { - buff.append(wd->i.AsByteArray(0, false), wd->i.GetNumBytes()); + buff.append(wd->i.AsByteArray(0, false).get(), wd->i.GetNumBytes()); buff << uint8(index++); buff << uint8(index++); buff << uint32(wd->Address); @@ -395,7 +395,7 @@ void WardenWin::HandleData(ByteBuffer &buff) continue; } - if (memcmp(buff.contents() + buff.rpos(), rs->Result.AsByteArray(0, false), rd->Length) != 0) + if (memcmp(buff.contents() + buff.rpos(), rs->Result.AsByteArray(0, false).get(), rd->Length) != 0) { TC_LOG_DEBUG(LOG_FILTER_WARDEN, "RESULT MEM_CHECK fail CheckId %u account Id %u", *itr, _session->GetAccountId()); checkFailed = *itr; @@ -474,7 +474,7 @@ void WardenWin::HandleData(ByteBuffer &buff) continue; } - if (memcmp(buff.contents() + buff.rpos(), rs->Result.AsByteArray(0, false), 20) != 0) // SHA1 + if (memcmp(buff.contents() + buff.rpos(), rs->Result.AsByteArray(0, false).get(), 20) != 0) // SHA1 { TC_LOG_DEBUG(LOG_FILTER_WARDEN, "RESULT MPQ_CHECK fail, CheckId %u account Id %u", *itr, _session->GetAccountId()); checkFailed = *itr; diff --git a/src/server/game/Weather/Weather.cpp b/src/server/game/Weather/Weather.cpp index ae04feb894b..461dc04588a 100644 --- a/src/server/game/Weather/Weather.cpp +++ b/src/server/game/Weather/Weather.cpp @@ -94,8 +94,9 @@ bool Weather::ReGenerate() //78 days between January 1st and March 20nd; 365/4=91 days by season // season source http://aa.usno.navy.mil/data/docs/EarthSeasons.html time_t gtime = sWorld->GetGameTime(); - struct tm * ltime = localtime(>ime); - uint32 season = ((ltime->tm_yday - 78 + 365)/91)%4; + struct tm ltime; + ACE_OS::localtime_r(>ime, <ime); + uint32 season = ((ltime.tm_yday - 78 + 365)/91)%4; static char const* seasonName[WEATHER_SEASONS] = { "spring", "summer", "fall", "winter" }; diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index f6001e2ac7a..f297e9a7b75 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -84,7 +84,7 @@ ACE_Atomic_Op<ACE_Thread_Mutex, bool> World::m_stopEvent = false; uint8 World::m_ExitCode = SHUTDOWN_EXIT_CODE; -volatile uint32 World::m_worldLoopCounter = 0; +ACE_Atomic_Op<ACE_Thread_Mutex, uint32> World::m_worldLoopCounter = 0; float World::m_MaxVisibleDistanceOnContinents = DEFAULT_VISIBILITY_DISTANCE; float World::m_MaxVisibleDistanceInInstances = DEFAULT_VISIBILITY_INSTANCE; @@ -1141,7 +1141,7 @@ void World::LoadConfigSettings(bool reload) ///- Read the "Data" directory from the config file std::string dataPath = sConfigMgr->GetStringDefault("DataDir", "./"); - if (dataPath.at(dataPath.length()-1) != '/' && dataPath.at(dataPath.length()-1) != '\\') + if (dataPath.empty() || (dataPath.at(dataPath.length()-1) != '/' && dataPath.at(dataPath.length()-1) != '\\')) dataPath.push_back('/'); #if PLATFORM == PLATFORM_UNIX || PLATFORM == PLATFORM_APPLE @@ -1228,9 +1228,23 @@ void World::LoadConfigSettings(bool reload) // DBC_ItemAttributes m_bool_configs[CONFIG_DBC_ENFORCE_ITEM_ATTRIBUTES] = sConfigMgr->GetBoolDefault("DBC.EnforceItemAttributes", true); + // Accountpassword Secruity + m_int_configs[CONFIG_ACC_PASSCHANGESEC] = sConfigMgr->GetIntDefault("Account.PasswordChangeSecurity", 0); + + // Random Battleground Rewards + m_int_configs[CONFIG_BG_REWARD_WINNER_HONOR_FIRST] = sConfigMgr->GetIntDefault("Battleground.RewardWinnerHonorFirst", 27000); + m_int_configs[CONFIG_BG_REWARD_WINNER_CONQUEST_FIRST] = sConfigMgr->GetIntDefault("Battleground.RewardWinnerConquestFirst", 10000); + m_int_configs[CONFIG_BG_REWARD_WINNER_HONOR_LAST] = sConfigMgr->GetIntDefault("Battleground.RewardWinnerHonorLast", 13500); + m_int_configs[CONFIG_BG_REWARD_WINNER_CONQUEST_LAST] = sConfigMgr->GetIntDefault("Battleground.RewardWinnerConquestLast", 5000); + m_int_configs[CONFIG_BG_REWARD_LOSER_HONOR_FIRST] = sConfigMgr->GetIntDefault("Battleground.RewardLoserHonorFirst", 4500); + m_int_configs[CONFIG_BG_REWARD_LOSER_HONOR_LAST] = sConfigMgr->GetIntDefault("Battleground.RewardLoserHonorLast", 3500); + // Max instances per hour m_int_configs[CONFIG_MAX_INSTANCES_PER_HOUR] = sConfigMgr->GetIntDefault("AccountInstancesPerHour", 5); + // Anounce reset of instance to whole party + m_bool_configs[CONFIG_INSTANCES_RESET_ANNOUNCE] = sConfigMgr->GetBoolDefault("InstancesResetAnnounce", false); + // AutoBroadcast m_bool_configs[CONFIG_AUTOBROADCAST] = sConfigMgr->GetBoolDefault("AutoBroadcast.On", false); m_int_configs[CONFIG_AUTOBROADCAST_CENTER] = sConfigMgr->GetIntDefault("AutoBroadcast.Center", 0); @@ -1274,6 +1288,14 @@ void World::LoadConfigSettings(bool reload) m_float_configs[CONFIG_STATS_LIMITS_BLOCK] = sConfigMgr->GetFloatDefault("Stats.Limits.Block", 95.0f); m_float_configs[CONFIG_STATS_LIMITS_CRIT] = sConfigMgr->GetFloatDefault("Stats.Limits.Crit", 95.0f); + //packet spoof punishment + m_int_configs[CONFIG_PACKET_SPOOF_POLICY] = sConfigMgr->GetIntDefault("PacketSpoof.Policy", (uint32)WorldSession::DosProtection::POLICY_KICK); + m_int_configs[CONFIG_PACKET_SPOOF_BANMODE] = sConfigMgr->GetIntDefault("PacketSpoof.BanMode", (uint32)BAN_ACCOUNT); + if (m_int_configs[CONFIG_PACKET_SPOOF_BANMODE] == BAN_CHARACTER || m_int_configs[CONFIG_PACKET_SPOOF_BANMODE] > BAN_IP) + m_int_configs[CONFIG_PACKET_SPOOF_BANMODE] = BAN_ACCOUNT; + + m_int_configs[CONFIG_PACKET_SPOOF_BANDURATION] = sConfigMgr->GetIntDefault("PacketSpoof.BanDuration", 86400); + // call ScriptMgr if we're reloading the configuration if (reload) sScriptMgr->OnConfigLoad(reload); @@ -1779,7 +1801,9 @@ void World::SetInitialWorldSettings() //mailtimer is increased when updating auctions //one second is 1000 -(tested on win system) /// @todo Get rid of magic numbers - mail_timer = ((((localtime(&m_gameTime)->tm_hour + 20) % 24)* HOUR * IN_MILLISECONDS) / m_timers[WUPDATE_AUCTIONS].GetInterval()); + tm localTm; + ACE_OS::localtime_r(&m_gameTime, &localTm); + mail_timer = ((((localTm.tm_hour + 20) % 24)* HOUR * IN_MILLISECONDS) / m_timers[WUPDATE_AUCTIONS].GetInterval()); //1440 mail_timer_expires = ((DAY * IN_MILLISECONDS) / (m_timers[WUPDATE_AUCTIONS].GetInterval())); TC_LOG_INFO(LOG_FILTER_SERVER_LOADING, "Mail timer set to: " UI64FMTD ", mail return is called every " UI64FMTD " minutes", uint64(mail_timer), uint64(mail_timer_expires)); @@ -2344,6 +2368,12 @@ void World::KickAllLess(AccountTypes sec) BanReturn World::BanAccount(BanMode mode, std::string const& nameOrIP, std::string const& duration, std::string const& reason, std::string const& author) { uint32 duration_secs = TimeStringToSecs(duration); + return BanAccount(mode, nameOrIP, duration_secs, reason, author); +} + +/// Ban an account or ban an IP address, duration is in seconds if positive, otherwise permban +BanReturn World::BanAccount(BanMode mode, std::string const& nameOrIP, uint32 duration_secs, std::string const& reason, std::string const& author) +{ PreparedQueryResult resultAccounts = PreparedQueryResult(NULL); //used for kicking PreparedStatement* stmt = NULL; @@ -2793,7 +2823,8 @@ void World::InitDailyQuestResetTime() // client built-in time for reset is 6:00 AM // FIX ME: client not show day start time time_t curTime = time(NULL); - tm localTm = *localtime(&curTime); + tm localTm; + ACE_OS::localtime_r(&curTime, &localTm); localTm.tm_hour = 6; localTm.tm_min = 0; localTm.tm_sec = 0; @@ -2826,7 +2857,8 @@ void World::InitRandomBGResetTime() // generate time by config time_t curTime = time(NULL); - tm localTm = *localtime(&curTime); + tm localTm; + ACE_OS::localtime_r(&curTime, &localTm); localTm.tm_hour = getIntConfig(CONFIG_RANDOM_BG_RESET_HOUR); localTm.tm_min = 0; localTm.tm_sec = 0; @@ -2853,7 +2885,8 @@ void World::InitGuildResetTime() // generate time by config time_t curTime = time(NULL); - tm localTm = *localtime(&curTime); + tm localTm; + ACE_OS::localtime_r(&curTime, &localTm); localTm.tm_hour = getIntConfig(CONFIG_GUILD_RESET_HOUR); localTm.tm_min = 0; localTm.tm_sec = 0; @@ -2978,7 +3011,8 @@ void World::ResetMonthlyQuests() // generate time time_t curTime = time(NULL); - tm localTm = *localtime(&curTime); + tm localTm; + ACE_OS::localtime_r(&curTime, &localTm); int month = localTm.tm_mon; int year = localTm.tm_year; diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h index cf57a178a2c..a649791546f 100644 --- a/src/server/game/World/World.h +++ b/src/server/game/World/World.h @@ -168,6 +168,7 @@ enum WorldBoolConfigs CONFIG_UI_QUESTLEVELS_IN_DIALOGS, // Should we add quest levels to the title in the NPC dialogs? CONFIG_EVENT_ANNOUNCE, CONFIG_STATS_LIMITS_ENABLE, + CONFIG_INSTANCES_RESET_ANNOUNCE, BOOL_CONFIG_VALUE_COUNT }; @@ -343,6 +344,16 @@ enum WorldIntConfigs CONFIG_GUILD_UNDELETABLE_LEVEL, CONFIG_GUILD_DAILY_XP_CAP, CONFIG_GUILD_WEEKLY_REP_CAP, + CONFIG_PACKET_SPOOF_POLICY, + CONFIG_PACKET_SPOOF_BANMODE, + CONFIG_PACKET_SPOOF_BANDURATION, + CONFIG_ACC_PASSCHANGESEC, + CONFIG_BG_REWARD_WINNER_HONOR_FIRST, + CONFIG_BG_REWARD_WINNER_HONOR_LAST, + CONFIG_BG_REWARD_LOSER_HONOR_FIRST, + CONFIG_BG_REWARD_LOSER_HONOR_LAST, + CONFIG_BG_REWARD_WINNER_CONQUEST_FIRST, + CONFIG_BG_REWARD_WINNER_CONQUEST_LAST, INT_CONFIG_VALUE_COUNT }; @@ -531,7 +542,7 @@ struct CharacterNameData class World { public: - static volatile uint32 m_worldLoopCounter; + static ACE_Atomic_Op<ACE_Thread_Mutex, uint32> m_worldLoopCounter; World(); ~World(); @@ -707,6 +718,7 @@ class World void KickAll(); void KickAllLess(AccountTypes sec); BanReturn BanAccount(BanMode mode, std::string const& nameOrIP, std::string const& duration, std::string const& reason, std::string const& author); + BanReturn BanAccount(BanMode mode, std::string const& nameOrIP, uint32 duration_secs, std::string const& reason, std::string const& author); bool RemoveBanAccount(BanMode mode, std::string const& nameOrIP); BanReturn BanCharacter(std::string const& name, std::string const& duration, std::string const& reason, std::string const& author); bool RemoveBanCharacter(std::string const& name); diff --git a/src/server/scripts/Commands/CMakeLists.txt b/src/server/scripts/Commands/CMakeLists.txt index ce31fa1f4d3..c38789ed90a 100644 --- a/src/server/scripts/Commands/CMakeLists.txt +++ b/src/server/scripts/Commands/CMakeLists.txt @@ -8,109 +8,11 @@ # WITHOUT ANY WARRANTY, to the extent permitted by law; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +file(GLOB_RECURSE sources_Commands Commands/*.cpp Commands/*.h) + set(scripts_STAT_SRCS ${scripts_STAT_SRCS} - Commands/cs_account.cpp - Commands/cs_achievement.cpp - Commands/cs_arena.cpp - Commands/cs_ban.cpp - Commands/cs_bf.cpp - Commands/cs_cast.cpp - Commands/cs_character.cpp - Commands/cs_cheat.cpp - Commands/cs_debug.cpp - Commands/cs_deserter.cpp - Commands/cs_disable.cpp - Commands/cs_event.cpp - Commands/cs_gm.cpp - Commands/cs_go.cpp - Commands/cs_gobject.cpp - Commands/cs_guild.cpp - Commands/cs_honor.cpp - Commands/cs_instance.cpp - Commands/cs_learn.cpp - Commands/cs_lfg.cpp - Commands/cs_list.cpp - Commands/cs_lookup.cpp - Commands/cs_message.cpp - Commands/cs_misc.cpp - Commands/cs_modify.cpp - Commands/cs_npc.cpp - Commands/cs_quest.cpp - Commands/cs_rbac.cpp - Commands/cs_reload.cpp - Commands/cs_reset.cpp - Commands/cs_tele.cpp - Commands/cs_ticket.cpp - Commands/cs_server.cpp - Commands/cs_titles.cpp - Commands/cs_wp.cpp - Commands/cs_mmaps.cpp -# Commands/cs_pdump.cpp -# Commands/cs_channel.cpp -# Commands/cs_pet.cpp -# Commands/cs_aura.cpp -# Commands/cs_unaura.cpp -# Commands/cs_nameannounce.cpp -# Commands/cs_gmnameannounce.cpp -# Commands/cs_announce.cpp -# Commands/cs_gmannounce.cpp -# Commands/cs_notify.cpp -# Commands/cs_gmnotify.cpp -# Commands/cs_appear.cpp -# Commands/cs_summon.cpp -# Commands/cs_groupsummon.cpp -# Commands/cs_commands.cpp -# Commands/cs_demorph.cpp -# Commands/cs_die.cpp -# Commands/cs_revive.cpp -# Commands/cs_dismount.cpp -# Commands/cs_guid.cpp -# Commands/cs_help.cpp -# Commands/cs_itemmove.cpp -# Commands/cs_cooldown.cpp -# Commands/cs_unlearn.cpp -# Commands/cs_distance.cpp -# Commands/cs_recall.cpp -# Commands/cs_save.cpp -# Commands/cs_saveall.cpp -# Commands/cs_kick.cpp -# Commands/cs_start.cpp -# Commands/cs_taxicheat.cpp -# Commands/cs_linkgrave.cpp -# Commands/cs_neargrave.cpp -# Commands/cs_explorecheat.cpp -# Commands/cs_hover.cpp -# Commands/cs_levelup.cpp -# Commands/cs_showarea.cpp -# Commands/cs_hidearea.cpp -# Commands/cs_additem.cpp -# Commands/cs_additemset.cpp -# Commands/cs_bank.cpp -# Commands/cs_wchange.cpp -# Commands/cs_maxskill.cpp -# Commands/cs_setskill.cpp -# Commands/cs_whispers.cpp -# Commands/cs_pinfo.cpp -# Commands/cs_respawn.cpp -# Commands/cs_send.cpp -# Commands/cs_mute.cpp -# Commands/cs_unmute.cpp -# Commands/cs_movegens.cpp -# Commands/cs_cometome.cpp -# Commands/cs_damage.cpp -# Commands/cs_combatstop.cpp -# Commands/cs_flusharenapoints.cpp -# Commands/cs_repairitems.cpp -# Commands/cs_waterwalk.cpp -# Commands/cs_freeze.cpp -# Commands/cs_unfreeze.cpp -# Commands/cs_listfreeze.cpp -# Commands/cs_possess.cpp -# Commands/cs_unpossess.cpp -# Commands/cs_bindsight.cpp -# Commands/cs_unbindsight.cpp -# Commands/cs_playall.cpp + ${sources_Commands} ) message(" -> Prepared: Commands") diff --git a/src/server/scripts/Commands/cs_account.cpp b/src/server/scripts/Commands/cs_account.cpp index 9b98fb5d151..f0d27104035 100644 --- a/src/server/scripts/Commands/cs_account.cpp +++ b/src/server/scripts/Commands/cs_account.cpp @@ -35,35 +35,43 @@ public: ChatCommand* GetCommands() const OVERRIDE { + static ChatCommand accountSetSecTable[] = + { + { "regmail", RBAC_PERM_COMMAND_ACCOUNT_SET_SEC_REGMAIL, true, &HandleAccountSetRegEmailCommand, "", NULL }, + { "email", RBAC_PERM_COMMAND_ACCOUNT_SET_SEC_EMAIL, true, &HandleAccountSetEmailCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } + }; static ChatCommand accountSetCommandTable[] = { - { "addon", SEC_ADMINISTRATOR, true, &HandleAccountSetAddonCommand, "", NULL }, - { "gmlevel", SEC_CONSOLE, true, &HandleAccountSetGmLevelCommand, "", NULL }, - { "password", SEC_CONSOLE, true, &HandleAccountSetPasswordCommand, "", NULL }, - { NULL, SEC_PLAYER, false, NULL, "", NULL } + { "addon", RBAC_PERM_COMMAND_ACCOUNT_SET_ADDON, true, &HandleAccountSetAddonCommand, "", NULL }, + { "sec", RBAC_PERM_COMMAND_ACCOUNT_SET_SEC, true, NULL, "", accountSetSecTable }, + { "gmlevel", RBAC_PERM_COMMAND_ACCOUNT_SET_GMLEVEL, true, &HandleAccountSetGmLevelCommand, "", NULL }, + { "password", RBAC_PERM_COMMAND_ACCOUNT_SET_PASSWORD, true, &HandleAccountSetPasswordCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand accountLockCommandTable[] = { - { "country", SEC_PLAYER, true, &HandleAccountLockCountryCommand, "", NULL }, - { "ip", SEC_PLAYER, true, &HandleAccountLockIpCommand, "", NULL }, - { NULL, SEC_PLAYER, false, NULL, "", NULL }, + { "country", RBAC_PERM_COMMAND_ACCOUNT_LOCK_COUNTRY, true, &HandleAccountLockCountryCommand, "", NULL }, + { "ip", RBAC_PERM_COMMAND_ACCOUNT_LOCK_IP, true, &HandleAccountLockIpCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand accountCommandTable[] = { - { "addon", SEC_MODERATOR, false, &HandleAccountAddonCommand, "", NULL }, - { "create", SEC_CONSOLE, true, &HandleAccountCreateCommand, "", NULL }, - { "delete", SEC_CONSOLE, true, &HandleAccountDeleteCommand, "", NULL }, - { "onlinelist", SEC_CONSOLE, true, &HandleAccountOnlineListCommand, "", NULL }, - { "lock", SEC_PLAYER, false, NULL, "", accountLockCommandTable }, - { "set", SEC_ADMINISTRATOR, true, NULL, "", accountSetCommandTable }, - { "password", SEC_PLAYER, false, &HandleAccountPasswordCommand, "", NULL }, - { "", SEC_PLAYER, false, &HandleAccountCommand, "", NULL }, - { NULL, SEC_PLAYER, false, NULL, "", NULL } + { "addon", RBAC_PERM_COMMAND_ACCOUNT_ADDON, false, &HandleAccountAddonCommand, "", NULL }, + { "create", RBAC_PERM_COMMAND_ACCOUNT_CREATE, true, &HandleAccountCreateCommand, "", NULL }, + { "delete", RBAC_PERM_COMMAND_ACCOUNT_DELETE, true, &HandleAccountDeleteCommand, "", NULL }, + { "email", RBAC_PERM_COMMAND_ACCOUNT_EMAIL, false, &HandleAccountEmailCommand, "", NULL }, + { "onlinelist", RBAC_PERM_COMMAND_ACCOUNT_ONLINE_LIST, true, &HandleAccountOnlineListCommand, "", NULL }, + { "lock", RBAC_PERM_COMMAND_ACCOUNT_LOCK, false, NULL, "", accountLockCommandTable }, + { "set", RBAC_PERM_COMMAND_ACCOUNT_SET, true, NULL, "", accountSetCommandTable }, + { "password", RBAC_PERM_COMMAND_ACCOUNT_PASSWORD, false, &HandleAccountPasswordCommand, "", NULL }, + { "", RBAC_PERM_COMMAND_ACCOUNT, false, &HandleAccountCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand commandTable[] = { - { "account", SEC_PLAYER, true, NULL, "", accountCommandTable }, - { NULL, SEC_PLAYER, false, NULL, "", NULL } + { "account", RBAC_PERM_COMMAND_ACCOUNT, true, NULL, "", accountCommandTable }, + { NULL, 0, false, NULL, "", NULL } }; return commandTable; } @@ -106,29 +114,36 @@ public: if (!*args) return false; + std::string email; + ///- %Parse the command line arguments char* accountName = strtok((char*)args, " "); char* password = strtok(NULL, " "); + char* possibleEmail = strtok(NULL, " ' "); + if (possibleEmail) + email = possibleEmail; + if (!accountName || !password) return false; - AccountOpResult result = sAccountMgr->CreateAccount(std::string(accountName), std::string(password)); + AccountOpResult result = sAccountMgr->CreateAccount(std::string(accountName), std::string(password), email); switch (result) { case AOR_OK: handler->PSendSysMessage(LANG_ACCOUNT_CREATED, accountName); if (handler->GetSession()) { - TC_LOG_INFO(LOG_FILTER_CHARACTER, "Account: %d (IP: %s) Character:[%s] (GUID: %u) Change Password.", + TC_LOG_INFO(LOG_FILTER_CHARACTER, "Account: %d (IP: %s) Character:[%s] (GUID: %u) created Account %s (Email: '%s')", handler->GetSession()->GetAccountId(), handler->GetSession()->GetRemoteAddress().c_str(), - handler->GetSession()->GetPlayer()->GetName().c_str(), handler->GetSession()->GetPlayer()->GetGUIDLow()); + handler->GetSession()->GetPlayer()->GetName().c_str(), handler->GetSession()->GetPlayer()->GetGUIDLow(), + accountName, email.c_str()); } break; case AOR_NAME_TOO_LONG: handler->SendSysMessage(LANG_ACCOUNT_TOO_LONG); handler->SetSentErrorMessage(true); return false; - case AOR_NAME_ALREDY_EXIST: + case AOR_NAME_ALREADY_EXIST: handler->SendSysMessage(LANG_ACCOUNT_ALREADY_EXIST); handler->SetSentErrorMessage(true); return false; @@ -338,8 +353,92 @@ public: return false; } + static bool HandleAccountEmailCommand(ChatHandler* handler, char const* args) + { + if (!*args) + { + handler->SendSysMessage(LANG_CMD_SYNTAX); + handler->SetSentErrorMessage(true); + return false; + } + + char* oldEmail = strtok((char*)args, " "); + char* password = strtok(NULL, " "); + char* email = strtok(NULL, " "); + char* emailConfirmation = strtok(NULL, " "); + + if (!oldEmail || !password || !email || !emailConfirmation) + { + handler->SendSysMessage(LANG_CMD_SYNTAX); + handler->SetSentErrorMessage(true); + return false; + } + + if (!AccountMgr::CheckEmail(handler->GetSession()->GetAccountId(), std::string(oldEmail))) + { + handler->SendSysMessage(LANG_COMMAND_WRONGEMAIL); + handler->SetSentErrorMessage(true); + TC_LOG_INFO(LOG_FILTER_CHARACTER, "Account: %u (IP: %s) Character:[%s] (GUID: %u) Tried to change email, but the provided email [%s] is not equal to registration email [%s].", + handler->GetSession()->GetAccountId(), handler->GetSession()->GetRemoteAddress().c_str(), + handler->GetSession()->GetPlayer()->GetName().c_str(), handler->GetSession()->GetPlayer()->GetGUIDLow(), + email, oldEmail); + return false; + } + + if (!AccountMgr::CheckPassword(handler->GetSession()->GetAccountId(), std::string(password))) + { + handler->SendSysMessage(LANG_COMMAND_WRONGOLDPASSWORD); + handler->SetSentErrorMessage(true); + TC_LOG_INFO(LOG_FILTER_CHARACTER, "Account: %u (IP: %s) Character:[%s] (GUID: %u) Tried to change email, but the provided password is wrong.", + handler->GetSession()->GetAccountId(), handler->GetSession()->GetRemoteAddress().c_str(), + handler->GetSession()->GetPlayer()->GetName().c_str(), handler->GetSession()->GetPlayer()->GetGUIDLow()); + return false; + } + + if (strcmp(email, oldEmail) == 0) + { + handler->SendSysMessage(LANG_OLD_EMAIL_IS_NEW_EMAIL); + handler->SetSentErrorMessage(true); + return false; + } + + if (strcmp(email, emailConfirmation) != 0) + { + handler->SendSysMessage(LANG_NEW_EMAILS_NOT_MATCH); + handler->SetSentErrorMessage(true); + TC_LOG_INFO(LOG_FILTER_CHARACTER, "Account: %u (IP: %s) Character:[%s] (GUID: %u) Tried to change email, but the provided password is wrong.", + handler->GetSession()->GetAccountId(), handler->GetSession()->GetRemoteAddress().c_str(), + handler->GetSession()->GetPlayer()->GetName().c_str(), handler->GetSession()->GetPlayer()->GetGUIDLow()); + return false; + } + + + AccountOpResult result = AccountMgr::ChangeEmail(handler->GetSession()->GetAccountId(), std::string(email)); + switch (result) + { + case AOR_OK: + handler->SendSysMessage(LANG_COMMAND_EMAIL); + TC_LOG_INFO(LOG_FILTER_CHARACTER, "Account: %u (IP: %s) Character:[%s] (GUID: %u) Changed Email from [%s] to [%s].", + handler->GetSession()->GetAccountId(), handler->GetSession()->GetRemoteAddress().c_str(), + handler->GetSession()->GetPlayer()->GetName().c_str(), handler->GetSession()->GetPlayer()->GetGUIDLow(), + oldEmail, email); + break; + case AOR_EMAIL_TOO_LONG: + handler->SendSysMessage(LANG_EMAIL_TOO_LONG); + handler->SetSentErrorMessage(true); + return false; + default: + handler->SendSysMessage(LANG_COMMAND_NOTCHANGEEMAIL); + handler->SetSentErrorMessage(true); + return false; + } + + return true; + } + static bool HandleAccountPasswordCommand(ChatHandler* handler, char const* args) { + // If no args are given at all, we can return false right away. if (!*args) { handler->SendSysMessage(LANG_CMD_SYNTAX); @@ -347,10 +446,18 @@ public: return false; } - char* oldPassword = strtok((char*)args, " "); - char* newPassword = strtok(NULL, " "); - char* passwordConfirmation = strtok(NULL, " "); + // First, we check config. What security type (sec type) is it ? Depending on it, the command branches out + uint32 pwConfig = sWorld->getIntConfig(CONFIG_ACC_PASSCHANGESEC); // 0 - PW_NONE, 1 - PW_EMAIL, 2 - PW_RBAC + + // Command is supposed to be: .account password [$oldpassword] [$newpassword] [$newpasswordconfirmation] [$emailconfirmation] + char* oldPassword = strtok((char*)args, " "); // This extracts [$oldpassword] + char* newPassword = strtok(NULL, " "); // This extracts [$newpassword] + char* passwordConfirmation = strtok(NULL, " "); // This extracts [$newpasswordconfirmation] + const char* emailConfirmation; // This defines the emailConfirmation variable, which is optional depending on sec type. + if (!(emailConfirmation = strtok(NULL, " "))) // This extracts [$emailconfirmation]. If it doesn't exist, however... + emailConfirmation = ""; // ... it's simply "" for emailConfirmation. + //Is any of those variables missing for any reason ? We return false. if (!oldPassword || !newPassword || !passwordConfirmation) { handler->SendSysMessage(LANG_CMD_SYNTAX); @@ -358,16 +465,31 @@ public: return false; } + // We compare the old, saved password to the entered old password - no chance for the unauthorized. if (!AccountMgr::CheckPassword(handler->GetSession()->GetAccountId(), std::string(oldPassword))) { handler->SendSysMessage(LANG_COMMAND_WRONGOLDPASSWORD); handler->SetSentErrorMessage(true); - TC_LOG_INFO(LOG_FILTER_CHARACTER, "Account: %u (IP: %s) Character:[%s] (GUID: %u) Tried to change password.", + TC_LOG_INFO(LOG_FILTER_CHARACTER, "Account: %u (IP: %s) Character:[%s] (GUID: %u) Tried to change password, but the provided old password is wrong.", handler->GetSession()->GetAccountId(), handler->GetSession()->GetRemoteAddress().c_str(), handler->GetSession()->GetPlayer()->GetName().c_str(), handler->GetSession()->GetPlayer()->GetGUIDLow()); return false; } + // This compares the old, current email to the entered email - however, only... + if ((pwConfig == PW_EMAIL || (pwConfig == PW_RBAC && handler->HasPermission(RBAC_PERM_EMAIL_CONFIRM_FOR_PASS_CHANGE))) // ...if either PW_EMAIL or PW_RBAC with the Permission is active... + && !AccountMgr::CheckEmail(handler->GetSession()->GetAccountId(), std::string(emailConfirmation))) // ... and returns false if the comparison fails. + { + handler->SendSysMessage(LANG_COMMAND_WRONGEMAIL); + handler->SetSentErrorMessage(true); + TC_LOG_INFO(LOG_FILTER_CHARACTER, "Account: %u (IP: %s) Character:[%s] (GUID: %u) Tried to change password, but the entered email [%s] is wrong.", + handler->GetSession()->GetAccountId(), handler->GetSession()->GetRemoteAddress().c_str(), + handler->GetSession()->GetPlayer()->GetName().c_str(), handler->GetSession()->GetPlayer()->GetGUIDLow(), + emailConfirmation); + return false; + } + + // Making sure that newly entered password is correctly entered. if (strcmp(newPassword, passwordConfirmation) != 0) { handler->SendSysMessage(LANG_NEW_PASSWORDS_NOT_MATCH); @@ -375,6 +497,7 @@ public: return false; } + // Changes password and prints result. AccountOpResult result = AccountMgr::ChangePassword(handler->GetSession()->GetAccountId(), std::string(newPassword)); switch (result) { @@ -399,8 +522,40 @@ public: static bool HandleAccountCommand(ChatHandler* handler, char const* /*args*/) { + // GM Level AccountTypes gmLevel = handler->GetSession()->GetSecurity(); handler->PSendSysMessage(LANG_ACCOUNT_LEVEL, uint32(gmLevel)); + + // Security level required + bool hasRBAC = (handler->HasPermission(RBAC_PERM_EMAIL_CONFIRM_FOR_PASS_CHANGE) ? true : false); + uint32 pwConfig = sWorld->getIntConfig(CONFIG_ACC_PASSCHANGESEC); // 0 - PW_NONE, 1 - PW_EMAIL, 2 - PW_RBAC + + handler->PSendSysMessage(LANG_ACCOUNT_SEC_TYPE, (pwConfig == PW_NONE ? "Lowest level: No Email input required." : + pwConfig == PW_EMAIL ? "Highest level: Email input required." : + pwConfig == PW_RBAC ? "Special level: Your account may require email input depending on settings. That is the case if another lien is printed." : + "Unknown security level: Notify technician for details.")); + + // RBAC required display - is not displayed for console + if (pwConfig == PW_RBAC && handler->GetSession() && hasRBAC) + handler->PSendSysMessage(LANG_RBAC_EMAIL_REQUIRED); + + // Email display if sufficient rights + if (handler->HasPermission(RBAC_PERM_MAY_CHECK_OWN_EMAIL)) + { + std::string emailoutput; + uint32 accountId = handler->GetSession()->GetAccountId(); + + PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_GET_EMAIL_BY_ID); + stmt->setUInt32(0, accountId); + PreparedQueryResult result = LoginDatabase.Query(stmt); + + if (result) + { + emailoutput = (*result)[0].GetString(); + handler->PSendSysMessage(LANG_COMMAND_EMAIL_OUTPUT, emailoutput.c_str()); + } + } + return true; } @@ -471,7 +626,11 @@ public: static bool HandleAccountSetGmLevelCommand(ChatHandler* handler, char const* args) { if (!*args) + { + handler->SendSysMessage(LANG_CMD_SYNTAX); + handler->SetSentErrorMessage(true); return false; + } std::string targetAccountName; uint32 targetAccountId = 0; @@ -524,7 +683,7 @@ public: playerSecurity = SEC_CONSOLE; // can set security level only for target with less security and to less security that we have - // This is also reject self apply in fact + // This also restricts setting handler's own security. targetSecurity = AccountMgr::GetSecurity(targetAccountId, gmRealmID); if (targetSecurity >= playerSecurity || gm >= playerSecurity) { @@ -570,7 +729,11 @@ public: static bool HandleAccountSetPasswordCommand(ChatHandler* handler, char const* args) { if (!*args) + { + handler->SendSysMessage(LANG_CMD_SYNTAX); + handler->SetSentErrorMessage(true); return false; + } ///- Get the command line arguments char* account = strtok((char*)args, " "); @@ -597,7 +760,7 @@ public: } /// can set password only for target with less security - /// This is also reject self apply in fact + /// This also restricts setting handler's own password if (handler->HasLowerSecurityAccount(NULL, targetAccountId, true)) return false; @@ -630,6 +793,153 @@ public: } return true; } + + /// Set normal email for account + static bool HandleAccountSetEmailCommand(ChatHandler* handler, char const* args) + { + if (!*args) + return false; + + ///- Get the command line arguments + char* account = strtok((char*)args, " "); + char* email = strtok(NULL, " "); + char* emailConfirmation = strtok(NULL, " "); + + if (!account || !email || !emailConfirmation) + { + handler->SendSysMessage(LANG_CMD_SYNTAX); + handler->SetSentErrorMessage(true); + return false; + } + + std::string accountName = account; + if (!AccountMgr::normalizeString(accountName)) + { + handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, accountName.c_str()); + handler->SetSentErrorMessage(true); + return false; + } + + uint32 targetAccountId = AccountMgr::GetId(accountName); + if (!targetAccountId) + { + handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, accountName.c_str()); + handler->SetSentErrorMessage(true); + return false; + } + + /// can set email only for target with less security + /// This also restricts setting handler's own email. + if (handler->HasLowerSecurityAccount(NULL, targetAccountId, true)) + return false; + + if (strcmp(email, emailConfirmation) != 0) + { + handler->SendSysMessage(LANG_NEW_EMAILS_NOT_MATCH); + handler->SetSentErrorMessage(true); + return false; + } + + AccountOpResult result = AccountMgr::ChangeEmail(targetAccountId, email); + switch (result) + { + case AOR_OK: + handler->SendSysMessage(LANG_COMMAND_EMAIL); + TC_LOG_INFO(LOG_FILTER_CHARACTER, "ChangeEmail: Account %s [Id: %u] had it's email changed to %s.", + accountName.c_str(), targetAccountId, email); + break; + case AOR_NAME_NOT_EXIST: + handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, accountName.c_str()); + handler->SetSentErrorMessage(true); + return false; + case AOR_EMAIL_TOO_LONG: + handler->SendSysMessage(LANG_EMAIL_TOO_LONG); + handler->SetSentErrorMessage(true); + return false; + default: + handler->SendSysMessage(LANG_COMMAND_NOTCHANGEEMAIL); + handler->SetSentErrorMessage(true); + return false; + } + + return true; + } + + /// Change registration email for account + static bool HandleAccountSetRegEmailCommand(ChatHandler* handler, char const* args) + { + if (!*args) + return false; + + //- We do not want anything short of console to use this by default. + //- So we force that. + if (handler->GetSession()) + return false; + + ///- Get the command line arguments + char* account = strtok((char*)args, " "); + char* email = strtok(NULL, " "); + char* emailConfirmation = strtok(NULL, " "); + + if (!account || !email || !emailConfirmation) + { + handler->SendSysMessage(LANG_CMD_SYNTAX); + handler->SetSentErrorMessage(true); + return false; + } + + std::string accountName = account; + if (!AccountMgr::normalizeString(accountName)) + { + handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, accountName.c_str()); + handler->SetSentErrorMessage(true); + return false; + } + + uint32 targetAccountId = AccountMgr::GetId(accountName); + if (!targetAccountId) + { + handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, accountName.c_str()); + handler->SetSentErrorMessage(true); + return false; + } + + /// can set email only for target with less security + /// This also restricts setting handler's own email. + if (handler->HasLowerSecurityAccount(NULL, targetAccountId, true)) + return false; + + if (strcmp(email, emailConfirmation) != 0) + { + handler->SendSysMessage(LANG_NEW_EMAILS_NOT_MATCH); + handler->SetSentErrorMessage(true); + return false; + } + + AccountOpResult result = AccountMgr::ChangeRegEmail(targetAccountId, email); + switch (result) + { + case AOR_OK: + handler->SendSysMessage(LANG_COMMAND_EMAIL); + TC_LOG_INFO(LOG_FILTER_CHARACTER, "ChangeRegEmail: Account %s [Id: %u] had it's Registration Email changed to %s.", + accountName.c_str(), targetAccountId, email); + break; + case AOR_NAME_NOT_EXIST: + handler->PSendSysMessage(LANG_ACCOUNT_NOT_EXIST, accountName.c_str()); + handler->SetSentErrorMessage(true); + return false; + case AOR_EMAIL_TOO_LONG: + handler->SendSysMessage(LANG_EMAIL_TOO_LONG); + handler->SetSentErrorMessage(true); + return false; + default: + handler->SendSysMessage(LANG_COMMAND_NOTCHANGEEMAIL); + handler->SetSentErrorMessage(true); + return false; + } + + return true; + } }; void AddSC_account_commandscript() diff --git a/src/server/scripts/Commands/cs_achievement.cpp b/src/server/scripts/Commands/cs_achievement.cpp index 8b7151046b3..bba55cd1fe8 100644 --- a/src/server/scripts/Commands/cs_achievement.cpp +++ b/src/server/scripts/Commands/cs_achievement.cpp @@ -37,13 +37,13 @@ public: { static ChatCommand achievementCommandTable[] = { - { "add", SEC_ADMINISTRATOR, false, &HandleAchievementAddCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "add", RBAC_PERM_COMMAND_ACHIEVEMENT_ADD, false, &HandleAchievementAddCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand commandTable[] = { - { "achievement", SEC_ADMINISTRATOR, false, NULL, "", achievementCommandTable }, - { NULL, 0, false, NULL, "", NULL } + { "achievement", RBAC_PERM_COMMAND_ACHIEVEMENT, false, NULL, "", achievementCommandTable }, + { NULL, 0, false, NULL, "", NULL } }; return commandTable; } diff --git a/src/server/scripts/Commands/cs_arena.cpp b/src/server/scripts/Commands/cs_arena.cpp index 4dbdab25747..90e47fda19f 100644 --- a/src/server/scripts/Commands/cs_arena.cpp +++ b/src/server/scripts/Commands/cs_arena.cpp @@ -38,18 +38,18 @@ public: { static ChatCommand arenaCommandTable[] = { - { "create", SEC_ADMINISTRATOR, true, &HandleArenaCreateCommand, "", NULL }, - { "disband", SEC_ADMINISTRATOR, true, &HandleArenaDisbandCommand, "", NULL }, - { "rename", SEC_ADMINISTRATOR, true, &HandleArenaRenameCommand, "", NULL }, - { "captain", SEC_ADMINISTRATOR, false, &HandleArenaCaptainCommand, "", NULL }, - { "info", SEC_GAMEMASTER, true, &HandleArenaInfoCommand, "", NULL }, - { "lookup", SEC_GAMEMASTER, false, &HandleArenaLookupCommand, "", NULL }, - { NULL, SEC_GAMEMASTER, false, NULL, "", NULL } + { "create", RBAC_PERM_COMMAND_ARENA_CREATE, true, &HandleArenaCreateCommand, "", NULL }, + { "disband", RBAC_PERM_COMMAND_ARENA_DISBAND, true, &HandleArenaDisbandCommand, "", NULL }, + { "rename", RBAC_PERM_COMMAND_ARENA_RENAME, true, &HandleArenaRenameCommand, "", NULL }, + { "captain", RBAC_PERM_COMMAND_ARENA_CAPTAIN, false, &HandleArenaCaptainCommand, "", NULL }, + { "info", RBAC_PERM_COMMAND_ARENA_INFO, true, &HandleArenaInfoCommand, "", NULL }, + { "lookup", RBAC_PERM_COMMAND_ARENA_LOOKUP, false, &HandleArenaLookupCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand commandTable[] = { - { "arena", SEC_GAMEMASTER, false, NULL, "", arenaCommandTable }, - { NULL, SEC_PLAYER, false, NULL, "", NULL } + { "arena", RBAC_PERM_COMMAND_ARENA, false, NULL, "", arenaCommandTable }, + { NULL, 0, false, NULL, "", NULL } }; return commandTable; } diff --git a/src/server/scripts/Commands/cs_ban.cpp b/src/server/scripts/Commands/cs_ban.cpp index c3eb92cae32..dd6e104f135 100644 --- a/src/server/scripts/Commands/cs_ban.cpp +++ b/src/server/scripts/Commands/cs_ban.cpp @@ -39,41 +39,41 @@ public: { static ChatCommand unbanCommandTable[] = { - { "account", SEC_ADMINISTRATOR, true, &HandleUnBanAccountCommand, "", NULL }, - { "character", SEC_ADMINISTRATOR, true, &HandleUnBanCharacterCommand, "", NULL }, - { "playeraccount", SEC_ADMINISTRATOR, true, &HandleUnBanAccountByCharCommand, "", NULL }, - { "ip", SEC_ADMINISTRATOR, true, &HandleUnBanIPCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "account", RBAC_PERM_COMMAND_UNBAN_ACCOUNT, true, &HandleUnBanAccountCommand, "", NULL }, + { "character", RBAC_PERM_COMMAND_UNBAN_CHARACTER, true, &HandleUnBanCharacterCommand, "", NULL }, + { "playeraccount", RBAC_PERM_COMMAND_UNBAN_PLAYERACCOUNT, true, &HandleUnBanAccountByCharCommand, "", NULL }, + { "ip", RBAC_PERM_COMMAND_UNBAN_IP, true, &HandleUnBanIPCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand banlistCommandTable[] = { - { "account", SEC_ADMINISTRATOR, true, &HandleBanListAccountCommand, "", NULL }, - { "character", SEC_ADMINISTRATOR, true, &HandleBanListCharacterCommand, "", NULL }, - { "ip", SEC_ADMINISTRATOR, true, &HandleBanListIPCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "account", RBAC_PERM_COMMAND_BANLIST_ACCOUNT, true, &HandleBanListAccountCommand, "", NULL }, + { "character", RBAC_PERM_COMMAND_BANLIST_CHARACTER, true, &HandleBanListCharacterCommand, "", NULL }, + { "ip", RBAC_PERM_COMMAND_BANLIST_IP, true, &HandleBanListIPCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand baninfoCommandTable[] = { - { "account", SEC_ADMINISTRATOR, true, &HandleBanInfoAccountCommand, "", NULL }, - { "character", SEC_ADMINISTRATOR, true, &HandleBanInfoCharacterCommand, "", NULL }, - { "ip", SEC_ADMINISTRATOR, true, &HandleBanInfoIPCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "account", RBAC_PERM_COMMAND_BANINFO_ACCOUNT, true, &HandleBanInfoAccountCommand, "", NULL }, + { "character", RBAC_PERM_COMMAND_BANINFO_CHARACTER, true, &HandleBanInfoCharacterCommand, "", NULL }, + { "ip", RBAC_PERM_COMMAND_BANINFO_IP, true, &HandleBanInfoIPCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand banCommandTable[] = { - { "account", SEC_ADMINISTRATOR, true, &HandleBanAccountCommand, "", NULL }, - { "character", SEC_ADMINISTRATOR, true, &HandleBanCharacterCommand, "", NULL }, - { "playeraccount", SEC_ADMINISTRATOR, true, &HandleBanAccountByCharCommand, "", NULL }, - { "ip", SEC_ADMINISTRATOR, true, &HandleBanIPCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "account", RBAC_PERM_COMMAND_BAN_ACCOUNT, true, &HandleBanAccountCommand, "", NULL }, + { "character", RBAC_PERM_COMMAND_BAN_CHARACTER, true, &HandleBanCharacterCommand, "", NULL }, + { "playeraccount", RBAC_PERM_COMMAND_BAN_PLAYERACCOUNT, true, &HandleBanAccountByCharCommand, "", NULL }, + { "ip", RBAC_PERM_COMMAND_BAN_IP, true, &HandleBanIPCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand commandTable[] = { - { "ban", SEC_ADMINISTRATOR, true, NULL, "", banCommandTable }, - { "baninfo", SEC_ADMINISTRATOR, true, NULL, "", baninfoCommandTable }, - { "banlist", SEC_ADMINISTRATOR, true, NULL, "", banlistCommandTable }, - { "unban", SEC_ADMINISTRATOR, true, NULL, "", unbanCommandTable }, - { NULL, 0, false, NULL, "", NULL } + { "ban", RBAC_PERM_COMMAND_BAN, true, NULL, "", banCommandTable }, + { "baninfo", RBAC_PERM_COMMAND_BANINFO, true, NULL, "", baninfoCommandTable }, + { "banlist", RBAC_PERM_COMMAND_BANLIST, true, NULL, "", banlistCommandTable }, + { "unban", RBAC_PERM_COMMAND_UNBAN, true, NULL, "", unbanCommandTable }, + { NULL, 0, false, NULL, "", NULL } }; return commandTable; } @@ -436,21 +436,23 @@ public: do { time_t timeBan = time_t(fields2[0].GetUInt32()); - tm* tmBan = localtime(&timeBan); + tm tmBan; + ACE_OS::localtime_r(&timeBan, &tmBan); if (fields2[0].GetUInt32() == fields2[1].GetUInt32()) { handler->PSendSysMessage("|%-15.15s|%02d-%02d-%02d %02d:%02d| permanent |%-15.15s|%-15.15s|", - accountName.c_str(), tmBan->tm_year%100, tmBan->tm_mon+1, tmBan->tm_mday, tmBan->tm_hour, tmBan->tm_min, + accountName.c_str(), tmBan.tm_year%100, tmBan.tm_mon+1, tmBan.tm_mday, tmBan.tm_hour, tmBan.tm_min, fields2[2].GetCString(), fields2[3].GetCString()); } else { time_t timeUnban = time_t(fields2[1].GetUInt32()); - tm* tmUnban = localtime(&timeUnban); + tm tmUnban; + ACE_OS::localtime_r(&timeUnban, &tmUnban); handler->PSendSysMessage("|%-15.15s|%02d-%02d-%02d %02d:%02d|%02d-%02d-%02d %02d:%02d|%-15.15s|%-15.15s|", - accountName.c_str(), tmBan->tm_year%100, tmBan->tm_mon+1, tmBan->tm_mday, tmBan->tm_hour, tmBan->tm_min, - tmUnban->tm_year%100, tmUnban->tm_mon+1, tmUnban->tm_mday, tmUnban->tm_hour, tmUnban->tm_min, + accountName.c_str(), tmBan.tm_year%100, tmBan.tm_mon+1, tmBan.tm_mday, tmBan.tm_hour, tmBan.tm_min, + tmUnban.tm_year%100, tmUnban.tm_mon+1, tmUnban.tm_mday, tmUnban.tm_hour, tmUnban.tm_min, fields2[2].GetCString(), fields2[3].GetCString()); } } @@ -523,21 +525,23 @@ public: do { time_t timeBan = time_t(banFields[0].GetUInt32()); - tm* tmBan = localtime(&timeBan); + tm tmBan; + ACE_OS::localtime_r(&timeBan, &tmBan); if (banFields[0].GetUInt32() == banFields[1].GetUInt32()) { handler->PSendSysMessage("|%-15.15s|%02d-%02d-%02d %02d:%02d| permanent |%-15.15s|%-15.15s|", - char_name.c_str(), tmBan->tm_year%100, tmBan->tm_mon+1, tmBan->tm_mday, tmBan->tm_hour, tmBan->tm_min, + char_name.c_str(), tmBan.tm_year%100, tmBan.tm_mon+1, tmBan.tm_mday, tmBan.tm_hour, tmBan.tm_min, banFields[2].GetCString(), banFields[3].GetCString()); } else { time_t timeUnban = time_t(banFields[1].GetUInt32()); - tm* tmUnban = localtime(&timeUnban); + tm tmUnban; + ACE_OS::localtime_r(&timeUnban, &tmUnban); handler->PSendSysMessage("|%-15.15s|%02d-%02d-%02d %02d:%02d|%02d-%02d-%02d %02d:%02d|%-15.15s|%-15.15s|", - char_name.c_str(), tmBan->tm_year%100, tmBan->tm_mon+1, tmBan->tm_mday, tmBan->tm_hour, tmBan->tm_min, - tmUnban->tm_year%100, tmUnban->tm_mon+1, tmUnban->tm_mday, tmUnban->tm_hour, tmUnban->tm_min, + char_name.c_str(), tmBan.tm_year%100, tmBan.tm_mon+1, tmBan.tm_mday, tmBan.tm_hour, tmBan.tm_min, + tmUnban.tm_year%100, tmUnban.tm_mon+1, tmUnban.tm_mday, tmUnban.tm_hour, tmUnban.tm_min, banFields[2].GetCString(), banFields[3].GetCString()); } } @@ -602,20 +606,22 @@ public: handler->SendSysMessage("-------------------------------------------------------------------------------"); Field* fields = result->Fetch(); time_t timeBan = time_t(fields[1].GetUInt32()); - tm* tmBan = localtime(&timeBan); + tm tmBan; + ACE_OS::localtime_r(&timeBan, &tmBan); if (fields[1].GetUInt32() == fields[2].GetUInt32()) { handler->PSendSysMessage("|%-15.15s|%02d-%02d-%02d %02d:%02d| permanent |%-15.15s|%-15.15s|", - fields[0].GetCString(), tmBan->tm_year%100, tmBan->tm_mon+1, tmBan->tm_mday, tmBan->tm_hour, tmBan->tm_min, + fields[0].GetCString(), tmBan.tm_year%100, tmBan.tm_mon+1, tmBan.tm_mday, tmBan.tm_hour, tmBan.tm_min, fields[3].GetCString(), fields[4].GetCString()); } else { time_t timeUnban = time_t(fields[2].GetUInt32()); - tm* tmUnban = localtime(&timeUnban); + tm tmUnban; + ACE_OS::localtime_r(&timeUnban, &tmUnban); handler->PSendSysMessage("|%-15.15s|%02d-%02d-%02d %02d:%02d|%02d-%02d-%02d %02d:%02d|%-15.15s|%-15.15s|", - fields[0].GetCString(), tmBan->tm_year%100, tmBan->tm_mon+1, tmBan->tm_mday, tmBan->tm_hour, tmBan->tm_min, - tmUnban->tm_year%100, tmUnban->tm_mon+1, tmUnban->tm_mday, tmUnban->tm_hour, tmUnban->tm_min, + fields[0].GetCString(), tmBan.tm_year%100, tmBan.tm_mon+1, tmBan.tm_mday, tmBan.tm_hour, tmBan.tm_min, + tmUnban.tm_year%100, tmUnban.tm_mon+1, tmUnban.tm_mday, tmUnban.tm_hour, tmUnban.tm_min, fields[3].GetCString(), fields[4].GetCString()); } } diff --git a/src/server/scripts/Commands/cs_bf.cpp b/src/server/scripts/Commands/cs_bf.cpp index 4593a88cc90..0b239219ddd 100644 --- a/src/server/scripts/Commands/cs_bf.cpp +++ b/src/server/scripts/Commands/cs_bf.cpp @@ -35,17 +35,17 @@ public: { static ChatCommand battlefieldcommandTable[] = { - { "start", SEC_ADMINISTRATOR, false, &HandleBattlefieldStart, "", NULL }, - { "stop", SEC_ADMINISTRATOR, false, &HandleBattlefieldEnd, "", NULL }, - { "switch", SEC_ADMINISTRATOR, false, &HandleBattlefieldSwitch, "", NULL }, - { "timer", SEC_ADMINISTRATOR, false, &HandleBattlefieldTimer, "", NULL }, - { "enable", SEC_ADMINISTRATOR, false, &HandleBattlefieldEnable, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "start", RBAC_PERM_COMMAND_BF_START, false, &HandleBattlefieldStart, "", NULL }, + { "stop", RBAC_PERM_COMMAND_BF_STOP, false, &HandleBattlefieldEnd, "", NULL }, + { "switch", RBAC_PERM_COMMAND_BF_SWITCH, false, &HandleBattlefieldSwitch, "", NULL }, + { "timer", RBAC_PERM_COMMAND_BF_TIMER, false, &HandleBattlefieldTimer, "", NULL }, + { "enable", RBAC_PERM_COMMAND_BF_ENABLE, false, &HandleBattlefieldEnable, "", NULL }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand commandTable[] = { - { "bf", SEC_ADMINISTRATOR, false, NULL, "", battlefieldcommandTable }, - { NULL, 0, false, NULL, "", NULL } + { "bf", RBAC_PERM_COMMAND_BF, false, NULL, "", battlefieldcommandTable }, + { NULL, 0, false, NULL, "", NULL } }; return commandTable; } diff --git a/src/server/scripts/Commands/cs_cast.cpp b/src/server/scripts/Commands/cs_cast.cpp index 1dbfb0c2b8a..cbcbbd214b3 100644 --- a/src/server/scripts/Commands/cs_cast.cpp +++ b/src/server/scripts/Commands/cs_cast.cpp @@ -37,18 +37,18 @@ public: { static ChatCommand castCommandTable[] = { - { "back", SEC_ADMINISTRATOR, false, &HandleCastBackCommand, "", NULL }, - { "dist", SEC_ADMINISTRATOR, false, &HandleCastDistCommand, "", NULL }, - { "self", SEC_ADMINISTRATOR, false, &HandleCastSelfCommand, "", NULL }, - { "target", SEC_ADMINISTRATOR, false, &HandleCastTargetCommad, "", NULL }, - { "dest", SEC_ADMINISTRATOR, false, &HandleCastDestCommand, "", NULL }, - { "", SEC_ADMINISTRATOR, false, &HandleCastCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "back", RBAC_PERM_COMMAND_CAST_BACK, false, &HandleCastBackCommand, "", NULL }, + { "dist", RBAC_PERM_COMMAND_CAST_DIST, false, &HandleCastDistCommand, "", NULL }, + { "self", RBAC_PERM_COMMAND_CAST_SELF, false, &HandleCastSelfCommand, "", NULL }, + { "target", RBAC_PERM_COMMAND_CAST_TARGET, false, &HandleCastTargetCommad, "", NULL }, + { "dest", RBAC_PERM_COMMAND_CAST_DEST, false, &HandleCastDestCommand, "", NULL }, + { "", RBAC_PERM_COMMAND_CAST, false, &HandleCastCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand commandTable[] = { - { "cast", SEC_ADMINISTRATOR, false, NULL, "", castCommandTable }, - { NULL, 0, false, NULL, "", NULL } + { "cast", RBAC_PERM_COMMAND_CAST, false, NULL, "", castCommandTable }, + { NULL, 0, false, NULL, "", NULL } }; return commandTable; } diff --git a/src/server/scripts/Commands/cs_character.cpp b/src/server/scripts/Commands/cs_character.cpp index 3b0e92a6905..4a69e9cc61b 100644 --- a/src/server/scripts/Commands/cs_character.cpp +++ b/src/server/scripts/Commands/cs_character.cpp @@ -39,39 +39,39 @@ public: { static ChatCommand pdumpCommandTable[] = { - { "load", SEC_ADMINISTRATOR, true, &HandlePDumpLoadCommand, "", NULL }, - { "write", SEC_ADMINISTRATOR, true, &HandlePDumpWriteCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "load", RBAC_PERM_COMMAND_PDUMP_LOAD, true, &HandlePDumpLoadCommand, "", NULL }, + { "write", RBAC_PERM_COMMAND_PDUMP_WRITE, true, &HandlePDumpWriteCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand characterDeletedCommandTable[] = { - { "delete", SEC_CONSOLE, true, &HandleCharacterDeletedDeleteCommand, "", NULL }, - { "list", SEC_ADMINISTRATOR, true, &HandleCharacterDeletedListCommand, "", NULL }, - { "restore", SEC_ADMINISTRATOR, true, &HandleCharacterDeletedRestoreCommand, "", NULL }, - { "old", SEC_CONSOLE, true, &HandleCharacterDeletedOldCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "delete", RBAC_PERM_COMMAND_CHARACTER_DELETED_DELETE, true, &HandleCharacterDeletedDeleteCommand, "", NULL }, + { "list", RBAC_PERM_COMMAND_CHARACTER_DELETED_LIST, true, &HandleCharacterDeletedListCommand, "", NULL }, + { "restore", RBAC_PERM_COMMAND_CHARACTER_DELETED_RESTORE, true, &HandleCharacterDeletedRestoreCommand, "", NULL }, + { "old", RBAC_PERM_COMMAND_CHARACTER_DELETED_OLD, true, &HandleCharacterDeletedOldCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand characterCommandTable[] = { - { "customize", SEC_GAMEMASTER, true, &HandleCharacterCustomizeCommand, "", NULL }, - { "changefaction", SEC_GAMEMASTER, true, &HandleCharacterChangeFactionCommand, "", NULL }, - { "changerace", SEC_GAMEMASTER, true, &HandleCharacterChangeRaceCommand, "", NULL }, - { "deleted", SEC_GAMEMASTER, true, NULL, "", characterDeletedCommandTable }, - { "erase", SEC_CONSOLE, true, &HandleCharacterEraseCommand, "", NULL }, - { "level", SEC_ADMINISTRATOR, true, &HandleCharacterLevelCommand, "", NULL }, - { "rename", SEC_GAMEMASTER, true, &HandleCharacterRenameCommand, "", NULL }, - { "reputation", SEC_GAMEMASTER, true, &HandleCharacterReputationCommand, "", NULL }, - { "titles", SEC_GAMEMASTER, true, &HandleCharacterTitlesCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "customize", RBAC_PERM_COMMAND_CHARACTER_CUSTOMIZE, true, &HandleCharacterCustomizeCommand, "", NULL }, + { "changefaction", RBAC_PERM_COMMAND_CHARACTER_CHANGEFACTION, true, &HandleCharacterChangeFactionCommand, "", NULL }, + { "changerace", RBAC_PERM_COMMAND_CHARACTER_CHANGERACE, true, &HandleCharacterChangeRaceCommand, "", NULL }, + { "deleted", RBAC_PERM_COMMAND_CHARACTER_DELETED, true, NULL, "", characterDeletedCommandTable }, + { "erase", RBAC_PERM_COMMAND_CHARACTER_ERASE, true, &HandleCharacterEraseCommand, "", NULL }, + { "level", RBAC_PERM_COMMAND_CHARACTER_LEVEL, true, &HandleCharacterLevelCommand, "", NULL }, + { "rename", RBAC_PERM_COMMAND_CHARACTER_RENAME, true, &HandleCharacterRenameCommand, "", NULL }, + { "reputation", RBAC_PERM_COMMAND_CHARACTER_REPUTATION, true, &HandleCharacterReputationCommand, "", NULL }, + { "titles", RBAC_PERM_COMMAND_CHARACTER_TITLES, true, &HandleCharacterTitlesCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand commandTable[] = { - { "character", SEC_GAMEMASTER, true, NULL, "", characterCommandTable }, - { "levelup", SEC_ADMINISTRATOR, false, &HandleLevelUpCommand, "", NULL }, - { "pdump", SEC_ADMINISTRATOR, true, NULL, "", pdumpCommandTable }, - { NULL, 0, false, NULL, "", NULL } + { "character", RBAC_PERM_COMMAND_CHARACTER, true, NULL, "", characterCommandTable }, + { "levelup", RBAC_PERM_COMMAND_LEVELUP, false, &HandleLevelUpCommand, "", NULL }, + { "pdump", RBAC_PERM_COMMAND_PDUMP, true, NULL, "", pdumpCommandTable }, + { NULL, 0, false, NULL, "", NULL } }; return commandTable; } diff --git a/src/server/scripts/Commands/cs_cheat.cpp b/src/server/scripts/Commands/cs_cheat.cpp index 854daebf975..6d27e2c4f0f 100644 --- a/src/server/scripts/Commands/cs_cheat.cpp +++ b/src/server/scripts/Commands/cs_cheat.cpp @@ -38,22 +38,22 @@ public: static ChatCommand cheatCommandTable[] = { - { "god", SEC_GAMEMASTER, false, &HandleGodModeCheatCommand, "", NULL }, - { "casttime", SEC_GAMEMASTER, false, &HandleCasttimeCheatCommand, "", NULL }, - { "cooldown", SEC_GAMEMASTER, false, &HandleCoolDownCheatCommand, "", NULL }, - { "power", SEC_GAMEMASTER, false, &HandlePowerCheatCommand, "", NULL }, - { "waterwalk", SEC_GAMEMASTER, false, &HandleWaterWalkCheatCommand, "", NULL }, - { "status", SEC_GAMEMASTER, false, &HandleCheatStatusCommand, "", NULL }, - { "taxi", SEC_GAMEMASTER, false, &HandleTaxiCheatCommand, "", NULL }, - { "explore", SEC_GAMEMASTER, false, &HandleExploreCheatCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "god", RBAC_PERM_COMMAND_CHEAT_GOD, false, &HandleGodModeCheatCommand, "", NULL }, + { "casttime", RBAC_PERM_COMMAND_CHEAT_CASTTIME, false, &HandleCasttimeCheatCommand, "", NULL }, + { "cooldown", RBAC_PERM_COMMAND_CHEAT_COOLDOWN, false, &HandleCoolDownCheatCommand, "", NULL }, + { "power", RBAC_PERM_COMMAND_CHEAT_POWER, false, &HandlePowerCheatCommand, "", NULL }, + { "waterwalk", RBAC_PERM_COMMAND_CHEAT_WATERWALK, false, &HandleWaterWalkCheatCommand, "", NULL }, + { "status", RBAC_PERM_COMMAND_CHEAT_STATUS, false, &HandleCheatStatusCommand, "", NULL }, + { "taxi", RBAC_PERM_COMMAND_CHEAT_TAXI, false, &HandleTaxiCheatCommand, "", NULL }, + { "explore", RBAC_PERM_COMMAND_CHEAT_EXPLORE, false, &HandleExploreCheatCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand commandTable[] = { - { "cheat", SEC_GAMEMASTER, false, NULL, "", cheatCommandTable }, - { NULL, 0, false, NULL, "", NULL } + { "cheat", RBAC_PERM_COMMAND_CHEAT, false, NULL, "", cheatCommandTable }, + { NULL, 0, false, NULL, "", NULL } }; return commandTable; } diff --git a/src/server/scripts/Commands/cs_debug.cpp b/src/server/scripts/Commands/cs_debug.cpp index 6ef84033312..52971d6553f 100644 --- a/src/server/scripts/Commands/cs_debug.cpp +++ b/src/server/scripts/Commands/cs_debug.cpp @@ -44,61 +44,61 @@ public: { static ChatCommand debugPlayCommandTable[] = { - { "cinematic", SEC_MODERATOR, false, &HandleDebugPlayCinematicCommand, "", NULL }, - { "movie", SEC_MODERATOR, false, &HandleDebugPlayMovieCommand, "", NULL }, - { "sound", SEC_MODERATOR, false, &HandleDebugPlaySoundCommand, "", NULL }, - { NULL, SEC_PLAYER, false, NULL, "", NULL } + { "cinematic", RBAC_PERM_COMMAND_DEBUG_PLAY_CINEMATIC, false, &HandleDebugPlayCinematicCommand, "", NULL }, + { "movie", RBAC_PERM_COMMAND_DEBUG_PLAY_MOVIE, false, &HandleDebugPlayMovieCommand, "", NULL }, + { "sound", RBAC_PERM_COMMAND_DEBUG_PLAY_SOUND, false, &HandleDebugPlaySoundCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand debugSendCommandTable[] = { - { "buyerror", SEC_ADMINISTRATOR, false, &HandleDebugSendBuyErrorCommand, "", NULL }, - { "channelnotify", SEC_ADMINISTRATOR, false, &HandleDebugSendChannelNotifyCommand, "", NULL }, - { "chatmmessage", SEC_ADMINISTRATOR, false, &HandleDebugSendChatMsgCommand, "", NULL }, - { "equiperror", SEC_ADMINISTRATOR, false, &HandleDebugSendEquipErrorCommand, "", NULL }, - { "largepacket", SEC_ADMINISTRATOR, false, &HandleDebugSendLargePacketCommand, "", NULL }, - { "opcode", SEC_ADMINISTRATOR, false, &HandleDebugSendOpcodeCommand, "", NULL }, - { "qpartymsg", SEC_ADMINISTRATOR, false, &HandleDebugSendQuestPartyMsgCommand, "", NULL }, - { "qinvalidmsg", SEC_ADMINISTRATOR, false, &HandleDebugSendQuestInvalidMsgCommand, "", NULL }, - { "sellerror", SEC_ADMINISTRATOR, false, &HandleDebugSendSellErrorCommand, "", NULL }, - { "setphaseshift", SEC_ADMINISTRATOR, false, &HandleDebugSendSetPhaseShiftCommand, "", NULL }, - { "spellfail", SEC_ADMINISTRATOR, false, &HandleDebugSendSpellFailCommand, "", NULL }, - { NULL, SEC_PLAYER, false, NULL, "", NULL } + { "buyerror", RBAC_PERM_COMMAND_DEBUG_SEND_BUYERROR, false, &HandleDebugSendBuyErrorCommand, "", NULL }, + { "channelnotify", RBAC_PERM_COMMAND_DEBUG_SEND_CHANNELNOTIFY, false, &HandleDebugSendChannelNotifyCommand, "", NULL }, + { "chatmessage", RBAC_PERM_COMMAND_DEBUG_SEND_CHATMESSAGE, false, &HandleDebugSendChatMsgCommand, "", NULL }, + { "equiperror", RBAC_PERM_COMMAND_DEBUG_SEND_EQUIPERROR, false, &HandleDebugSendEquipErrorCommand, "", NULL }, + { "largepacket", RBAC_PERM_COMMAND_DEBUG_SEND_LARGEPACKET, false, &HandleDebugSendLargePacketCommand, "", NULL }, + { "opcode", RBAC_PERM_COMMAND_DEBUG_SEND_OPCODE, false, &HandleDebugSendOpcodeCommand, "", NULL }, + { "qpartymsg", RBAC_PERM_COMMAND_DEBUG_SEND_QPARTYMSG, false, &HandleDebugSendQuestPartyMsgCommand, "", NULL }, + { "qinvalidmsg", RBAC_PERM_COMMAND_DEBUG_SEND_QINVALIDMSG, false, &HandleDebugSendQuestInvalidMsgCommand, "", NULL }, + { "sellerror", RBAC_PERM_COMMAND_DEBUG_SEND_SELLERROR, false, &HandleDebugSendSellErrorCommand, "", NULL }, + { "setphaseshift", RBAC_PERM_COMMAND_DEBUG_SEND_SETPHASESHIFT, false, &HandleDebugSendSetPhaseShiftCommand, "", NULL }, + { "spellfail", RBAC_PERM_COMMAND_DEBUG_SEND_SPELLFAIL, false, &HandleDebugSendSpellFailCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand debugCommandTable[] = { - { "setbit", SEC_ADMINISTRATOR, false, &HandleDebugSet32BitCommand, "", NULL }, - { "threat", SEC_ADMINISTRATOR, false, &HandleDebugThreatListCommand, "", NULL }, - { "hostil", SEC_ADMINISTRATOR, false, &HandleDebugHostileRefListCommand, "", NULL }, - { "anim", SEC_GAMEMASTER, false, &HandleDebugAnimCommand, "", NULL }, - { "arena", SEC_ADMINISTRATOR, false, &HandleDebugArenaCommand, "", NULL }, - { "bg", SEC_ADMINISTRATOR, false, &HandleDebugBattlegroundCommand, "", NULL }, - { "getitemstate", SEC_ADMINISTRATOR, false, &HandleDebugGetItemStateCommand, "", NULL }, - { "lootrecipient", SEC_GAMEMASTER, false, &HandleDebugGetLootRecipientCommand, "", NULL }, - { "getvalue", SEC_ADMINISTRATOR, false, &HandleDebugGetValueCommand, "", NULL }, - { "getitemvalue", SEC_ADMINISTRATOR, false, &HandleDebugGetItemValueCommand, "", NULL }, - { "Mod32Value", SEC_ADMINISTRATOR, false, &HandleDebugMod32ValueCommand, "", NULL }, - { "play", SEC_MODERATOR, false, NULL, "", debugPlayCommandTable }, - { "send", SEC_ADMINISTRATOR, false, NULL, "", debugSendCommandTable }, - { "setaurastate", SEC_ADMINISTRATOR, false, &HandleDebugSetAuraStateCommand, "", NULL }, - { "setitemvalue", SEC_ADMINISTRATOR, false, &HandleDebugSetItemValueCommand, "", NULL }, - { "setvalue", SEC_ADMINISTRATOR, false, &HandleDebugSetValueCommand, "", NULL }, - { "spawnvehicle", SEC_ADMINISTRATOR, false, &HandleDebugSpawnVehicleCommand, "", NULL }, - { "setvid", SEC_ADMINISTRATOR, false, &HandleDebugSetVehicleIdCommand, "", NULL }, - { "entervehicle", SEC_ADMINISTRATOR, false, &HandleDebugEnterVehicleCommand, "", NULL }, - { "uws", SEC_ADMINISTRATOR, false, &HandleDebugUpdateWorldStateCommand, "", NULL }, - { "update", SEC_ADMINISTRATOR, false, &HandleDebugUpdateCommand, "", NULL }, - { "itemexpire", SEC_ADMINISTRATOR, false, &HandleDebugItemExpireCommand, "", NULL }, - { "areatriggers", SEC_ADMINISTRATOR, false, &HandleDebugAreaTriggersCommand, "", NULL }, - { "los", SEC_MODERATOR, false, &HandleDebugLoSCommand, "", NULL }, - { "moveflags", SEC_ADMINISTRATOR, false, &HandleDebugMoveflagsCommand, "", NULL }, - { "phase", SEC_MODERATOR, false, &HandleDebugPhaseCommand, "", NULL }, - { NULL, SEC_PLAYER, false, NULL, "", NULL } + { "setbit", RBAC_PERM_COMMAND_DEBUG_SETBIT, false, &HandleDebugSet32BitCommand, "", NULL }, + { "threat", RBAC_PERM_COMMAND_DEBUG_THREAT, false, &HandleDebugThreatListCommand, "", NULL }, + { "hostil", RBAC_PERM_COMMAND_DEBUG_HOSTIL, false, &HandleDebugHostileRefListCommand, "", NULL }, + { "anim", RBAC_PERM_COMMAND_DEBUG_ANIM, false, &HandleDebugAnimCommand, "", NULL }, + { "arena", RBAC_PERM_COMMAND_DEBUG_ARENA, false, &HandleDebugArenaCommand, "", NULL }, + { "bg", RBAC_PERM_COMMAND_DEBUG_BG, false, &HandleDebugBattlegroundCommand, "", NULL }, + { "getitemstate", RBAC_PERM_COMMAND_DEBUG_GETITEMSTATE, false, &HandleDebugGetItemStateCommand, "", NULL }, + { "lootrecipient", RBAC_PERM_COMMAND_DEBUG_LOOTRECIPIENT, false, &HandleDebugGetLootRecipientCommand, "", NULL }, + { "getvalue", RBAC_PERM_COMMAND_DEBUG_GETVALUE, false, &HandleDebugGetValueCommand, "", NULL }, + { "getitemvalue", RBAC_PERM_COMMAND_DEBUG_GETITEMVALUE, false, &HandleDebugGetItemValueCommand, "", NULL }, + { "Mod32Value", RBAC_PERM_COMMAND_DEBUG_MOD32VALUE, false, &HandleDebugMod32ValueCommand, "", NULL }, + { "play", RBAC_PERM_COMMAND_DEBUG_PLAY, false, NULL, "", debugPlayCommandTable }, + { "send", RBAC_PERM_COMMAND_DEBUG_SEND, false, NULL, "", debugSendCommandTable }, + { "setaurastate", RBAC_PERM_COMMAND_DEBUG_SETAURASTATE, false, &HandleDebugSetAuraStateCommand, "", NULL }, + { "setitemvalue", RBAC_PERM_COMMAND_DEBUG_SETITEMVALUE, false, &HandleDebugSetItemValueCommand, "", NULL }, + { "setvalue", RBAC_PERM_COMMAND_DEBUG_SETVALUE, false, &HandleDebugSetValueCommand, "", NULL }, + { "spawnvehicle", RBAC_PERM_COMMAND_DEBUG_SPAWNVEHICLE, false, &HandleDebugSpawnVehicleCommand, "", NULL }, + { "setvid", RBAC_PERM_COMMAND_DEBUG_SETVID, false, &HandleDebugSetVehicleIdCommand, "", NULL }, + { "entervehicle", RBAC_PERM_COMMAND_DEBUG_ENTERVEHICLE, false, &HandleDebugEnterVehicleCommand, "", NULL }, + { "uws", RBAC_PERM_COMMAND_DEBUG_UWS, false, &HandleDebugUpdateWorldStateCommand, "", NULL }, + { "update", RBAC_PERM_COMMAND_DEBUG_UPDATE, false, &HandleDebugUpdateCommand, "", NULL }, + { "itemexpire", RBAC_PERM_COMMAND_DEBUG_ITEMEXPIRE, false, &HandleDebugItemExpireCommand, "", NULL }, + { "areatriggers", RBAC_PERM_COMMAND_DEBUG_AREATRIGGERS, false, &HandleDebugAreaTriggersCommand, "", NULL }, + { "los", RBAC_PERM_COMMAND_DEBUG_LOS, false, &HandleDebugLoSCommand, "", NULL }, + { "moveflags", RBAC_PERM_COMMAND_DEBUG_MOVEFLAGS, false, &HandleDebugMoveflagsCommand, "", NULL }, + { "phase", RBAC_PERM_COMMAND_DEBUG_PHASE, false, &HandleDebugPhaseCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand commandTable[] = { - { "debug", SEC_MODERATOR, true, NULL, "", debugCommandTable }, - { "wpgps", SEC_ADMINISTRATOR, false, &HandleWPGPSCommand, "", NULL }, - { NULL, SEC_PLAYER, false, NULL, "", NULL } + { "debug", RBAC_PERM_COMMAND_DEBUG, true, NULL, "", debugCommandTable }, + { "wpgps", RBAC_PERM_COMMAND_WPGPS, false, &HandleWPGPSCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } }; return commandTable; } @@ -265,7 +265,7 @@ public: unit = player; std::ifstream ifs("opcode.txt"); - if (ifs.bad()) + if (ifs.fail()) return false; // remove comments from file @@ -1325,6 +1325,8 @@ public: uint32 moveFlags = (uint32)atoi(mask1); target->SetUnitMovementFlags(moveFlags); + /// @fixme: port master's HandleDebugMoveflagsCommand; flags need different handling + if (mask2) { uint32 moveFlagsExtra = uint32(atoi(mask2)); diff --git a/src/server/scripts/Commands/cs_deserter.cpp b/src/server/scripts/Commands/cs_deserter.cpp index 285b68a6162..aa0d34e3638 100644 --- a/src/server/scripts/Commands/cs_deserter.cpp +++ b/src/server/scripts/Commands/cs_deserter.cpp @@ -47,27 +47,27 @@ public: { static ChatCommand deserterInstanceCommandTable[] = { - { "add", SEC_ADMINISTRATOR, false, &HandleDeserterInstanceAdd, "", NULL }, - { "remove", SEC_ADMINISTRATOR, false, &HandleDeserterInstanceRemove, "", NULL }, - { NULL, SEC_PLAYER, false, NULL, "", NULL } + { "add", RBAC_PERM_COMMAND_DESERTER_INSTANCE_ADD, false, &HandleDeserterInstanceAdd, "", NULL }, + { "remove", RBAC_PERM_COMMAND_DESERTER_INSTANCE_REMOVE, false, &HandleDeserterInstanceRemove, "", NULL }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand deserterBGCommandTable[] = { - { "add", SEC_ADMINISTRATOR, false, &HandleDeserterBGAdd, "", NULL }, - { "remove", SEC_ADMINISTRATOR, false, &HandleDeserterBGRemove, "", NULL }, - { NULL, SEC_PLAYER, false, NULL, "", NULL } + { "add", RBAC_PERM_COMMAND_DESERTER_BG_ADD, false, &HandleDeserterBGAdd, "", NULL }, + { "remove", RBAC_PERM_COMMAND_DESERTER_BG_REMOVE, false, &HandleDeserterBGRemove, "", NULL }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand deserterCommandTable[] = { - { "instance", SEC_ADMINISTRATOR, false, NULL, "", deserterInstanceCommandTable }, - { "bg", SEC_ADMINISTRATOR, false, NULL, "", deserterBGCommandTable }, - { NULL, SEC_PLAYER, false, NULL, "", NULL } + { "instance", RBAC_PERM_COMMAND_DESERTER_INSTANCE, false, NULL, "", deserterInstanceCommandTable }, + { "bg", RBAC_PERM_COMMAND_DESERTER_BG, false, NULL, "", deserterBGCommandTable }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand commandTable[] = { - { "deserter", SEC_ADMINISTRATOR, false, NULL, "", deserterCommandTable }, - { NULL, SEC_PLAYER, false, NULL, "", NULL } + { "deserter", RBAC_PERM_COMMAND_DESERTER, false, NULL, "", deserterCommandTable }, + { NULL, 0, false, NULL, "", NULL } }; return commandTable; } diff --git a/src/server/scripts/Commands/cs_disable.cpp b/src/server/scripts/Commands/cs_disable.cpp index e6acb17373f..1b9955ddaf2 100644 --- a/src/server/scripts/Commands/cs_disable.cpp +++ b/src/server/scripts/Commands/cs_disable.cpp @@ -41,38 +41,38 @@ public: { static ChatCommand removeDisableCommandTable[] = { - { "spell", SEC_ADMINISTRATOR, true, &HandleRemoveDisableSpellCommand, "", NULL }, - { "quest", SEC_ADMINISTRATOR, true, &HandleRemoveDisableQuestCommand, "", NULL }, - { "map", SEC_ADMINISTRATOR, true, &HandleRemoveDisableMapCommand, "", NULL }, - { "battleground", SEC_ADMINISTRATOR, true, &HandleRemoveDisableBattlegroundCommand, "", NULL }, - { "achievement_criteria", SEC_ADMINISTRATOR, true, &HandleRemoveDisableAchievementCriteriaCommand, "", NULL }, - { "outdoorpvp", SEC_ADMINISTRATOR, true, &HandleRemoveDisableOutdoorPvPCommand, "", NULL }, - { "vmap", SEC_ADMINISTRATOR, true, &HandleRemoveDisableVmapCommand, "", NULL }, - { "mmap", SEC_ADMINISTRATOR, true, &HandleRemoveDisableMMapCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "spell", RBAC_PERM_COMMAND_DISABLE_REMOVE_SPELL, true, &HandleRemoveDisableSpellCommand, "", NULL }, + { "quest", RBAC_PERM_COMMAND_DISABLE_REMOVE_QUEST, true, &HandleRemoveDisableQuestCommand, "", NULL }, + { "map", RBAC_PERM_COMMAND_DISABLE_REMOVE_MAP, true, &HandleRemoveDisableMapCommand, "", NULL }, + { "battleground", RBAC_PERM_COMMAND_DISABLE_REMOVE_BATTLEGROUND, true, &HandleRemoveDisableBattlegroundCommand, "", NULL }, + { "achievement_criteria", RBAC_PERM_COMMAND_DISABLE_REMOVE_ACHIEVEMENT_CRITERIA, true, &HandleRemoveDisableAchievementCriteriaCommand, "", NULL }, + { "outdoorpvp", RBAC_PERM_COMMAND_DISABLE_REMOVE_OUTDOORPVP, true, &HandleRemoveDisableOutdoorPvPCommand, "", NULL }, + { "vmap", RBAC_PERM_COMMAND_DISABLE_REMOVE_VMAP, true, &HandleRemoveDisableVmapCommand, "", NULL }, + { "mmap", RBAC_PERM_COMMAND_DISABLE_REMOVE_MMAP, true, &HandleRemoveDisableMMapCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand addDisableCommandTable[] = { - { "spell", SEC_ADMINISTRATOR, true, &HandleAddDisableSpellCommand, "", NULL }, - { "quest", SEC_ADMINISTRATOR, true, &HandleAddDisableQuestCommand, "", NULL }, - { "map", SEC_ADMINISTRATOR, true, &HandleAddDisableMapCommand, "", NULL }, - { "battleground", SEC_ADMINISTRATOR, true, &HandleAddDisableBattlegroundCommand, "", NULL }, - { "achievement_criteria", SEC_ADMINISTRATOR, true, &HandleAddDisableAchievementCriteriaCommand, "", NULL }, - { "outdoorpvp", SEC_ADMINISTRATOR, true, &HandleAddDisableOutdoorPvPCommand, "", NULL }, - { "vmap", SEC_ADMINISTRATOR, true, &HandleAddDisableVmapCommand, "", NULL }, - { "mmap", SEC_ADMINISTRATOR, true, &HandleAddDisableMMapCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "spell", RBAC_PERM_COMMAND_DISABLE_ADD_SPELL, true, &HandleAddDisableSpellCommand, "", NULL }, + { "quest", RBAC_PERM_COMMAND_DISABLE_ADD_QUEST, true, &HandleAddDisableQuestCommand, "", NULL }, + { "map", RBAC_PERM_COMMAND_DISABLE_ADD_MAP, true, &HandleAddDisableMapCommand, "", NULL }, + { "battleground", RBAC_PERM_COMMAND_DISABLE_ADD_BATTLEGROUND, true, &HandleAddDisableBattlegroundCommand, "", NULL }, + { "achievement_criteria", RBAC_PERM_COMMAND_DISABLE_ADD_ACHIEVEMENT_CRITERIA, true, &HandleAddDisableAchievementCriteriaCommand, "", NULL }, + { "outdoorpvp", RBAC_PERM_COMMAND_DISABLE_ADD_OUTDOORPVP, true, &HandleAddDisableOutdoorPvPCommand, "", NULL }, + { "vmap", RBAC_PERM_COMMAND_DISABLE_ADD_VMAP, true, &HandleAddDisableVmapCommand, "", NULL }, + { "mmap", RBAC_PERM_COMMAND_DISABLE_ADD_MMAP, true, &HandleAddDisableMMapCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand disableCommandTable[] = { - { "add", SEC_ADMINISTRATOR, true, NULL, "", addDisableCommandTable }, - { "remove", SEC_ADMINISTRATOR, true, NULL, "", removeDisableCommandTable }, - { NULL, 0, false, NULL, "", NULL } + { "add", RBAC_PERM_COMMAND_DISABLE_ADD, true, NULL, "", addDisableCommandTable }, + { "remove", RBAC_PERM_COMMAND_DISABLE_REMOVE, true, NULL, "", removeDisableCommandTable }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand commandTable[] = { - { "disable", SEC_ADMINISTRATOR, false, NULL, "", disableCommandTable }, - { NULL, 0, false, NULL, "", NULL } + { "disable", RBAC_PERM_COMMAND_DISABLE, false, NULL, "", disableCommandTable }, + { NULL, 0, false, NULL, "", NULL } }; return commandTable; } @@ -357,7 +357,7 @@ public: if (!*args) return false; - return HandleAddDisables(handler, args, DISABLE_TYPE_MAP); + return HandleRemoveDisables(handler, args, DISABLE_TYPE_MAP); } static bool HandleRemoveDisableBattlegroundCommand(ChatHandler* handler, char const* args) diff --git a/src/server/scripts/Commands/cs_event.cpp b/src/server/scripts/Commands/cs_event.cpp index 7a5977074a3..491ae65e0ca 100644 --- a/src/server/scripts/Commands/cs_event.cpp +++ b/src/server/scripts/Commands/cs_event.cpp @@ -37,16 +37,16 @@ public: { static ChatCommand eventCommandTable[] = { - { "activelist", SEC_GAMEMASTER, true, &HandleEventActiveListCommand, "", NULL }, - { "start", SEC_GAMEMASTER, true, &HandleEventStartCommand, "", NULL }, - { "stop", SEC_GAMEMASTER, true, &HandleEventStopCommand, "", NULL }, - { "", SEC_GAMEMASTER, true, &HandleEventInfoCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "activelist", RBAC_PERM_COMMAND_EVENT_ACTIVELIST, true, &HandleEventActiveListCommand, "", NULL }, + { "start", RBAC_PERM_COMMAND_EVENT_START, true, &HandleEventStartCommand, "", NULL }, + { "stop", RBAC_PERM_COMMAND_EVENT_STOP, true, &HandleEventStopCommand, "", NULL }, + { "", RBAC_PERM_COMMAND_EVENT, true, &HandleEventInfoCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand commandTable[] = { - { "event", SEC_GAMEMASTER, false, NULL, "", eventCommandTable }, - { NULL, 0, false, NULL, "", NULL } + { "event", RBAC_PERM_COMMAND_EVENT, false, NULL, "", eventCommandTable }, + { NULL, 0, false, NULL, "", NULL } }; return commandTable; } diff --git a/src/server/scripts/Commands/cs_gm.cpp b/src/server/scripts/Commands/cs_gm.cpp index 7b6e57bdacb..888afcfdf2f 100644 --- a/src/server/scripts/Commands/cs_gm.cpp +++ b/src/server/scripts/Commands/cs_gm.cpp @@ -40,18 +40,18 @@ public: { static ChatCommand gmCommandTable[] = { - { "chat", SEC_MODERATOR, false, &HandleGMChatCommand, "", NULL }, - { "fly", SEC_ADMINISTRATOR, false, &HandleGMFlyCommand, "", NULL }, - { "ingame", SEC_PLAYER, true, &HandleGMListIngameCommand, "", NULL }, - { "list", SEC_ADMINISTRATOR, true, &HandleGMListFullCommand, "", NULL }, - { "visible", SEC_MODERATOR, false, &HandleGMVisibleCommand, "", NULL }, - { "", SEC_MODERATOR, false, &HandleGMCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "chat", RBAC_PERM_COMMAND_GM_CHAT, false, &HandleGMChatCommand, "", NULL }, + { "fly", RBAC_PERM_COMMAND_GM_FLY, false, &HandleGMFlyCommand, "", NULL }, + { "ingame", RBAC_PERM_COMMAND_GM_INGAME, true, &HandleGMListIngameCommand, "", NULL }, + { "list", RBAC_PERM_COMMAND_GM_LIST, true, &HandleGMListFullCommand, "", NULL }, + { "visible", RBAC_PERM_COMMAND_GM_VISIBLE, false, &HandleGMVisibleCommand, "", NULL }, + { "", RBAC_PERM_COMMAND_GM, false, &HandleGMCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand commandTable[] = { - { "gm", SEC_MODERATOR, false, NULL, "", gmCommandTable }, - { NULL, 0, false, NULL, "", NULL } + { "gm", RBAC_PERM_COMMAND_GM, false, NULL, "", gmCommandTable }, + { NULL, 0, false, NULL, "", NULL } }; return commandTable; } diff --git a/src/server/scripts/Commands/cs_go.cpp b/src/server/scripts/Commands/cs_go.cpp index 1c3781e73d3..48c1e8eb3fa 100644 --- a/src/server/scripts/Commands/cs_go.cpp +++ b/src/server/scripts/Commands/cs_go.cpp @@ -39,23 +39,23 @@ public: { static ChatCommand goCommandTable[] = { - { "creature", SEC_MODERATOR, false, &HandleGoCreatureCommand, "", NULL }, - { "graveyard", SEC_MODERATOR, false, &HandleGoGraveyardCommand, "", NULL }, - { "grid", SEC_MODERATOR, false, &HandleGoGridCommand, "", NULL }, - { "object", SEC_MODERATOR, false, &HandleGoObjectCommand, "", NULL }, - { "taxinode", SEC_MODERATOR, false, &HandleGoTaxinodeCommand, "", NULL }, - { "trigger", SEC_MODERATOR, false, &HandleGoTriggerCommand, "", NULL }, - { "zonexy", SEC_MODERATOR, false, &HandleGoZoneXYCommand, "", NULL }, - { "xyz", SEC_MODERATOR, false, &HandleGoXYZCommand, "", NULL }, - { "ticket", SEC_MODERATOR, false, &HandleGoTicketCommand, "", NULL }, - { "", SEC_MODERATOR, false, &HandleGoXYZCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "creature", RBAC_PERM_COMMAND_GO_CREATURE, false, &HandleGoCreatureCommand, "", NULL }, + { "graveyard", RBAC_PERM_COMMAND_GO_GRAVEYARD, false, &HandleGoGraveyardCommand, "", NULL }, + { "grid", RBAC_PERM_COMMAND_GO_GRID, false, &HandleGoGridCommand, "", NULL }, + { "object", RBAC_PERM_COMMAND_GO_OBJECT, false, &HandleGoObjectCommand, "", NULL }, + { "taxinode", RBAC_PERM_COMMAND_GO_TAXINODE, false, &HandleGoTaxinodeCommand, "", NULL }, + { "trigger", RBAC_PERM_COMMAND_GO_TRIGGER, false, &HandleGoTriggerCommand, "", NULL }, + { "zonexy", RBAC_PERM_COMMAND_GO_ZONEXY, false, &HandleGoZoneXYCommand, "", NULL }, + { "xyz", RBAC_PERM_COMMAND_GO_XYZ, false, &HandleGoXYZCommand, "", NULL }, + { "ticket", RBAC_PERM_COMMAND_GO_TICKET, false, &HandleGoTicketCommand, "", NULL }, + { "", RBAC_PERM_COMMAND_GO, false, &HandleGoXYZCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand commandTable[] = { - { "go", SEC_MODERATOR, false, NULL, "", goCommandTable }, - { NULL, 0, false, NULL, "", NULL } + { "go", RBAC_PERM_COMMAND_GO, false, NULL, "", goCommandTable }, + { NULL, 0, false, NULL, "", NULL } }; return commandTable; } diff --git a/src/server/scripts/Commands/cs_gobject.cpp b/src/server/scripts/Commands/cs_gobject.cpp index 4473000bc3b..d3a1849d56f 100644 --- a/src/server/scripts/Commands/cs_gobject.cpp +++ b/src/server/scripts/Commands/cs_gobject.cpp @@ -41,33 +41,33 @@ public: { static ChatCommand gobjectAddCommandTable[] = { - { "temp", SEC_GAMEMASTER, false, &HandleGameObjectAddTempCommand, "", NULL }, - { "", SEC_GAMEMASTER, false, &HandleGameObjectAddCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "temp", RBAC_PERM_COMMAND_GOBJECT_ADD_TEMP, false, &HandleGameObjectAddTempCommand, "", NULL }, + { "", RBAC_PERM_COMMAND_GOBJECT_ADD, false, &HandleGameObjectAddCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand gobjectSetCommandTable[] = { - { "phase", SEC_GAMEMASTER, false, &HandleGameObjectSetPhaseCommand, "", NULL }, - { "state", SEC_GAMEMASTER, false, &HandleGameObjectSetStateCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "phase", RBAC_PERM_COMMAND_GOBJECT_SET_PHASE, false, &HandleGameObjectSetPhaseCommand, "", NULL }, + { "state", RBAC_PERM_COMMAND_GOBJECT_SET_STATE, false, &HandleGameObjectSetStateCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand gobjectCommandTable[] = { - { "activate", SEC_GAMEMASTER, false, &HandleGameObjectActivateCommand, "", NULL }, - { "delete", SEC_GAMEMASTER, false, &HandleGameObjectDeleteCommand, "", NULL }, - { "info", SEC_GAMEMASTER, false, &HandleGameObjectInfoCommand, "", NULL }, - { "move", SEC_GAMEMASTER, false, &HandleGameObjectMoveCommand, "", NULL }, - { "near", SEC_GAMEMASTER, false, &HandleGameObjectNearCommand, "", NULL }, - { "target", SEC_GAMEMASTER, false, &HandleGameObjectTargetCommand, "", NULL }, - { "turn", SEC_GAMEMASTER, false, &HandleGameObjectTurnCommand, "", NULL }, - { "add", SEC_GAMEMASTER, false, NULL, "", gobjectAddCommandTable }, - { "set", SEC_GAMEMASTER, false, NULL, "", gobjectSetCommandTable }, - { NULL, 0, false, NULL, "", NULL } + { "activate", RBAC_PERM_COMMAND_GOBJECT_ACTIVATE, false, &HandleGameObjectActivateCommand, "", NULL }, + { "delete", RBAC_PERM_COMMAND_GOBJECT_DELETE, false, &HandleGameObjectDeleteCommand, "", NULL }, + { "info", RBAC_PERM_COMMAND_GOBJECT_INFO, false, &HandleGameObjectInfoCommand, "", NULL }, + { "move", RBAC_PERM_COMMAND_GOBJECT_MOVE, false, &HandleGameObjectMoveCommand, "", NULL }, + { "near", RBAC_PERM_COMMAND_GOBJECT_NEAR, false, &HandleGameObjectNearCommand, "", NULL }, + { "target", RBAC_PERM_COMMAND_GOBJECT_TARGET, false, &HandleGameObjectTargetCommand, "", NULL }, + { "turn", RBAC_PERM_COMMAND_GOBJECT_TURN, false, &HandleGameObjectTurnCommand, "", NULL }, + { "add", RBAC_PERM_COMMAND_GOBJECT_ADD, false, NULL, "", gobjectAddCommandTable }, + { "set", RBAC_PERM_COMMAND_GOBJECT_SET, false, NULL, "", gobjectSetCommandTable }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand commandTable[] = { - { "gobject", SEC_GAMEMASTER, false, NULL, "", gobjectCommandTable }, - { NULL, 0, false, NULL, "", NULL } + { "gobject", RBAC_PERM_COMMAND_GOBJECT, false, NULL, "", gobjectCommandTable }, + { NULL, 0, false, NULL, "", NULL } }; return commandTable; } diff --git a/src/server/scripts/Commands/cs_group.cpp b/src/server/scripts/Commands/cs_group.cpp new file mode 100644 index 00000000000..784ff216c41 --- /dev/null +++ b/src/server/scripts/Commands/cs_group.cpp @@ -0,0 +1,338 @@ +/* + * Copyright (C) 2008-2013 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 "Chat.h" +#include "Language.h" +#include "LFG.h" +#include "Player.h" +#include "ObjectMgr.h" +#include "GroupMgr.h" +#include "ScriptMgr.h" + +class group_commandscript : public CommandScript +{ +public: + group_commandscript() : CommandScript("group_commandscript") { } + + ChatCommand* GetCommands() const OVERRIDE + { + static ChatCommand groupCommandTable[] = + { + { "leader", RBAC_PERM_COMMAND_GROUP_LEADER, false, &HandleGroupLeaderCommand, "", NULL }, + { "disband", RBAC_PERM_COMMAND_GROUP_DISBAND, false, &HandleGroupDisbandCommand, "", NULL }, + { "remove", RBAC_PERM_COMMAND_GROUP_REMOVE, false, &HandleGroupRemoveCommand, "", NULL }, + { "join", RBAC_PERM_COMMAND_GROUP_JOIN, false, &HandleGroupJoinCommand, "", NULL }, + { "list", RBAC_PERM_COMMAND_GROUP_LIST, false, &HandleGroupListCommand, "", NULL }, + { "summon", RBAC_PERM_COMMAND_GROUP_SUMMON, false, &HandleGroupSummonCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } + }; + + static ChatCommand commandTable[] = + { + { "group", RBAC_PERM_COMMAND_GROUP, false, NULL, "", groupCommandTable }, + { NULL, 0, false, NULL, "", NULL } + }; + return commandTable; + } + + // Summon group of player + static bool HandleGroupSummonCommand(ChatHandler* handler, char const* args) + { + Player* target; + if (!handler->extractPlayerTarget((char*)args, &target)) + return false; + + // check online security + if (handler->HasLowerSecurity(target, 0)) + return false; + + Group* group = target->GetGroup(); + + std::string nameLink = handler->GetNameLink(target); + + if (!group) + { + handler->PSendSysMessage(LANG_NOT_IN_GROUP, nameLink.c_str()); + handler->SetSentErrorMessage(true); + return false; + } + + Player* gmPlayer = handler->GetSession()->GetPlayer(); + Group* gmGroup = gmPlayer->GetGroup(); + Map* gmMap = gmPlayer->GetMap(); + bool toInstance = gmMap->Instanceable(); + + // we are in instance, and can summon only player in our group with us as lead + if (toInstance && ( + !gmGroup || group->GetLeaderGUID() != gmPlayer->GetGUID() || + gmGroup->GetLeaderGUID() != gmPlayer->GetGUID())) + // the last check is a bit excessive, but let it be, just in case + { + handler->SendSysMessage(LANG_CANNOT_SUMMON_TO_INST); + handler->SetSentErrorMessage(true); + return false; + } + + for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next()) + { + Player* player = itr->GetSource(); + + if (!player || player == gmPlayer || !player->GetSession()) + continue; + + // check online security + if (handler->HasLowerSecurity(player, 0)) + return false; + + std::string plNameLink = handler->GetNameLink(player); + + if (player->IsBeingTeleported()) + { + handler->PSendSysMessage(LANG_IS_TELEPORTED, plNameLink.c_str()); + handler->SetSentErrorMessage(true); + return false; + } + + if (toInstance) + { + Map* playerMap = player->GetMap(); + + if (playerMap->Instanceable() && playerMap->GetInstanceId() != gmMap->GetInstanceId()) + { + // cannot summon from instance to instance + handler->PSendSysMessage(LANG_CANNOT_SUMMON_TO_INST, plNameLink.c_str()); + handler->SetSentErrorMessage(true); + return false; + } + } + + handler->PSendSysMessage(LANG_SUMMONING, plNameLink.c_str(), ""); + if (handler->needReportToTarget(player)) + ChatHandler(player->GetSession()).PSendSysMessage(LANG_SUMMONED_BY, handler->GetNameLink().c_str()); + + // stop flight if need + if (player->IsInFlight()) + { + player->GetMotionMaster()->MovementExpired(); + player->CleanupAfterTaxiFlight(); + } + // save only in non-flight case + else + player->SaveRecallPosition(); + + // before GM + float x, y, z; + gmPlayer->GetClosePoint(x, y, z, player->GetObjectSize()); + player->TeleportTo(gmPlayer->GetMapId(), x, y, z, player->GetOrientation()); + } + + return true; + } + + static bool HandleGroupLeaderCommand(ChatHandler* handler, char const* args) + { + Player* player = NULL; + Group* group = NULL; + uint64 guid = 0; + char* nameStr = strtok((char*)args, " "); + + if (!handler->GetPlayerGroupAndGUIDByName(nameStr, player, group, guid)) + return false; + + if (!group) + { + handler->PSendSysMessage(LANG_GROUP_NOT_IN_GROUP, player->GetName().c_str()); + handler->SetSentErrorMessage(true); + return false; + } + + if (group->GetLeaderGUID() != guid) + { + group->ChangeLeader(guid); + group->SendUpdate(); + } + + return true; + } + + static bool HandleGroupDisbandCommand(ChatHandler* handler, char const* args) + { + Player* player = NULL; + Group* group = NULL; + uint64 guid = 0; + char* nameStr = strtok((char*)args, " "); + + if (!handler->GetPlayerGroupAndGUIDByName(nameStr, player, group, guid)) + return false; + + if (!group) + { + handler->PSendSysMessage(LANG_GROUP_NOT_IN_GROUP, player->GetName().c_str()); + handler->SetSentErrorMessage(true); + return false; + } + + group->Disband(); + return true; + } + + static bool HandleGroupRemoveCommand(ChatHandler* handler, char const* args) + { + Player* player = NULL; + Group* group = NULL; + uint64 guid = 0; + char* nameStr = strtok((char*)args, " "); + + if (!handler->GetPlayerGroupAndGUIDByName(nameStr, player, group, guid)) + return false; + + if (!group) + { + handler->PSendSysMessage(LANG_GROUP_NOT_IN_GROUP, player->GetName().c_str()); + handler->SetSentErrorMessage(true); + return false; + } + + group->RemoveMember(guid); + return true; + } + + static bool HandleGroupJoinCommand(ChatHandler* handler, char const* args) + { + if (!*args) + return false; + + Player* playerSource = NULL; + Player* playerTarget = NULL; + Group* groupSource = NULL; + Group* groupTarget = NULL; + uint64 guidSource = 0; + uint64 guidTarget = 0; + char* nameplgrStr = strtok((char*)args, " "); + char* nameplStr = strtok(NULL, " "); + + if (!handler->GetPlayerGroupAndGUIDByName(nameplgrStr, playerSource, groupSource, guidSource, true)) + return false; + + if (!groupSource) + { + handler->PSendSysMessage(LANG_GROUP_NOT_IN_GROUP, playerSource->GetName().c_str()); + handler->SetSentErrorMessage(true); + return false; + } + + if (!handler->GetPlayerGroupAndGUIDByName(nameplStr, playerTarget, groupTarget, guidTarget, true)) + return false; + + if (groupTarget || playerTarget->GetGroup() == groupSource) + { + handler->PSendSysMessage(LANG_GROUP_ALREADY_IN_GROUP, playerTarget->GetName().c_str()); + handler->SetSentErrorMessage(true); + return false; + } + + if (!groupSource->IsFull()) + { + handler->PSendSysMessage(LANG_GROUP_FULL); + handler->SetSentErrorMessage(true); + return false; + } + + groupSource->AddMember(playerTarget); + groupSource->BroadcastGroupUpdate(); + handler->PSendSysMessage(LANG_GROUP_PLAYER_JOINED, playerTarget->GetName().c_str(), playerSource->GetName().c_str()); + return true; + } + + static bool HandleGroupListCommand(ChatHandler* handler, char const* args) + { + Player* playerTarget; + uint64 guidTarget; + std::string nameTarget; + + uint32 parseGUID = MAKE_NEW_GUID(atol((char*)args), 0, HIGHGUID_PLAYER); + + if (sObjectMgr->GetPlayerNameByGUID(parseGUID, nameTarget)) + { + playerTarget = sObjectMgr->GetPlayerByLowGUID(parseGUID); + guidTarget = parseGUID; + } + else if (!handler->extractPlayerTarget((char*)args, &playerTarget, &guidTarget, &nameTarget)) + return false; + + Group* groupTarget = NULL; + if (playerTarget) + groupTarget = playerTarget->GetGroup(); + + if (!groupTarget) + { + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GROUP_MEMBER); + stmt->setUInt32(0, guidTarget); + PreparedQueryResult resultGroup = CharacterDatabase.Query(stmt); + if (resultGroup) + groupTarget = sGroupMgr->GetGroupByDbStoreId((*resultGroup)[0].GetUInt32()); + } + + if (!groupTarget) + { + handler->PSendSysMessage(LANG_GROUP_NOT_IN_GROUP, nameTarget.c_str()); + handler->SetSentErrorMessage(true); + return false; + } + + handler->PSendSysMessage(LANG_GROUP_TYPE, (groupTarget->isRaidGroup() ? "raid" : "party")); + Group::MemberSlotList const& members = groupTarget->GetMemberSlots(); + for (Group::MemberSlotList::const_iterator itr = members.begin(); itr != members.end(); ++itr) + { + Group::MemberSlot const& slot = *itr; + + std::string flags; + if (slot.flags & MEMBER_FLAG_ASSISTANT) + flags = "Assistant"; + + if (slot.flags & MEMBER_FLAG_MAINTANK) + { + if (!flags.empty()) + flags.append(", "); + flags.append("MainTank"); + } + + if (slot.flags & MEMBER_FLAG_MAINASSIST) + { + if (!flags.empty()) + flags.append(", "); + flags.append("MainAssist"); + } + + if (flags.empty()) + flags = "None"; + + Player* p = ObjectAccessor::FindPlayer((*itr).guid); + const char* onlineState = (p && p->IsInWorld()) ? "online" : "offline"; + + handler->PSendSysMessage(LANG_GROUP_PLAYER_NAME_GUID, slot.name.c_str(), onlineState, + GUID_LOPART(slot.guid), flags.c_str(), lfg::GetRolesString(slot.roles).c_str()); + } + + return true; + } +}; + +void AddSC_group_commandscript() +{ + new group_commandscript(); +} diff --git a/src/server/scripts/Commands/cs_guild.cpp b/src/server/scripts/Commands/cs_guild.cpp index ffaf1360ad5..04276016fff 100644 --- a/src/server/scripts/Commands/cs_guild.cpp +++ b/src/server/scripts/Commands/cs_guild.cpp @@ -39,18 +39,18 @@ public: { static ChatCommand guildCommandTable[] = { - { "create", SEC_GAMEMASTER, true, &HandleGuildCreateCommand, "", NULL }, - { "delete", SEC_GAMEMASTER, true, &HandleGuildDeleteCommand, "", NULL }, - { "invite", SEC_GAMEMASTER, true, &HandleGuildInviteCommand, "", NULL }, - { "uninvite", SEC_GAMEMASTER, true, &HandleGuildUninviteCommand, "", NULL }, - { "rank", SEC_GAMEMASTER, true, &HandleGuildRankCommand, "", NULL }, - { "rename", SEC_GAMEMASTER, true, &HandleGuildRenameCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "create", RBAC_PERM_COMMAND_GUILD_CREATE, true, &HandleGuildCreateCommand, "", NULL }, + { "delete", RBAC_PERM_COMMAND_GUILD_DELETE, true, &HandleGuildDeleteCommand, "", NULL }, + { "invite", RBAC_PERM_COMMAND_GUILD_INVITE, true, &HandleGuildInviteCommand, "", NULL }, + { "uninvite", RBAC_PERM_COMMAND_GUILD_UNINVITE, true, &HandleGuildUninviteCommand, "", NULL }, + { "rank", RBAC_PERM_COMMAND_GUILD_RANK, true, &HandleGuildRankCommand, "", NULL }, + { "rename", RBAC_PERM_COMMAND_GUILD_RENAME, true, &HandleGuildRenameCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand commandTable[] = { - { "guild", SEC_ADMINISTRATOR, true, NULL, "", guildCommandTable }, - { NULL, 0, false, NULL, "", NULL } + { "guild", RBAC_PERM_COMMAND_GUILD, true, NULL, "", guildCommandTable }, + { NULL, 0, false, NULL, "", NULL } }; return commandTable; } @@ -119,6 +119,7 @@ public: return false; targetGuild->Disband(); + delete targetGuild; return true; } @@ -165,7 +166,7 @@ public: if (!targetGuild) return false; - targetGuild->DeleteMember(targetGuid, false, true); + targetGuild->DeleteMember(targetGuid, false, true, true); return true; } diff --git a/src/server/scripts/Commands/cs_honor.cpp b/src/server/scripts/Commands/cs_honor.cpp index 75c7fcf71e2..cd8e2630a67 100644 --- a/src/server/scripts/Commands/cs_honor.cpp +++ b/src/server/scripts/Commands/cs_honor.cpp @@ -37,22 +37,22 @@ public: { static ChatCommand honorAddCommandTable[] = { - { "kill", SEC_GAMEMASTER, false, &HandleHonorAddKillCommand, "", NULL }, - { "", SEC_GAMEMASTER, false, &HandleHonorAddCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "kill", RBAC_PERM_COMMAND_HONOR_ADD_KILL, false, &HandleHonorAddKillCommand, "", NULL }, + { "", RBAC_PERM_COMMAND_HONOR_ADD, false, &HandleHonorAddCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand honorCommandTable[] = { - { "add", SEC_GAMEMASTER, false, NULL, "", honorAddCommandTable }, - { "update", SEC_GAMEMASTER, false, &HandleHonorUpdateCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "add", RBAC_PERM_COMMAND_HONOR_ADD, false, NULL, "", honorAddCommandTable }, + { "update", RBAC_PERM_COMMAND_HONOR_UPDATE, false, &HandleHonorUpdateCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand commandTable[] = { - { "honor", SEC_GAMEMASTER, false, NULL, "", honorCommandTable }, - { NULL, 0, false, NULL, "", NULL } + { "honor", RBAC_PERM_COMMAND_HONOR, false, NULL, "", honorCommandTable }, + { NULL, 0, false, NULL, "", NULL } }; return commandTable; } diff --git a/src/server/scripts/Commands/cs_instance.cpp b/src/server/scripts/Commands/cs_instance.cpp index a0cd306c631..b597caf0ae0 100644 --- a/src/server/scripts/Commands/cs_instance.cpp +++ b/src/server/scripts/Commands/cs_instance.cpp @@ -39,17 +39,17 @@ public: { static ChatCommand instanceCommandTable[] = { - { "listbinds", SEC_ADMINISTRATOR, false, &HandleInstanceListBindsCommand, "", NULL }, - { "unbind", SEC_ADMINISTRATOR, false, &HandleInstanceUnbindCommand, "", NULL }, - { "stats", SEC_ADMINISTRATOR, true, &HandleInstanceStatsCommand, "", NULL }, - { "savedata", SEC_ADMINISTRATOR, false, &HandleInstanceSaveDataCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "listbinds", RBAC_PERM_COMMAND_INSTANCE_LISTBINDS, false, &HandleInstanceListBindsCommand, "", NULL }, + { "unbind", RBAC_PERM_COMMAND_INSTANCE_UNBIND, false, &HandleInstanceUnbindCommand, "", NULL }, + { "stats", RBAC_PERM_COMMAND_INSTANCE_STATS, true, &HandleInstanceStatsCommand, "", NULL }, + { "savedata", RBAC_PERM_COMMAND_INSTANCE_SAVEDATA, false, &HandleInstanceSaveDataCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand commandTable[] = { - { "instance", SEC_ADMINISTRATOR, true, NULL, "", instanceCommandTable }, - { NULL, 0, false, NULL, "", NULL } + { "instance", RBAC_PERM_COMMAND_INSTANCE, true, NULL, "", instanceCommandTable }, + { NULL, 0, false, NULL, "", NULL } }; return commandTable; diff --git a/src/server/scripts/Commands/cs_learn.cpp b/src/server/scripts/Commands/cs_learn.cpp index 89ea572d74b..90ab4eff86a 100644 --- a/src/server/scripts/Commands/cs_learn.cpp +++ b/src/server/scripts/Commands/cs_learn.cpp @@ -40,36 +40,36 @@ public: { static ChatCommand learnAllMyCommandTable[] = { - { "class", SEC_ADMINISTRATOR, false, &HandleLearnAllMyClassCommand, "", NULL }, - { "pettalents", SEC_ADMINISTRATOR, false, &HandleLearnAllMyPetTalentsCommand, "", NULL }, - { "spells", SEC_ADMINISTRATOR, false, &HandleLearnAllMySpellsCommand, "", NULL }, - { "talents", SEC_ADMINISTRATOR, false, &HandleLearnAllMyTalentsCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "class", RBAC_PERM_COMMAND_LEARN_ALL_MY_CLASS, false, &HandleLearnAllMyClassCommand, "", NULL }, + { "pettalents", RBAC_PERM_COMMAND_LEARN_ALL_MY_PETTALENTS, false, &HandleLearnAllMyPetTalentsCommand, "", NULL }, + { "spells", RBAC_PERM_COMMAND_LEARN_ALL_MY_SPELLS, false, &HandleLearnAllMySpellsCommand, "", NULL }, + { "talents", RBAC_PERM_COMMAND_LEARN_ALL_MY_TALENTS, false, &HandleLearnAllMyTalentsCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand learnAllCommandTable[] = { - { "my", SEC_ADMINISTRATOR, false, NULL, "", learnAllMyCommandTable }, - { "gm", SEC_GAMEMASTER, false, &HandleLearnAllGMCommand, "", NULL }, - { "crafts", SEC_GAMEMASTER, false, &HandleLearnAllCraftsCommand, "", NULL }, - { "default", SEC_MODERATOR, false, &HandleLearnAllDefaultCommand, "", NULL }, - { "lang", SEC_MODERATOR, false, &HandleLearnAllLangCommand, "", NULL }, - { "recipes", SEC_GAMEMASTER, false, &HandleLearnAllRecipesCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "my", RBAC_PERM_COMMAND_LEARN_ALL_MY, false, NULL, "", learnAllMyCommandTable }, + { "gm", RBAC_PERM_COMMAND_LEARN_ALL_GM, false, &HandleLearnAllGMCommand, "", NULL }, + { "crafts", RBAC_PERM_COMMAND_LEARN_ALL_CRAFTS, false, &HandleLearnAllCraftsCommand, "", NULL }, + { "default", RBAC_PERM_COMMAND_LEARN_ALL_DEFAULT, false, &HandleLearnAllDefaultCommand, "", NULL }, + { "lang", RBAC_PERM_COMMAND_LEARN_ALL_LANG, false, &HandleLearnAllLangCommand, "", NULL }, + { "recipes", RBAC_PERM_COMMAND_LEARN_ALL_RECIPES, false, &HandleLearnAllRecipesCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand learnCommandTable[] = { - { "all", SEC_ADMINISTRATOR, false, NULL, "", learnAllCommandTable }, - { "", SEC_ADMINISTRATOR, false, &HandleLearnCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "all", RBAC_PERM_COMMAND_LEARN_ALL, false, NULL, "", learnAllCommandTable }, + { "", RBAC_PERM_COMMAND_LEARN, false, &HandleLearnCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand commandTable[] = { - { "learn", SEC_MODERATOR, false, NULL, "", learnCommandTable }, - { "unlearn", SEC_ADMINISTRATOR, false, &HandleUnLearnCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "learn", RBAC_PERM_COMMAND_LEARN, false, NULL, "", learnCommandTable }, + { "unlearn", RBAC_PERM_COMMAND_UNLEARN, false, &HandleUnLearnCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } }; return commandTable; } @@ -339,8 +339,12 @@ public: return true; } - static bool HandleLearnAllCraftsCommand(ChatHandler* handler, char const* /*args*/) + static bool HandleLearnAllCraftsCommand(ChatHandler* handler, char const* args) { + Player* target; + if (!handler->extractPlayerTarget((char*)args, &target)) + return false; + for (uint32 i = 0; i < sSkillLineStore.GetNumRows(); ++i) { SkillLineEntry const* skillInfo = sSkillLineStore.LookupEntry(i); @@ -350,7 +354,7 @@ public: if ((skillInfo->categoryId == SKILL_CATEGORY_PROFESSION || skillInfo->categoryId == SKILL_CATEGORY_SECONDARY) && skillInfo->canLink) // only prof. with recipes have { - HandleLearnSkillRecipesHelper(handler->GetSession()->GetPlayer(), skillInfo->id); + HandleLearnSkillRecipesHelper(target, skillInfo->id); } } diff --git a/src/server/scripts/Commands/cs_lfg.cpp b/src/server/scripts/Commands/cs_lfg.cpp index 3a9e7a67214..76d9fe50de1 100644 --- a/src/server/scripts/Commands/cs_lfg.cpp +++ b/src/server/scripts/Commands/cs_lfg.cpp @@ -45,18 +45,18 @@ public: { static ChatCommand lfgCommandTable[] = { - { "player", SEC_GAMEMASTER, false, &HandleLfgPlayerInfoCommand, "", NULL }, - { "group", SEC_GAMEMASTER, false, &HandleLfgGroupInfoCommand, "", NULL }, - { "queue", SEC_GAMEMASTER, false, &HandleLfgQueueInfoCommand, "", NULL }, - { "clean", SEC_ADMINISTRATOR, false, &HandleLfgCleanCommand, "", NULL }, - { "options", SEC_ADMINISTRATOR, false, &HandleLfgOptionsCommand, "", NULL }, - { NULL, SEC_PLAYER, false, NULL, "", NULL } + { "player", RBAC_PERM_COMMAND_LFG_PLAYER, false, &HandleLfgPlayerInfoCommand, "", NULL }, + { "group", RBAC_PERM_COMMAND_LFG_GROUP, false, &HandleLfgGroupInfoCommand, "", NULL }, + { "queue", RBAC_PERM_COMMAND_LFG_QUEUE, false, &HandleLfgQueueInfoCommand, "", NULL }, + { "clean", RBAC_PERM_COMMAND_LFG_CLEAN, false, &HandleLfgCleanCommand, "", NULL }, + { "options", RBAC_PERM_COMMAND_LFG_OPTIONS, false, &HandleLfgOptionsCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand commandTable[] = { - { "lfg", SEC_GAMEMASTER, false, NULL, "", lfgCommandTable }, - { NULL, SEC_PLAYER, false, NULL, "", NULL } + { "lfg", RBAC_PERM_COMMAND_LFG, false, NULL, "", lfgCommandTable }, + { NULL, 0, false, NULL, "", NULL } }; return commandTable; } diff --git a/src/server/scripts/Commands/cs_list.cpp b/src/server/scripts/Commands/cs_list.cpp index 279e7765863..4921b82b47e 100644 --- a/src/server/scripts/Commands/cs_list.cpp +++ b/src/server/scripts/Commands/cs_list.cpp @@ -40,17 +40,17 @@ public: { static ChatCommand listCommandTable[] = { - { "creature", SEC_ADMINISTRATOR, true, &HandleListCreatureCommand, "", NULL }, - { "item", SEC_ADMINISTRATOR, true, &HandleListItemCommand, "", NULL }, - { "object", SEC_ADMINISTRATOR, true, &HandleListObjectCommand, "", NULL }, - { "auras", SEC_ADMINISTRATOR, false, &HandleListAurasCommand, "", NULL }, - { "mail", SEC_ADMINISTRATOR, true, &HandleListMailCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "creature", RBAC_PERM_COMMAND_LIST_CREATURE, true, &HandleListCreatureCommand, "", NULL }, + { "item", RBAC_PERM_COMMAND_LIST_ITEM, true, &HandleListItemCommand, "", NULL }, + { "object", RBAC_PERM_COMMAND_LIST_OBJECT, true, &HandleListObjectCommand, "", NULL }, + { "auras", RBAC_PERM_COMMAND_LIST_AURAS, false, &HandleListAurasCommand, "", NULL }, + { "mail", RBAC_PERM_COMMAND_LIST_MAIL, true, &HandleListMailCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand commandTable[] = { - { "list", SEC_ADMINISTRATOR, true, NULL, "", listCommandTable }, - { NULL, 0, false, NULL, "", NULL } + { "list", RBAC_PERM_COMMAND_LIST,true, NULL, "", listCommandTable }, + { NULL, 0, false, NULL, "", NULL } }; return commandTable; } diff --git a/src/server/scripts/Commands/cs_lookup.cpp b/src/server/scripts/Commands/cs_lookup.cpp index 913b37f1200..736b8085eeb 100644 --- a/src/server/scripts/Commands/cs_lookup.cpp +++ b/src/server/scripts/Commands/cs_lookup.cpp @@ -41,43 +41,43 @@ public: { static ChatCommand lookupPlayerCommandTable[] = { - { "ip", SEC_GAMEMASTER, true, &HandleLookupPlayerIpCommand, "", NULL }, - { "account", SEC_GAMEMASTER, true, &HandleLookupPlayerAccountCommand, "", NULL }, - { "email", SEC_GAMEMASTER, true, &HandleLookupPlayerEmailCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "ip", RBAC_PERM_COMMAND_LOOKUP_PLAYER_IP, true, &HandleLookupPlayerIpCommand, "", NULL }, + { "account", RBAC_PERM_COMMAND_LOOKUP_PLAYER_ACCOUNT, true, &HandleLookupPlayerAccountCommand, "", NULL }, + { "email", RBAC_PERM_COMMAND_LOOKUP_PLAYER_EMAIL, true, &HandleLookupPlayerEmailCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand lookupSpellCommandTable[] = { - { "id", SEC_ADMINISTRATOR, true, &HandleLookupSpellIdCommand, "", NULL }, - { "", SEC_ADMINISTRATOR, true, &HandleLookupSpellCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "id", RBAC_PERM_COMMAND_LOOKUP_SPELL_ID, true, &HandleLookupSpellIdCommand, "", NULL }, + { "", RBAC_PERM_COMMAND_LOOKUP_SPELL, true, &HandleLookupSpellCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand lookupCommandTable[] = { - { "area", SEC_MODERATOR, true, &HandleLookupAreaCommand, "", NULL }, - { "creature", SEC_ADMINISTRATOR, true, &HandleLookupCreatureCommand, "", NULL }, - { "event", SEC_GAMEMASTER, true, &HandleLookupEventCommand, "", NULL }, - { "faction", SEC_ADMINISTRATOR, true, &HandleLookupFactionCommand, "", NULL }, - { "item", SEC_ADMINISTRATOR, true, &HandleLookupItemCommand, "", NULL }, - { "itemset", SEC_ADMINISTRATOR, true, &HandleLookupItemSetCommand, "", NULL }, - { "object", SEC_ADMINISTRATOR, true, &HandleLookupObjectCommand, "", NULL }, - { "quest", SEC_ADMINISTRATOR, true, &HandleLookupQuestCommand, "", NULL }, - { "player", SEC_GAMEMASTER, true, NULL, "", lookupPlayerCommandTable }, - { "skill", SEC_ADMINISTRATOR, true, &HandleLookupSkillCommand, "", NULL }, - { "spell", SEC_ADMINISTRATOR, true, NULL, "", lookupSpellCommandTable }, - { "taxinode", SEC_ADMINISTRATOR, true, &HandleLookupTaxiNodeCommand, "", NULL }, - { "tele", SEC_MODERATOR, true, &HandleLookupTeleCommand, "", NULL }, - { "title", SEC_GAMEMASTER, true, &HandleLookupTitleCommand, "", NULL }, - { "map", SEC_ADMINISTRATOR, true, &HandleLookupMapCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "area", RBAC_PERM_COMMAND_LOOKUP_AREA, true, &HandleLookupAreaCommand, "", NULL }, + { "creature", RBAC_PERM_COMMAND_LOOKUP_CREATURE, true, &HandleLookupCreatureCommand, "", NULL }, + { "event", RBAC_PERM_COMMAND_LOOKUP_EVENT, true, &HandleLookupEventCommand, "", NULL }, + { "faction", RBAC_PERM_COMMAND_LOOKUP_FACTION, true, &HandleLookupFactionCommand, "", NULL }, + { "item", RBAC_PERM_COMMAND_LOOKUP_ITEM, true, &HandleLookupItemCommand, "", NULL }, + { "itemset", RBAC_PERM_COMMAND_LOOKUP_ITEMSET, true, &HandleLookupItemSetCommand, "", NULL }, + { "object", RBAC_PERM_COMMAND_LOOKUP_OBJECT, true, &HandleLookupObjectCommand, "", NULL }, + { "quest", RBAC_PERM_COMMAND_LOOKUP_QUEST, true, &HandleLookupQuestCommand, "", NULL }, + { "player", RBAC_PERM_COMMAND_LOOKUP_PLAYER, true, NULL, "", lookupPlayerCommandTable }, + { "skill", RBAC_PERM_COMMAND_LOOKUP_SKILL, true, &HandleLookupSkillCommand, "", NULL }, + { "spell", RBAC_PERM_COMMAND_LOOKUP_SPELL, true, NULL, "", lookupSpellCommandTable }, + { "taxinode", RBAC_PERM_COMMAND_LOOKUP_TAXINODE, true, &HandleLookupTaxiNodeCommand, "", NULL }, + { "tele", RBAC_PERM_COMMAND_LOOKUP_TELE, true, &HandleLookupTeleCommand, "", NULL }, + { "title", RBAC_PERM_COMMAND_LOOKUP_TITLE, true, &HandleLookupTitleCommand, "", NULL }, + { "map", RBAC_PERM_COMMAND_LOOKUP_MAP, true, &HandleLookupMapCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand commandTable[] = { - { "lookup", SEC_ADMINISTRATOR, true, NULL, "", lookupCommandTable }, - { NULL, 0, false, NULL, "", NULL } + { "lookup", RBAC_PERM_COMMAND_LOOKUP, true, NULL, "", lookupCommandTable }, + { NULL, 0, false, NULL, "", NULL } }; return commandTable; } diff --git a/src/server/scripts/Commands/cs_message.cpp b/src/server/scripts/Commands/cs_message.cpp index cc50490e831..8c06d87bd7c 100644 --- a/src/server/scripts/Commands/cs_message.cpp +++ b/src/server/scripts/Commands/cs_message.cpp @@ -38,25 +38,25 @@ public: { static ChatCommand channelSetCommandTable[] = { - { "ownership", SEC_ADMINISTRATOR, false, &HandleChannelSetOwnership, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "ownership", RBAC_PERM_COMMAND_CHANNEL_SET_OWNERSHIP, false, &HandleChannelSetOwnership, "", NULL }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand channelCommandTable[] = { - { "set", SEC_ADMINISTRATOR, true, NULL, "", channelSetCommandTable }, - { NULL, 0, false, NULL, "", NULL } + { "set", RBAC_PERM_COMMAND_CHANNEL_SET, true, NULL, "", channelSetCommandTable }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand commandTable[] = { - { "channel", SEC_ADMINISTRATOR, true, NULL, "", channelCommandTable }, - { "nameannounce", SEC_MODERATOR, true, &HandleNameAnnounceCommand, "", NULL }, - { "gmnameannounce", SEC_MODERATOR, true, &HandleGMNameAnnounceCommand, "", NULL }, - { "announce", SEC_MODERATOR, true, &HandleAnnounceCommand, "", NULL }, - { "gmannounce", SEC_MODERATOR, true, &HandleGMAnnounceCommand, "", NULL }, - { "notify", SEC_MODERATOR, true, &HandleNotifyCommand, "", NULL }, - { "gmnotify", SEC_MODERATOR, true, &HandleGMNotifyCommand, "", NULL }, - { "whispers", SEC_MODERATOR, false, &HandleWhispersCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "channel", RBAC_PERM_COMMAND_CHANNEL, true, NULL, "", channelCommandTable }, + { "nameannounce", RBAC_PERM_COMMAND_NAMEANNOUNCE, true, &HandleNameAnnounceCommand, "", NULL }, + { "gmnameannounce", RBAC_PERM_COMMAND_GMNAMEANNOUNCE, true, &HandleGMNameAnnounceCommand, "", NULL }, + { "announce", RBAC_PERM_COMMAND_ANNOUNCE, true, &HandleAnnounceCommand, "", NULL }, + { "gmannounce", RBAC_PERM_COMMAND_GMANNOUNCE, true, &HandleGMAnnounceCommand, "", NULL }, + { "notify", RBAC_PERM_COMMAND_NOTIFY, true, &HandleNotifyCommand, "", NULL }, + { "gmnotify", RBAC_PERM_COMMAND_GMNOTIFY, true, &HandleGMNotifyCommand, "", NULL }, + { "whispers", RBAC_PERM_COMMAND_WHISPERS, false, &HandleWhispersCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } }; return commandTable; } diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp index 3c18d04c9bf..f05bb58b5b0 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -44,84 +44,56 @@ public: ChatCommand* GetCommands() const OVERRIDE { - static ChatCommand groupCommandTable[] = - { - { "leader", SEC_ADMINISTRATOR, false, &HandleGroupLeaderCommand, "", NULL }, - { "disband", SEC_ADMINISTRATOR, false, &HandleGroupDisbandCommand, "", NULL }, - { "remove", SEC_ADMINISTRATOR, false, &HandleGroupRemoveCommand, "", NULL }, - { "join", SEC_ADMINISTRATOR, false, &HandleGroupJoinCommand, "", NULL }, - { "list", SEC_ADMINISTRATOR, false, &HandleGroupListCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } - }; - static ChatCommand petCommandTable[] = - { - { "create", SEC_GAMEMASTER, false, &HandleCreatePetCommand, "", NULL }, - { "learn", SEC_GAMEMASTER, false, &HandlePetLearnCommand, "", NULL }, - { "unlearn", SEC_GAMEMASTER, false, &HandlePetUnlearnCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } - }; - static ChatCommand sendCommandTable[] = - { - { "items", SEC_ADMINISTRATOR, true, &HandleSendItemsCommand, "", NULL }, - { "mail", SEC_MODERATOR, true, &HandleSendMailCommand, "", NULL }, - { "message", SEC_ADMINISTRATOR, true, &HandleSendMessageCommand, "", NULL }, - { "money", SEC_ADMINISTRATOR, true, &HandleSendMoneyCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } - }; static ChatCommand commandTable[] = { - { "dev", SEC_ADMINISTRATOR, false, &HandleDevCommand, "", NULL }, - { "gps", SEC_ADMINISTRATOR, false, &HandleGPSCommand, "", NULL }, - { "aura", SEC_ADMINISTRATOR, false, &HandleAuraCommand, "", NULL }, - { "unaura", SEC_ADMINISTRATOR, false, &HandleUnAuraCommand, "", NULL }, - { "appear", SEC_MODERATOR, false, &HandleAppearCommand, "", NULL }, - { "summon", SEC_MODERATOR, false, &HandleSummonCommand, "", NULL }, - { "groupsummon", SEC_MODERATOR, false, &HandleGroupSummonCommand, "", NULL }, - { "commands", SEC_PLAYER, true, &HandleCommandsCommand, "", NULL }, - { "die", SEC_ADMINISTRATOR, false, &HandleDieCommand, "", NULL }, - { "revive", SEC_ADMINISTRATOR, true, &HandleReviveCommand, "", NULL }, - { "dismount", SEC_PLAYER, false, &HandleDismountCommand, "", NULL }, - { "guid", SEC_GAMEMASTER, false, &HandleGUIDCommand, "", NULL }, - { "help", SEC_PLAYER, true, &HandleHelpCommand, "", NULL }, - { "itemmove", SEC_GAMEMASTER, false, &HandleItemMoveCommand, "", NULL }, - { "cooldown", SEC_ADMINISTRATOR, false, &HandleCooldownCommand, "", NULL }, - { "distance", SEC_ADMINISTRATOR, false, &HandleGetDistanceCommand, "", NULL }, - { "recall", SEC_MODERATOR, false, &HandleRecallCommand, "", NULL }, - { "save", SEC_PLAYER, false, &HandleSaveCommand, "", NULL }, - { "saveall", SEC_MODERATOR, true, &HandleSaveAllCommand, "", NULL }, - { "kick", SEC_GAMEMASTER, true, &HandleKickPlayerCommand, "", NULL }, - { "unstuck", SEC_PLAYER, true, &HandleUnstuckCommand, "", NULL }, - { "linkgrave", SEC_ADMINISTRATOR, false, &HandleLinkGraveCommand, "", NULL }, - { "neargrave", SEC_ADMINISTRATOR, false, &HandleNearGraveCommand, "", NULL }, - { "showarea", SEC_ADMINISTRATOR, false, &HandleShowAreaCommand, "", NULL }, - { "hidearea", SEC_ADMINISTRATOR, false, &HandleHideAreaCommand, "", NULL }, - { "additem", SEC_ADMINISTRATOR, false, &HandleAddItemCommand, "", NULL }, - { "additemset", SEC_ADMINISTRATOR, false, &HandleAddItemSetCommand, "", NULL }, - { "bank", SEC_ADMINISTRATOR, false, &HandleBankCommand, "", NULL }, - { "wchange", SEC_ADMINISTRATOR, false, &HandleChangeWeather, "", NULL }, - { "maxskill", SEC_ADMINISTRATOR, false, &HandleMaxSkillCommand, "", NULL }, - { "setskill", SEC_ADMINISTRATOR, false, &HandleSetSkillCommand, "", NULL }, - { "pinfo", SEC_GAMEMASTER, true, &HandlePInfoCommand, "", NULL }, - { "respawn", SEC_ADMINISTRATOR, false, &HandleRespawnCommand, "", NULL }, - { "send", SEC_MODERATOR, true, NULL, "", sendCommandTable }, - { "pet", SEC_GAMEMASTER, false, NULL, "", petCommandTable }, - { "mute", SEC_MODERATOR, true, &HandleMuteCommand, "", NULL }, - { "unmute", SEC_MODERATOR, true, &HandleUnmuteCommand, "", NULL }, - { "movegens", SEC_ADMINISTRATOR, false, &HandleMovegensCommand, "", NULL }, - { "cometome", SEC_ADMINISTRATOR, false, &HandleComeToMeCommand, "", NULL }, - { "damage", SEC_ADMINISTRATOR, false, &HandleDamageCommand, "", NULL }, - { "combatstop", SEC_GAMEMASTER, true, &HandleCombatStopCommand, "", NULL }, - { "repairitems", SEC_GAMEMASTER, true, &HandleRepairitemsCommand, "", NULL }, - { "freeze", SEC_MODERATOR, false, &HandleFreezeCommand, "", NULL }, - { "unfreeze", SEC_MODERATOR, false, &HandleUnFreezeCommand, "", NULL }, - { "listfreeze", SEC_MODERATOR, false, &HandleListFreezeCommand, "", NULL }, - { "group", SEC_ADMINISTRATOR, false, NULL, "", groupCommandTable }, - { "possess", SEC_ADMINISTRATOR, false, HandlePossessCommand, "", NULL }, - { "unpossess", SEC_ADMINISTRATOR, false, HandleUnPossessCommand, "", NULL }, - { "bindsight", SEC_ADMINISTRATOR, false, HandleBindSightCommand, "", NULL }, - { "unbindsight", SEC_ADMINISTRATOR, false, HandleUnbindSightCommand, "", NULL }, - { "playall", SEC_GAMEMASTER, false, HandlePlayAllCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "additem", RBAC_PERM_COMMAND_ADDITEM, false, &HandleAddItemCommand, "", NULL }, + { "additemset", RBAC_PERM_COMMAND_ADDITEMSET, false, &HandleAddItemSetCommand, "", NULL }, + { "appear", RBAC_PERM_COMMAND_APPEAR, false, &HandleAppearCommand, "", NULL }, + { "aura", RBAC_PERM_COMMAND_AURA, false, &HandleAuraCommand, "", NULL }, + { "bank", RBAC_PERM_COMMAND_BANK, false, &HandleBankCommand, "", NULL }, + { "bindsight", RBAC_PERM_COMMAND_BINDSIGHT, false, &HandleBindSightCommand, "", NULL }, + { "combatstop", RBAC_PERM_COMMAND_COMBATSTOP, true, &HandleCombatStopCommand, "", NULL }, + { "cometome", RBAC_PERM_COMMAND_COMETOME, false, &HandleComeToMeCommand, "", NULL }, + { "commands", RBAC_PERM_COMMAND_COMMANDS, true, &HandleCommandsCommand, "", NULL }, + { "cooldown", RBAC_PERM_COMMAND_COOLDOWN, false, &HandleCooldownCommand, "", NULL }, + { "damage", RBAC_PERM_COMMAND_DAMAGE, false, &HandleDamageCommand, "", NULL }, + { "dev", RBAC_PERM_COMMAND_DEV, false, &HandleDevCommand, "", NULL }, + { "die", RBAC_PERM_COMMAND_DIE, false, &HandleDieCommand, "", NULL }, + { "dismount", RBAC_PERM_COMMAND_DISMOUNT, false, &HandleDismountCommand, "", NULL }, + { "distance", RBAC_PERM_COMMAND_DISTANCE, false, &HandleGetDistanceCommand, "", NULL }, + { "freeze", RBAC_PERM_COMMAND_FREEZE, false, &HandleFreezeCommand, "", NULL }, + { "gps", RBAC_PERM_COMMAND_GPS, false, &HandleGPSCommand, "", NULL }, + { "guid", RBAC_PERM_COMMAND_GUID, false, &HandleGUIDCommand, "", NULL }, + { "help", RBAC_PERM_COMMAND_HELP, true, &HandleHelpCommand, "", NULL }, + { "hidearea", RBAC_PERM_COMMAND_HIDEAREA, false, &HandleHideAreaCommand, "", NULL }, + { "itemmove", RBAC_PERM_COMMAND_ITEMMOVE, false, &HandleItemMoveCommand, "", NULL }, + { "kick", RBAC_PERM_COMMAND_KICK, true, &HandleKickPlayerCommand, "", NULL }, + { "linkgrave", RBAC_PERM_COMMAND_LINKGRAVE, false, &HandleLinkGraveCommand, "", NULL }, + { "listfreeze", RBAC_PERM_COMMAND_LISTFREEZE, false, &HandleListFreezeCommand, "", NULL }, + { "maxskill", RBAC_PERM_COMMAND_MAXSKILL, false, &HandleMaxSkillCommand, "", NULL }, + { "movegens", RBAC_PERM_COMMAND_MOVEGENS, false, &HandleMovegensCommand, "", NULL }, + { "mute", RBAC_PERM_COMMAND_MUTE, true, &HandleMuteCommand, "", NULL }, + { "neargrave", RBAC_PERM_COMMAND_NEARGRAVE, false, &HandleNearGraveCommand, "", NULL }, + { "pinfo", RBAC_PERM_COMMAND_PINFO, true, &HandlePInfoCommand, "", NULL }, + { "playall", RBAC_PERM_COMMAND_PLAYALL, false, &HandlePlayAllCommand, "", NULL }, + { "possess", RBAC_PERM_COMMAND_POSSESS, false, &HandlePossessCommand, "", NULL }, + { "recall", RBAC_PERM_COMMAND_RECALL, false, &HandleRecallCommand, "", NULL }, + { "repairitems", RBAC_PERM_COMMAND_REPAIRITEMS, true, &HandleRepairitemsCommand, "", NULL }, + { "respawn", RBAC_PERM_COMMAND_RESPAWN, false, &HandleRespawnCommand, "", NULL }, + { "revive", RBAC_PERM_COMMAND_REVIVE, true, &HandleReviveCommand, "", NULL }, + { "saveall", RBAC_PERM_COMMAND_SAVEALL, true, &HandleSaveAllCommand, "", NULL }, + { "save", RBAC_PERM_COMMAND_SAVE, false, &HandleSaveCommand, "", NULL }, + { "setskill", RBAC_PERM_COMMAND_SETSKILL, false, &HandleSetSkillCommand, "", NULL }, + { "showarea", RBAC_PERM_COMMAND_SHOWAREA, false, &HandleShowAreaCommand, "", NULL }, + { "summon", RBAC_PERM_COMMAND_SUMMON, false, &HandleSummonCommand, "", NULL }, + { "unaura", RBAC_PERM_COMMAND_UNAURA, false, &HandleUnAuraCommand, "", NULL }, + { "unbindsight", RBAC_PERM_COMMAND_UNBINDSIGHT, false, HandleUnbindSightCommand, "", NULL }, + { "unfreeze", RBAC_PERM_COMMAND_UNFREEZE, false, &HandleUnFreezeCommand, "", NULL }, + { "unmute", RBAC_PERM_COMMAND_UNMUTE, true, &HandleUnmuteCommand, "", NULL }, + { "unpossess", RBAC_PERM_COMMAND_UNPOSSESS, false, &HandleUnPossessCommand, "", NULL }, + { "unstuck", RBAC_PERM_COMMAND_UNSTUCK, true, &HandleUnstuckCommand, "", NULL }, + { "wchange", RBAC_PERM_COMMAND_WCHANGE, false, &HandleChangeWeather, "", NULL }, + { NULL, 0, false, NULL, "", NULL } }; return commandTable; } @@ -545,97 +517,6 @@ public: return true; } - // Summon group of player - static bool HandleGroupSummonCommand(ChatHandler* handler, char const* args) - { - Player* target; - if (!handler->extractPlayerTarget((char*)args, &target)) - return false; - - // check online security - if (handler->HasLowerSecurity(target, 0)) - return false; - - Group* group = target->GetGroup(); - - std::string nameLink = handler->GetNameLink(target); - - if (!group) - { - handler->PSendSysMessage(LANG_NOT_IN_GROUP, nameLink.c_str()); - handler->SetSentErrorMessage(true); - return false; - } - - Map* gmMap = handler->GetSession()->GetPlayer()->GetMap(); - bool toInstance = gmMap->Instanceable(); - - // we are in instance, and can summon only player in our group with us as lead - if (toInstance && ( - !handler->GetSession()->GetPlayer()->GetGroup() || (group->GetLeaderGUID() != handler->GetSession()->GetPlayer()->GetGUID()) || - (handler->GetSession()->GetPlayer()->GetGroup()->GetLeaderGUID() != handler->GetSession()->GetPlayer()->GetGUID()))) - // the last check is a bit excessive, but let it be, just in case - { - handler->SendSysMessage(LANG_CANNOT_SUMMON_TO_INST); - handler->SetSentErrorMessage(true); - return false; - } - - for (GroupReference* itr = group->GetFirstMember(); itr != NULL; itr = itr->next()) - { - Player* player = itr->GetSource(); - - if (!player || player == handler->GetSession()->GetPlayer() || !player->GetSession()) - continue; - - // check online security - if (handler->HasLowerSecurity(player, 0)) - return false; - - std::string plNameLink = handler->GetNameLink(player); - - if (player->IsBeingTeleported() == true) - { - handler->PSendSysMessage(LANG_IS_TELEPORTED, plNameLink.c_str()); - handler->SetSentErrorMessage(true); - return false; - } - - if (toInstance) - { - Map* playerMap = player->GetMap(); - - if (playerMap->Instanceable() && playerMap->GetInstanceId() != gmMap->GetInstanceId()) - { - // cannot summon from instance to instance - handler->PSendSysMessage(LANG_CANNOT_SUMMON_TO_INST, plNameLink.c_str()); - handler->SetSentErrorMessage(true); - return false; - } - } - - handler->PSendSysMessage(LANG_SUMMONING, plNameLink.c_str(), ""); - if (handler->needReportToTarget(player)) - ChatHandler(player->GetSession()).PSendSysMessage(LANG_SUMMONED_BY, handler->GetNameLink().c_str()); - - // stop flight if need - if (player->IsInFlight()) - { - player->GetMotionMaster()->MovementExpired(); - player->CleanupAfterTaxiFlight(); - } - // save only in non-flight case - else - player->SaveRecallPosition(); - - // before GM - float x, y, z; - handler->GetSession()->GetPlayer()->GetClosePoint(x, y, z, player->GetObjectSize()); - player->TeleportTo(handler->GetSession()->GetPlayer()->GetMapId(), x, y, z, player->GetOrientation()); - } - - return true; - } static bool HandleCommandsCommand(ChatHandler* handler, char const* /*args*/) { @@ -1519,20 +1400,21 @@ public: * ** Muted: (Time, Reason, By) - IV. LANG_PINFO_MUTED (if muted) * * Account: %s (id: %u), GM Level: %u - V. LANG_PINFO_ACC_ACCOUNT * * Last Login: %u (Failed Logins: %u) - VI. LANG_PINFO_ACC_LASTLOGIN - * * Uses OS: %s - Latency: %u ms - Email %s - VII. LANG_PINFO_ACC_OS - * * Last IP: %u (Locked: %s) - VIII. LANG_PINFO_ACC_IP - * * Level: %u (%u/%u XP (%u XP left) - IX. LANG_PINFO_CHR_LEVEL - * * Race: %s %s, Class %s - X. LANG_PINFO_CHR_RACE - * * Alive ?: %s - XI. LANG_PINFO_CHR_ALIVE - * * Phase: %s - XII. LANG_PINFO_CHR_PHASE (if not GM) - * * Money: %ug%us%uc - XIII. LANG_PINFO_CHR_MONEY - * * Map: %s, Area: %s - XIV. LANG_PINFO_CHR_MAP - * * Guild: %s (Id: %u) - XV. LANG_PINFO_CHR_GUILD (if in guild) - * ** Rank: %s - XVI. LANG_PINFO_CHR_GUILD_RANK (if in guild) - * ** Note: %s - XVII. LANG_PINFO_CHR_GUILD_NOTE (if in guild and has note) - * ** O. Note: %s - XVIII.LANG_PINFO_CHR_GUILD_ONOTE (if in guild and has officer note) - * * Played time: %s - XIX. LANG_PINFO_CHR_PLAYEDTIME - * * Mails: %u Read/%u Total - XX. LANG_PINFO_CHR_MAILS (if has mails) + * * Uses OS: %s - Latency: %u ms - VII. LANG_PINFO_ACC_OS + * * Registration Email: %s - Email: %s - VIII. LANG_PINFO_ACC_REGMAILS + * * Last IP: %u (Locked: %s) - IX. LANG_PINFO_ACC_IP + * * Level: %u (%u/%u XP (%u XP left) - X. LANG_PINFO_CHR_LEVEL + * * Race: %s %s, Class %s - XI. LANG_PINFO_CHR_RACE + * * Alive ?: %s - XII. LANG_PINFO_CHR_ALIVE + * * Phase: %s - XIII. LANG_PINFO_CHR_PHASE (if not GM) + * * Money: %ug%us%uc - XIV. LANG_PINFO_CHR_MONEY + * * Map: %s, Area: %s - XV. LANG_PINFO_CHR_MAP + * * Guild: %s (Id: %u) - XVI. LANG_PINFO_CHR_GUILD (if in guild) + * ** Rank: %s - XVII. LANG_PINFO_CHR_GUILD_RANK (if in guild) + * ** Note: %s - XVIII.LANG_PINFO_CHR_GUILD_NOTE (if in guild and has note) + * ** O. Note: %s - XVIX. LANG_PINFO_CHR_GUILD_ONOTE (if in guild and has officer note) + * * Played time: %s - XX. LANG_PINFO_CHR_PLAYEDTIME + * * Mails: %u Read/%u Total - XXI. LANG_PINFO_CHR_MAILS (if has mails) * * Not all of them can be moved to the top. These should * place the most important ones to the head, though. @@ -1545,6 +1427,7 @@ public: uint32 accId = 0; uint32 lowguid = GUID_LOPART(targetGuid); std::string eMail = handler->GetTrinityString(LANG_ERROR); + std::string regMail = handler->GetTrinityString(LANG_ERROR); uint32 security = 0; std::string lastIp = handler->GetTrinityString(LANG_ERROR); uint8 locked = 0; @@ -1665,8 +1548,9 @@ public: (!handler->GetSession() || handler->GetSession()->GetSecurity() >= AccountTypes(security))) { eMail = fields[2].GetString(); - lastIp = fields[3].GetString(); - lastLogin = fields[4].GetString(); + regMail = fields[3].GetString(); + lastIp = fields[4].GetString(); + lastLogin = fields[5].GetString(); uint32 ip = inet_addr(lastIp.c_str()); EndianConvertReverse(ip); @@ -1688,12 +1572,12 @@ public: lastIp = "Unauthorized"; lastLogin = "Unauthorized"; } - muteTime = fields[5].GetUInt64(); - muteReason = fields[6].GetString(); - muteBy = fields[7].GetString(); - failedLogins = fields[8].GetUInt32(); - locked = fields[9].GetUInt8(); - OS = fields[10].GetString(); + muteTime = fields[6].GetUInt64(); + muteReason = fields[7].GetString(); + muteBy = fields[8].GetString(); + failedLogins = fields[9].GetUInt32(); + locked = fields[10].GetUInt8(); + OS = fields[11].GetString(); } // Creates a chat link to the character. Returns nameLink @@ -1782,8 +1666,11 @@ public: // Output VI. LANG_PINFO_ACC_LASTLOGIN handler->PSendSysMessage(LANG_PINFO_ACC_LASTLOGIN, lastLogin.c_str(), failedLogins); - // Output VIII. LANG_PINFO_ACC_OS - handler->PSendSysMessage(LANG_PINFO_ACC_OS, OS.c_str(), latency, eMail.c_str()); + // Output VII. LANG_PINFO_ACC_OS + handler->PSendSysMessage(LANG_PINFO_ACC_OS, OS.c_str(), latency); + + // Output VIII. LANG_PINFO_ACC_REGMAILS + handler->PSendSysMessage(LANG_PINFO_ACC_REGMAILS, regMail.c_str(), eMail.c_str()); // Output IX. LANG_PINFO_ACC_IP handler->PSendSysMessage(LANG_PINFO_ACC_IP, lastIp.c_str(), locked ? "Yes" : "No"); @@ -1827,7 +1714,7 @@ public: if (target) handler->PSendSysMessage(LANG_PINFO_CHR_MAP, map->name, (!zoneName.empty() ? zoneName.c_str() : "<Unknown>"), (!areaName.empty() ? areaName.c_str() : "<Unknown>")); - // Output XVII. - XX. if they are not empty + // Output XVII. - XVIX. if they are not empty if (!guildName.empty()) { handler->PSendSysMessage(LANG_PINFO_CHR_GUILD, guildName.c_str(), guildId); @@ -1838,7 +1725,7 @@ public: handler->PSendSysMessage(LANG_PINFO_CHR_GUILD_ONOTE, officeNote.c_str()); } - // Output XXI. LANG_PINFO_CHR_PLAYEDTIME + // Output XX. LANG_PINFO_CHR_PLAYEDTIME handler->PSendSysMessage(LANG_PINFO_CHR_PLAYEDTIME, (secsToTimeString(totalPlayerTime, true, true)).c_str()); // Mail Data - an own query, because it may or may not be useful. @@ -1860,7 +1747,7 @@ public: // ... we have to convert it from Char to int. We can use totalmail as it is rmailint = atol(readmail.c_str()); - // Output XXII. LANG_INFO_CHR_MAILS if at least one mail is given + // Output XXI. LANG_INFO_CHR_MAILS if at least one mail is given if (totalmail >= 1) handler->PSendSysMessage(LANG_PINFO_CHR_MAILS, rmailint, totalmail); } @@ -2345,380 +2232,6 @@ public: return true; } - // Send mail by command - static bool HandleSendMailCommand(ChatHandler* handler, char const* args) - { - // format: name "subject text" "mail text" - Player* target; - uint64 targetGuid; - std::string targetName; - if (!handler->extractPlayerTarget((char*)args, &target, &targetGuid, &targetName)) - return false; - - char* tail1 = strtok(NULL, ""); - if (!tail1) - return false; - - char const* msgSubject = handler->extractQuotedArg(tail1); - if (!msgSubject) - return false; - - char* tail2 = strtok(NULL, ""); - if (!tail2) - return false; - - char const* msgText = handler->extractQuotedArg(tail2); - if (!msgText) - return false; - - // msgSubject, msgText isn't NUL after prev. check - std::string subject = msgSubject; - std::string text = msgText; - - // from console show not existed sender - MailSender sender(MAIL_NORMAL, handler->GetSession() ? handler->GetSession()->GetPlayer()->GetGUIDLow() : 0, MAIL_STATIONERY_GM); - - /// @todo Fix poor design - SQLTransaction trans = CharacterDatabase.BeginTransaction(); - MailDraft(subject, text) - .SendMailTo(trans, MailReceiver(target, GUID_LOPART(targetGuid)), sender); - - CharacterDatabase.CommitTransaction(trans); - - std::string nameLink = handler->playerLink(targetName); - handler->PSendSysMessage(LANG_MAIL_SENT, nameLink.c_str()); - return true; - } - // Send items by mail - static bool HandleSendItemsCommand(ChatHandler* handler, char const* args) - { - // format: name "subject text" "mail text" item1[:count1] item2[:count2] ... item12[:count12] - Player* receiver; - uint64 receiverGuid; - std::string receiverName; - if (!handler->extractPlayerTarget((char*)args, &receiver, &receiverGuid, &receiverName)) - return false; - - char* tail1 = strtok(NULL, ""); - if (!tail1) - return false; - - char const* msgSubject = handler->extractQuotedArg(tail1); - if (!msgSubject) - return false; - - char* tail2 = strtok(NULL, ""); - if (!tail2) - return false; - - char const* msgText = handler->extractQuotedArg(tail2); - if (!msgText) - return false; - - // msgSubject, msgText isn't NUL after prev. check - std::string subject = msgSubject; - std::string text = msgText; - - // extract items - typedef std::pair<uint32, uint32> ItemPair; - typedef std::list< ItemPair > ItemPairs; - ItemPairs items; - - // get all tail string - char* tail = strtok(NULL, ""); - - // get from tail next item str - while (char* itemStr = strtok(tail, " ")) - { - // and get new tail - tail = strtok(NULL, ""); - - // parse item str - char const* itemIdStr = strtok(itemStr, ":"); - char const* itemCountStr = strtok(NULL, " "); - - uint32 itemId = atoi(itemIdStr); - if (!itemId) - return false; - - ItemTemplate const* item_proto = sObjectMgr->GetItemTemplate(itemId); - if (!item_proto) - { - handler->PSendSysMessage(LANG_COMMAND_ITEMIDINVALID, itemId); - handler->SetSentErrorMessage(true); - return false; - } - - uint32 itemCount = itemCountStr ? atoi(itemCountStr) : 1; - if (itemCount < 1 || (item_proto->MaxCount > 0 && itemCount > uint32(item_proto->MaxCount))) - { - handler->PSendSysMessage(LANG_COMMAND_INVALID_ITEM_COUNT, itemCount, itemId); - handler->SetSentErrorMessage(true); - return false; - } - - while (itemCount > item_proto->GetMaxStackSize()) - { - items.push_back(ItemPair(itemId, item_proto->GetMaxStackSize())); - itemCount -= item_proto->GetMaxStackSize(); - } - - items.push_back(ItemPair(itemId, itemCount)); - - if (items.size() > MAX_MAIL_ITEMS) - { - handler->PSendSysMessage(LANG_COMMAND_MAIL_ITEMS_LIMIT, MAX_MAIL_ITEMS); - handler->SetSentErrorMessage(true); - return false; - } - } - - // from console show not existed sender - MailSender sender(MAIL_NORMAL, handler->GetSession() ? handler->GetSession()->GetPlayer()->GetGUIDLow() : 0, MAIL_STATIONERY_GM); - - // fill mail - MailDraft draft(subject, text); - - SQLTransaction trans = CharacterDatabase.BeginTransaction(); - - for (ItemPairs::const_iterator itr = items.begin(); itr != items.end(); ++itr) - { - if (Item* item = Item::CreateItem(itr->first, itr->second, handler->GetSession() ? handler->GetSession()->GetPlayer() : 0)) - { - item->SaveToDB(trans); // save for prevent lost at next mail load, if send fail then item will deleted - draft.AddItem(item); - } - } - - draft.SendMailTo(trans, MailReceiver(receiver, GUID_LOPART(receiverGuid)), sender); - CharacterDatabase.CommitTransaction(trans); - - std::string nameLink = handler->playerLink(receiverName); - handler->PSendSysMessage(LANG_MAIL_SENT, nameLink.c_str()); - return true; - } - /// Send money by mail - static bool HandleSendMoneyCommand(ChatHandler* handler, char const* args) - { - /// format: name "subject text" "mail text" money - - Player* receiver; - uint64 receiverGuid; - std::string receiverName; - if (!handler->extractPlayerTarget((char*)args, &receiver, &receiverGuid, &receiverName)) - return false; - - char* tail1 = strtok(NULL, ""); - if (!tail1) - return false; - - char* msgSubject = handler->extractQuotedArg(tail1); - if (!msgSubject) - return false; - - char* tail2 = strtok(NULL, ""); - if (!tail2) - return false; - - char* msgText = handler->extractQuotedArg(tail2); - if (!msgText) - return false; - - char* moneyStr = strtok(NULL, ""); - int32 money = moneyStr ? atoi(moneyStr) : 0; - if (money <= 0) - return false; - - // msgSubject, msgText isn't NUL after prev. check - std::string subject = msgSubject; - std::string text = msgText; - - // from console show not existed sender - MailSender sender(MAIL_NORMAL, handler->GetSession() ? handler->GetSession()->GetPlayer()->GetGUIDLow() : 0, MAIL_STATIONERY_GM); - - SQLTransaction trans = CharacterDatabase.BeginTransaction(); - - MailDraft(subject, text) - .AddMoney(money) - .SendMailTo(trans, MailReceiver(receiver, GUID_LOPART(receiverGuid)), sender); - - CharacterDatabase.CommitTransaction(trans); - - std::string nameLink = handler->playerLink(receiverName); - handler->PSendSysMessage(LANG_MAIL_SENT, nameLink.c_str()); - return true; - } - /// Send a message to a player in game - static bool HandleSendMessageCommand(ChatHandler* handler, char const* args) - { - /// - Find the player - Player* player; - if (!handler->extractPlayerTarget((char*)args, &player)) - return false; - - char* msgStr = strtok(NULL, ""); - if (!msgStr) - return false; - - ///- Check that he is not logging out. - if (player->GetSession()->isLogingOut()) - { - handler->SendSysMessage(LANG_PLAYER_NOT_FOUND); - handler->SetSentErrorMessage(true); - return false; - } - - /// - Send the message - // Use SendAreaTriggerMessage for fastest delivery. - player->GetSession()->SendAreaTriggerMessage("%s", msgStr); - player->GetSession()->SendAreaTriggerMessage("|cffff0000[Message from administrator]:|r"); - - // Confirmation message - std::string nameLink = handler->GetNameLink(player); - handler->PSendSysMessage(LANG_SENDMESSAGE, nameLink.c_str(), msgStr); - - return true; - } - - static bool HandleCreatePetCommand(ChatHandler* handler, char const* /*args*/) - { - Player* player = handler->GetSession()->GetPlayer(); - Creature* creatureTarget = handler->getSelectedCreature(); - - if (!creatureTarget || creatureTarget->IsPet() || creatureTarget->GetTypeId() == TYPEID_PLAYER) - { - handler->PSendSysMessage(LANG_SELECT_CREATURE); - handler->SetSentErrorMessage(true); - return false; - } - - CreatureTemplate const* creatrueTemplate = sObjectMgr->GetCreatureTemplate(creatureTarget->GetEntry()); - // Creatures with family 0 crashes the server - if (!creatrueTemplate->family) - { - handler->PSendSysMessage("This creature cannot be tamed. (family id: 0)."); - handler->SetSentErrorMessage(true); - return false; - } - - if (player->GetPetGUID()) - { - handler->PSendSysMessage("You already have a pet"); - handler->SetSentErrorMessage(true); - return false; - } - - // Everything looks OK, create new pet - Pet* pet = new Pet(player, HUNTER_PET); - if (!pet->CreateBaseAtCreature(creatureTarget)) - { - delete pet; - handler->PSendSysMessage("Error 1"); - return false; - } - - creatureTarget->setDeathState(JUST_DIED); - creatureTarget->RemoveCorpse(); - creatureTarget->SetHealth(0); // just for nice GM-mode view - - pet->SetUInt64Value(UNIT_FIELD_CREATEDBY, player->GetGUID()); - pet->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, player->getFaction()); - - if (!pet->InitStatsForLevel(creatureTarget->getLevel())) - { - TC_LOG_ERROR(LOG_FILTER_GENERAL, "InitStatsForLevel() in EffectTameCreature failed! Pet deleted."); - handler->PSendSysMessage("Error 2"); - delete pet; - return false; - } - - // prepare visual effect for levelup - pet->SetUInt32Value(UNIT_FIELD_LEVEL, creatureTarget->getLevel()-1); - - pet->GetCharmInfo()->SetPetNumber(sObjectMgr->GeneratePetNumber(), true); - // this enables pet details window (Shift+P) - pet->InitPetCreateSpells(); - pet->SetFullHealth(); - - pet->GetMap()->AddToMap(pet->ToCreature()); - - // visual effect for levelup - pet->SetUInt32Value(UNIT_FIELD_LEVEL, creatureTarget->getLevel()); - - player->SetMinion(pet, true); - pet->SavePetToDB(PET_SAVE_AS_CURRENT); - player->PetSpellInitialize(); - - return true; - } - - static bool HandlePetLearnCommand(ChatHandler* handler, char const* args) - { - if (!*args) - return false; - - Player* player = handler->GetSession()->GetPlayer(); - Pet* pet = player->GetPet(); - - if (!pet) - { - handler->PSendSysMessage("You have no pet"); - handler->SetSentErrorMessage(true); - return false; - } - - uint32 spellId = handler->extractSpellIdFromLink((char*)args); - - if (!spellId || !sSpellMgr->GetSpellInfo(spellId)) - return false; - - // Check if pet already has it - if (pet->HasSpell(spellId)) - { - handler->PSendSysMessage("Pet already has spell: %u", spellId); - handler->SetSentErrorMessage(true); - return false; - } - - // Check if spell is valid - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); - if (!spellInfo || !SpellMgr::IsSpellValid(spellInfo)) - { - handler->PSendSysMessage(LANG_COMMAND_SPELL_BROKEN, spellId); - handler->SetSentErrorMessage(true); - return false; - } - - pet->learnSpell(spellId); - - handler->PSendSysMessage("Pet has learned spell %u", spellId); - return true; - } - - static bool HandlePetUnlearnCommand(ChatHandler* handler, char const* args) - { - if (!*args) - return false; - - Player* player = handler->GetSession()->GetPlayer(); - Pet* pet = player->GetPet(); - if (!pet) - { - handler->PSendSysMessage("You have no pet"); - handler->SetSentErrorMessage(true); - return false; - } - - uint32 spellId = handler->extractSpellIdFromLink((char*)args); - - if (pet->HasSpell(spellId)) - pet->removeSpell(spellId, false); - else - handler->PSendSysMessage("Pet doesn't have that spell"); - - return true; - } - static bool HandleFreezeCommand(ChatHandler* handler, char const* args) { std::string name; @@ -2881,177 +2394,6 @@ public: return true; } - static bool HandleGroupLeaderCommand(ChatHandler* handler, char const* args) - { - Player* player = NULL; - Group* group = NULL; - uint64 guid = 0; - char* nameStr = strtok((char*)args, " "); - - if (handler->GetPlayerGroupAndGUIDByName(nameStr, player, group, guid)) - if (group && group->GetLeaderGUID() != guid) - { - group->ChangeLeader(guid); - group->SendUpdate(); - } - - return true; - } - - static bool HandleGroupDisbandCommand(ChatHandler* handler, char const* args) - { - Player* player = NULL; - Group* group = NULL; - uint64 guid = 0; - char* nameStr = strtok((char*)args, " "); - - if (handler->GetPlayerGroupAndGUIDByName(nameStr, player, group, guid)) - if (group) - group->Disband(); - - return true; - } - - static bool HandleGroupRemoveCommand(ChatHandler* handler, char const* args) - { - Player* player = NULL; - Group* group = NULL; - uint64 guid = 0; - char* nameStr = strtok((char*)args, " "); - - if (handler->GetPlayerGroupAndGUIDByName(nameStr, player, group, guid, true)) - if (group) - group->RemoveMember(guid); - - return true; - } - - static bool HandleGroupJoinCommand(ChatHandler* handler, char const* args) - { - if (!*args) - return false; - - Player* playerSource = NULL; - Player* playerTarget = NULL; - Group* groupSource = NULL; - Group* groupTarget = NULL; - uint64 guidSource = 0; - uint64 guidTarget = 0; - char* nameplgrStr = strtok((char*)args, " "); - char* nameplStr = strtok(NULL, " "); - - if (handler->GetPlayerGroupAndGUIDByName(nameplgrStr, playerSource, groupSource, guidSource, true)) - { - if (groupSource) - { - if (handler->GetPlayerGroupAndGUIDByName(nameplStr, playerTarget, groupTarget, guidTarget, true)) - { - if (!groupTarget && playerTarget->GetGroup() != groupSource) - { - if (!groupSource->IsFull()) - { - groupSource->AddMember(playerTarget); - groupSource->BroadcastGroupUpdate(); - handler->PSendSysMessage(LANG_GROUP_PLAYER_JOINED, playerTarget->GetName().c_str(), playerSource->GetName().c_str()); - return true; - } - else - { - // group is full - handler->PSendSysMessage(LANG_GROUP_FULL); - return true; - } - } - else - { - // group is full or target player already in a group - handler->PSendSysMessage(LANG_GROUP_ALREADY_IN_GROUP, playerTarget->GetName().c_str()); - return true; - } - } - } - else - { - // specified source player is not in a group - handler->PSendSysMessage(LANG_GROUP_NOT_IN_GROUP, playerSource->GetName().c_str()); - return true; - } - } - - return true; - } - - static bool HandleGroupListCommand(ChatHandler* handler, char const* args) - { - Player* playerTarget; - uint64 guidTarget; - std::string nameTarget; - - uint32 parseGUID = MAKE_NEW_GUID(atol((char*)args), 0, HIGHGUID_PLAYER); - - if (sObjectMgr->GetPlayerNameByGUID(parseGUID, nameTarget)) - { - playerTarget = sObjectMgr->GetPlayerByLowGUID(parseGUID); - guidTarget = parseGUID; - } - else if (!handler->extractPlayerTarget((char*)args, &playerTarget, &guidTarget, &nameTarget)) - return false; - - Group* groupTarget = NULL; - if (playerTarget) - groupTarget = playerTarget->GetGroup(); - - if (!groupTarget) - { - PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GROUP_MEMBER); - stmt->setUInt32(0, guidTarget); - PreparedQueryResult resultGroup = CharacterDatabase.Query(stmt); - if (resultGroup) - groupTarget = sGroupMgr->GetGroupByDbStoreId((*resultGroup)[0].GetUInt32()); - } - - if (groupTarget) - { - handler->PSendSysMessage(LANG_GROUP_TYPE, (groupTarget->isRaidGroup() ? "raid" : "party")); - Group::MemberSlotList const& members = groupTarget->GetMemberSlots(); - for (Group::MemberSlotList::const_iterator itr = members.begin(); itr != members.end(); ++itr) - { - Group::MemberSlot const& slot = *itr; - - std::string flags; - if (slot.flags & MEMBER_FLAG_ASSISTANT) - flags = "Assistant"; - - if (slot.flags & MEMBER_FLAG_MAINTANK) - { - if (!flags.empty()) - flags.append(", "); - flags.append("MainTank"); - } - - if (slot.flags & MEMBER_FLAG_MAINASSIST) - { - if (!flags.empty()) - flags.append(", "); - flags.append("MainAssist"); - } - - if (flags.empty()) - flags = "None"; - - Player* p = ObjectAccessor::FindPlayer((*itr).guid); - const char* onlineState = (p && p->IsInWorld()) ? "online" : "offline"; - - handler->PSendSysMessage(LANG_GROUP_PLAYER_NAME_GUID, slot.name.c_str(), onlineState, - GUID_LOPART(slot.guid), flags.c_str(), lfg::GetRolesString(slot.roles).c_str()); - } - } - else - handler->PSendSysMessage(LANG_GROUP_NOT_IN_GROUP, nameTarget.c_str()); - - return true; - } - static bool HandlePlayAllCommand(ChatHandler* handler, char const* args) { if (!*args) diff --git a/src/server/scripts/Commands/cs_mmaps.cpp b/src/server/scripts/Commands/cs_mmaps.cpp index 4d7b42e1885..caefcceb886 100644 --- a/src/server/scripts/Commands/cs_mmaps.cpp +++ b/src/server/scripts/Commands/cs_mmaps.cpp @@ -45,18 +45,18 @@ public: { static ChatCommand mmapCommandTable[] = { - { "path", SEC_ADMINISTRATOR, false, &HandleMmapPathCommand, "", NULL }, - { "loc", SEC_ADMINISTRATOR, false, &HandleMmapLocCommand, "", NULL }, - { "loadedtiles", SEC_ADMINISTRATOR, false, &HandleMmapLoadedTilesCommand, "", NULL }, - { "stats", SEC_ADMINISTRATOR, false, &HandleMmapStatsCommand, "", NULL }, - { "testarea", SEC_ADMINISTRATOR, false, &HandleMmapTestArea, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "loadedtiles", RBAC_PERM_COMMAND_MMAP_LOADEDTILES, false, &HandleMmapLoadedTilesCommand, "", NULL }, + { "loc", RBAC_PERM_COMMAND_MMAP_LOC, false, &HandleMmapLocCommand, "", NULL }, + { "path", RBAC_PERM_COMMAND_MMAP_PATH, false, &HandleMmapPathCommand, "", NULL }, + { "stats", RBAC_PERM_COMMAND_MMAP_STATS, false, &HandleMmapStatsCommand, "", NULL }, + { "testarea", RBAC_PERM_COMMAND_MMAP_TESTAREA, false, &HandleMmapTestArea, "", NULL }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand commandTable[] = { - { "mmap", SEC_ADMINISTRATOR, true, NULL, "", mmapCommandTable }, - { NULL, 0, false, NULL, "", NULL } + { "mmap", RBAC_PERM_COMMAND_MMAP, true, NULL, "", mmapCommandTable }, + { NULL, 0, false, NULL, "", NULL } }; return commandTable; } diff --git a/src/server/scripts/Commands/cs_modify.cpp b/src/server/scripts/Commands/cs_modify.cpp index c1ee051f277..67d9a4f692d 100644 --- a/src/server/scripts/Commands/cs_modify.cpp +++ b/src/server/scripts/Commands/cs_modify.cpp @@ -41,44 +41,44 @@ public: { static ChatCommand modifyspeedCommandTable[] = { - { "fly", SEC_MODERATOR, false, &HandleModifyFlyCommand, "", NULL }, - { "all", SEC_MODERATOR, false, &HandleModifyASpeedCommand, "", NULL }, - { "walk", SEC_MODERATOR, false, &HandleModifySpeedCommand, "", NULL }, - { "backwalk", SEC_MODERATOR, false, &HandleModifyBWalkCommand, "", NULL }, - { "swim", SEC_MODERATOR, false, &HandleModifySwimCommand, "", NULL }, - { "", SEC_MODERATOR, false, &HandleModifyASpeedCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "all", RBAC_PERM_COMMAND_MODIFY_SPEED_ALL, false, &HandleModifyASpeedCommand, "", NULL }, + { "backwalk", RBAC_PERM_COMMAND_MODIFY_SPEED_BACKWALK, false, &HandleModifyBWalkCommand, "", NULL }, + { "fly", RBAC_PERM_COMMAND_MODIFY_SPEED_FLY, false, &HandleModifyFlyCommand, "", NULL }, + { "walk", RBAC_PERM_COMMAND_MODIFY_SPEED_WALK, false, &HandleModifySpeedCommand, "", NULL }, + { "swim", RBAC_PERM_COMMAND_MODIFY_SPEED_SWIM, false, &HandleModifySwimCommand, "", NULL }, + { "", RBAC_PERM_COMMAND_MODIFY_SPEED, false, &HandleModifyASpeedCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand modifyCommandTable[] = { - { "hp", SEC_MODERATOR, false, &HandleModifyHPCommand, "", NULL }, - { "mana", SEC_MODERATOR, false, &HandleModifyManaCommand, "", NULL }, - { "rage", SEC_MODERATOR, false, &HandleModifyRageCommand, "", NULL }, - { "runicpower", SEC_MODERATOR, false, &HandleModifyRunicPowerCommand, "", NULL }, - { "energy", SEC_MODERATOR, false, &HandleModifyEnergyCommand, "", NULL }, - { "money", SEC_MODERATOR, false, &HandleModifyMoneyCommand, "", NULL }, - { "scale", SEC_MODERATOR, false, &HandleModifyScaleCommand, "", NULL }, - { "bit", SEC_MODERATOR, false, &HandleModifyBitCommand, "", NULL }, - { "faction", SEC_MODERATOR, false, &HandleModifyFactionCommand, "", NULL }, - { "spell", SEC_MODERATOR, false, &HandleModifySpellCommand, "", NULL }, - { "talentpoints", SEC_MODERATOR, false, &HandleModifyTalentCommand, "", NULL }, - { "mount", SEC_MODERATOR, false, &HandleModifyMountCommand, "", NULL }, - { "honor", SEC_MODERATOR, false, &HandleModifyHonorCommand, "", NULL }, - { "reputation", SEC_GAMEMASTER, false, &HandleModifyRepCommand, "", NULL }, - { "drunk", SEC_MODERATOR, false, &HandleModifyDrunkCommand, "", NULL }, - { "standstate", SEC_GAMEMASTER, false, &HandleModifyStandStateCommand, "", NULL }, - { "phase", SEC_ADMINISTRATOR, false, &HandleModifyPhaseCommand, "", NULL }, - { "gender", SEC_GAMEMASTER, false, &HandleModifyGenderCommand, "", NULL }, - { "currency", SEC_GAMEMASTER, false, &HandleModifyCurrencyCommand, "", NULL }, - { "speed", SEC_MODERATOR, false, NULL, "", modifyspeedCommandTable }, - { NULL, 0, false, NULL, "", NULL } + { "bit", RBAC_PERM_COMMAND_MODIFY_BIT, false, &HandleModifyBitCommand, "", NULL }, + { "currency", RBAC_PERM_COMMAND_MODIFY_CURRENCY, false, &HandleModifyCurrencyCommand, "", NULL }, + { "drunk", RBAC_PERM_COMMAND_MODIFY_DRUNK, false, &HandleModifyDrunkCommand, "", NULL }, + { "energy", RBAC_PERM_COMMAND_MODIFY_ENERGY, false, &HandleModifyEnergyCommand, "", NULL }, + { "faction", RBAC_PERM_COMMAND_MODIFY_FACTION, false, &HandleModifyFactionCommand, "", NULL }, + { "gender", RBAC_PERM_COMMAND_MODIFY_GENDER, false, &HandleModifyGenderCommand, "", NULL }, + { "honor", RBAC_PERM_COMMAND_MODIFY_HONOR, false, &HandleModifyHonorCommand, "", NULL }, + { "hp", RBAC_PERM_COMMAND_MODIFY_HP, false, &HandleModifyHPCommand, "", NULL }, + { "mana", RBAC_PERM_COMMAND_MODIFY_MANA, false, &HandleModifyManaCommand, "", NULL }, + { "money", RBAC_PERM_COMMAND_MODIFY_MONEY, false, &HandleModifyMoneyCommand, "", NULL }, + { "mount", RBAC_PERM_COMMAND_MODIFY_MOUNT, false, &HandleModifyMountCommand, "", NULL }, + { "phase", RBAC_PERM_COMMAND_MODIFY_PHASE, false, &HandleModifyPhaseCommand, "", NULL }, + { "rage", RBAC_PERM_COMMAND_MODIFY_RAGE, false, &HandleModifyRageCommand, "", NULL }, + { "reputation", RBAC_PERM_COMMAND_MODIFY_REPUTATION, false, &HandleModifyRepCommand, "", NULL }, + { "runicpower", RBAC_PERM_COMMAND_MODIFY_RUNICPOWER, false, &HandleModifyRunicPowerCommand, "", NULL }, + { "scale", RBAC_PERM_COMMAND_MODIFY_SCALE, false, &HandleModifyScaleCommand, "", NULL }, + { "speed", RBAC_PERM_COMMAND_MODIFY_SPEED, false, NULL, "", modifyspeedCommandTable }, + { "spell", RBAC_PERM_COMMAND_MODIFY_SPELL, false, &HandleModifySpellCommand, "", NULL }, + { "standstate", RBAC_PERM_COMMAND_MODIFY_STANDSTATE, false, &HandleModifyStandStateCommand, "", NULL }, + { "talentpoints", RBAC_PERM_COMMAND_MODIFY_TALENTPOINTS, false, &HandleModifyTalentCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand commandTable[] = { - { "morph", SEC_GAMEMASTER, false, &HandleModifyMorphCommand, "", NULL }, - { "demorph", SEC_GAMEMASTER, false, &HandleDeMorphCommand, "", NULL }, - { "modify", SEC_MODERATOR, false, NULL, "", modifyCommandTable }, - { NULL, 0, false, NULL, "", NULL } + { "morph", RBAC_PERM_COMMAND_MORPH, false, &HandleModifyMorphCommand, "", NULL }, + { "demorph", RBAC_PERM_COMMAND_DEMORPH, false, &HandleDeMorphCommand, "", NULL }, + { "modify", RBAC_PERM_COMMAND_MODIFY, false, NULL, "", modifyCommandTable }, + { NULL, 0, false, NULL, "", NULL } }; return commandTable; } @@ -1172,7 +1172,7 @@ public: int32 amount = 0; char *rankTxt = strtok(NULL, " "); - if (!factionTxt || !rankTxt) + if (!factionId || !rankTxt) return false; amount = atoi(rankTxt); diff --git a/src/server/scripts/Commands/cs_npc.cpp b/src/server/scripts/Commands/cs_npc.cpp index 56610c1ea29..233600e2a9c 100644 --- a/src/server/scripts/Commands/cs_npc.cpp +++ b/src/server/scripts/Commands/cs_npc.cpp @@ -33,15 +33,18 @@ EndScriptData */ #include "Player.h" #include "Pet.h" -struct NpcFlagText +template<typename E, typename T = char const*> +struct EnumName { - uint32 flag; - int32 text; + E Value; + T Name; }; +#define CREATE_NAMED_ENUM(VALUE) { VALUE, STRINGIZE(VALUE) } + #define NPCFLAG_COUNT 24 -NpcFlagText const npcFlagTexts[NPCFLAG_COUNT] = +EnumName<NPCFlags, int32> const npcFlagTexts[NPCFLAG_COUNT] = { { UNIT_NPC_FLAG_AUCTIONEER, LANG_NPCINFO_AUCTIONEER }, { UNIT_NPC_FLAG_BANKER, LANG_NPCINFO_BANKER }, @@ -69,90 +72,77 @@ NpcFlagText const npcFlagTexts[NPCFLAG_COUNT] = { UNIT_NPC_FLAG_VENDOR_REAGENT, LANG_NPCINFO_VENDOR_REAGENT } }; -struct MechanicImmune -{ - uint32 flag; - char const* text; -}; - -MechanicImmune const mechanicImmunes[MAX_MECHANIC] = -{ - { MECHANIC_NONE , "MECHANIC_NONE" }, - { MECHANIC_CHARM , "MECHANIC_CHARM" }, - { MECHANIC_DISORIENTED , "MECHANIC_DISORIENTED" }, - { MECHANIC_DISARM , "MECHANIC_DISARM" }, - { MECHANIC_DISTRACT , "MECHANIC_DISTRACT" }, - { MECHANIC_FEAR , "MECHANIC_FEAR" }, - { MECHANIC_GRIP , "MECHANIC_GRIP" }, - { MECHANIC_ROOT , "MECHANIC_ROOT" }, - { MECHANIC_SLOW_ATTACK , "MECHANIC_SLOW_ATTACK" }, - { MECHANIC_SILENCE , "MECHANIC_SILENCE" }, - { MECHANIC_SLEEP , "MECHANIC_SLEEP" }, - { MECHANIC_SNARE , "MECHANIC_SNARE" }, - { MECHANIC_STUN , "MECHANIC_STUN" }, - { MECHANIC_FREEZE , "MECHANIC_FREEZE" }, - { MECHANIC_KNOCKOUT , "MECHANIC_KNOCKOUT" }, - { MECHANIC_BLEED , "MECHANIC_BLEED" }, - { MECHANIC_BANDAGE , "MECHANIC_BANDAGE" }, - { MECHANIC_POLYMORPH , "MECHANIC_POLYMORPH" }, - { MECHANIC_BANISH , "MECHANIC_BANISH" }, - { MECHANIC_SHIELD , "MECHANIC_SHIELD" }, - { MECHANIC_SHACKLE , "MECHANIC_SHACKLE" }, - { MECHANIC_MOUNT , "MECHANIC_MOUNT" }, - { MECHANIC_INFECTED , "MECHANIC_INFECTED" }, - { MECHANIC_TURN , "MECHANIC_TURN" }, - { MECHANIC_HORROR , "MECHANIC_HORROR" }, - { MECHANIC_INVULNERABILITY , "MECHANIC_INVULNERABILITY" }, - { MECHANIC_INTERRUPT , "MECHANIC_INTERRUPT" }, - { MECHANIC_DAZE , "MECHANIC_DAZE" }, - { MECHANIC_DISCOVERY , "MECHANIC_DISCOVERY" }, - { MECHANIC_IMMUNE_SHIELD , "MECHANIC_IMMUNE_SHIELD" }, - { MECHANIC_SAPPED , "MECHANIC_SAPPED" }, - { MECHANIC_ENRAGED , "MECHANIC_ENRAGED" }, - { MECHANIC_WOUNDED , "MECHANIC_WOUNDED" } -}; - - -struct UnitFlag +EnumName<Mechanics> const mechanicImmunes[MAX_MECHANIC] = { - uint32 flag; - char const* text; + CREATE_NAMED_ENUM(MECHANIC_NONE), + CREATE_NAMED_ENUM(MECHANIC_CHARM), + CREATE_NAMED_ENUM(MECHANIC_DISORIENTED), + CREATE_NAMED_ENUM(MECHANIC_DISARM), + CREATE_NAMED_ENUM(MECHANIC_DISTRACT), + CREATE_NAMED_ENUM(MECHANIC_FEAR), + CREATE_NAMED_ENUM(MECHANIC_GRIP), + CREATE_NAMED_ENUM(MECHANIC_ROOT), + CREATE_NAMED_ENUM(MECHANIC_SLOW_ATTACK), + CREATE_NAMED_ENUM(MECHANIC_SILENCE), + CREATE_NAMED_ENUM(MECHANIC_SLEEP), + CREATE_NAMED_ENUM(MECHANIC_SNARE), + CREATE_NAMED_ENUM(MECHANIC_STUN), + CREATE_NAMED_ENUM(MECHANIC_FREEZE), + CREATE_NAMED_ENUM(MECHANIC_KNOCKOUT), + CREATE_NAMED_ENUM(MECHANIC_BLEED), + CREATE_NAMED_ENUM(MECHANIC_BANDAGE), + CREATE_NAMED_ENUM(MECHANIC_POLYMORPH), + CREATE_NAMED_ENUM(MECHANIC_BANISH), + CREATE_NAMED_ENUM(MECHANIC_SHIELD), + CREATE_NAMED_ENUM(MECHANIC_SHACKLE), + CREATE_NAMED_ENUM(MECHANIC_MOUNT), + CREATE_NAMED_ENUM(MECHANIC_INFECTED), + CREATE_NAMED_ENUM(MECHANIC_TURN), + CREATE_NAMED_ENUM(MECHANIC_HORROR), + CREATE_NAMED_ENUM(MECHANIC_INVULNERABILITY), + CREATE_NAMED_ENUM(MECHANIC_INTERRUPT), + CREATE_NAMED_ENUM(MECHANIC_DAZE), + CREATE_NAMED_ENUM(MECHANIC_DISCOVERY), + CREATE_NAMED_ENUM(MECHANIC_IMMUNE_SHIELD), + CREATE_NAMED_ENUM(MECHANIC_SAPPED), + CREATE_NAMED_ENUM(MECHANIC_ENRAGED), + CREATE_NAMED_ENUM(MECHANIC_WOUNDED) }; -UnitFlag const unitFlags[MAX_UNIT_FLAGS] = +EnumName<UnitFlags> const unitFlags[MAX_UNIT_FLAGS] = { - { UNIT_FLAG_SERVER_CONTROLLED , "UNIT_FLAG_SERVER_CONTROLLED" }, - { UNIT_FLAG_NON_ATTACKABLE , "UNIT_FLAG_NON_ATTACKABLE" }, - { UNIT_FLAG_DISABLE_MOVE , "UNIT_FLAG_DISABLE_MOVE" }, - { UNIT_FLAG_PVP_ATTACKABLE , "UNIT_FLAG_PVP_ATTACKABLE" }, - { UNIT_FLAG_RENAME , "UNIT_FLAG_RENAME" }, - { UNIT_FLAG_PREPARATION , "UNIT_FLAG_PREPARATION" }, - { UNIT_FLAG_UNK_6 , "UNIT_FLAG_UNK_6" }, - { UNIT_FLAG_NOT_ATTACKABLE_1 , "UNIT_FLAG_NOT_ATTACKABLE_1" }, - { UNIT_FLAG_IMMUNE_TO_PC , "UNIT_FLAG_IMMUNE_TO_PC" }, - { UNIT_FLAG_IMMUNE_TO_NPC , "UNIT_FLAG_IMMUNE_TO_NPC" }, - { UNIT_FLAG_LOOTING , "UNIT_FLAG_LOOTING" }, - { UNIT_FLAG_PET_IN_COMBAT , "UNIT_FLAG_PET_IN_COMBAT" }, - { UNIT_FLAG_PVP , "UNIT_FLAG_PVP" }, - { UNIT_FLAG_SILENCED , "UNIT_FLAG_SILENCED" }, - { UNIT_FLAG_UNK_14 , "UNIT_FLAG_UNK_14" }, - { UNIT_FLAG_UNK_15 , "UNIT_FLAG_UNK_15" }, - { UNIT_FLAG_UNK_16 , "UNIT_FLAG_UNK_16" }, - { UNIT_FLAG_PACIFIED , "UNIT_FLAG_PACIFIED" }, - { UNIT_FLAG_STUNNED , "UNIT_FLAG_STUNNED" }, - { UNIT_FLAG_IN_COMBAT , "UNIT_FLAG_IN_COMBAT" }, - { UNIT_FLAG_TAXI_FLIGHT , "UNIT_FLAG_TAXI_FLIGHT" }, - { UNIT_FLAG_DISARMED , "UNIT_FLAG_DISARMED" }, - { UNIT_FLAG_CONFUSED , "UNIT_FLAG_CONFUSED" }, - { UNIT_FLAG_FLEEING , "UNIT_FLAG_FLEEING" }, - { UNIT_FLAG_PLAYER_CONTROLLED , "UNIT_FLAG_PLAYER_CONTROLLED" }, - { UNIT_FLAG_NOT_SELECTABLE , "UNIT_FLAG_NOT_SELECTABLE" }, - { UNIT_FLAG_SKINNABLE , "UNIT_FLAG_SKINNABLE" }, - { UNIT_FLAG_MOUNT , "UNIT_FLAG_MOUNT" }, - { UNIT_FLAG_UNK_28 , "UNIT_FLAG_UNK_28" }, - { UNIT_FLAG_UNK_29 , "UNIT_FLAG_UNK_29" }, - { UNIT_FLAG_SHEATHE , "UNIT_FLAG_SHEATHE" }, - { UNIT_FLAG_UNK_31 , "UNIT_FLAG_UNK_31" } + CREATE_NAMED_ENUM(UNIT_FLAG_SERVER_CONTROLLED), + CREATE_NAMED_ENUM(UNIT_FLAG_NON_ATTACKABLE), + CREATE_NAMED_ENUM(UNIT_FLAG_DISABLE_MOVE), + CREATE_NAMED_ENUM(UNIT_FLAG_PVP_ATTACKABLE), + CREATE_NAMED_ENUM(UNIT_FLAG_RENAME), + CREATE_NAMED_ENUM(UNIT_FLAG_PREPARATION), + CREATE_NAMED_ENUM(UNIT_FLAG_UNK_6), + CREATE_NAMED_ENUM(UNIT_FLAG_NOT_ATTACKABLE_1), + CREATE_NAMED_ENUM(UNIT_FLAG_IMMUNE_TO_PC), + CREATE_NAMED_ENUM(UNIT_FLAG_IMMUNE_TO_NPC), + CREATE_NAMED_ENUM(UNIT_FLAG_LOOTING), + CREATE_NAMED_ENUM(UNIT_FLAG_PET_IN_COMBAT), + CREATE_NAMED_ENUM(UNIT_FLAG_PVP), + CREATE_NAMED_ENUM(UNIT_FLAG_SILENCED), + CREATE_NAMED_ENUM(UNIT_FLAG_UNK_14), + CREATE_NAMED_ENUM(UNIT_FLAG_UNK_15), + CREATE_NAMED_ENUM(UNIT_FLAG_UNK_16), + CREATE_NAMED_ENUM(UNIT_FLAG_PACIFIED), + CREATE_NAMED_ENUM(UNIT_FLAG_STUNNED), + CREATE_NAMED_ENUM(UNIT_FLAG_IN_COMBAT), + CREATE_NAMED_ENUM(UNIT_FLAG_TAXI_FLIGHT), + CREATE_NAMED_ENUM(UNIT_FLAG_DISARMED), + CREATE_NAMED_ENUM(UNIT_FLAG_CONFUSED), + CREATE_NAMED_ENUM(UNIT_FLAG_FLEEING), + CREATE_NAMED_ENUM(UNIT_FLAG_PLAYER_CONTROLLED), + CREATE_NAMED_ENUM(UNIT_FLAG_NOT_SELECTABLE), + CREATE_NAMED_ENUM(UNIT_FLAG_SKINNABLE), + CREATE_NAMED_ENUM(UNIT_FLAG_MOUNT), + CREATE_NAMED_ENUM(UNIT_FLAG_UNK_28), + CREATE_NAMED_ENUM(UNIT_FLAG_UNK_29), + CREATE_NAMED_ENUM(UNIT_FLAG_SHEATHE), + CREATE_NAMED_ENUM(UNIT_FLAG_UNK_31) }; class npc_commandscript : public CommandScript @@ -164,69 +154,65 @@ public: { static ChatCommand npcAddCommandTable[] = { - { "formation", SEC_MODERATOR, false, &HandleNpcAddFormationCommand, "", NULL }, - { "item", SEC_GAMEMASTER, false, &HandleNpcAddVendorItemCommand, "", NULL }, - { "move", SEC_GAMEMASTER, false, &HandleNpcAddMoveCommand, "", NULL }, - { "temp", SEC_GAMEMASTER, false, &HandleNpcAddTempSpawnCommand, "", NULL }, - //{@todo fix or remove this command - { "weapon", SEC_ADMINISTRATOR, false, &HandleNpcAddWeaponCommand, "", NULL }, - //} - { "", SEC_GAMEMASTER, false, &HandleNpcAddCommand, "", NULL }, - { NULL, SEC_PLAYER, false, NULL, "", NULL } + { "formation", RBAC_PERM_COMMAND_NPC_ADD_FORMATION, false, &HandleNpcAddFormationCommand, "", NULL }, + { "item", RBAC_PERM_COMMAND_NPC_ADD_ITEM, false, &HandleNpcAddVendorItemCommand, "", NULL }, + { "move", RBAC_PERM_COMMAND_NPC_ADD_MOVE, false, &HandleNpcAddMoveCommand, "", NULL }, + { "temp", RBAC_PERM_COMMAND_NPC_ADD_TEMP, false, &HandleNpcAddTempSpawnCommand, "", NULL }, + //{ "weapon", RBAC_PERM_COMMAND_NPC_ADD_WEAPON, false, &HandleNpcAddWeaponCommand, "", NULL }, + { "", RBAC_PERM_COMMAND_NPC_ADD, false, &HandleNpcAddCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand npcDeleteCommandTable[] = { - { "item", SEC_GAMEMASTER, false, &HandleNpcDeleteVendorItemCommand, "", NULL }, - { "", SEC_GAMEMASTER, false, &HandleNpcDeleteCommand, "", NULL }, - { NULL, SEC_PLAYER, false, NULL, "", NULL } + { "item", RBAC_PERM_COMMAND_NPC_DELETE_ITEM, false, &HandleNpcDeleteVendorItemCommand, "", NULL }, + { "", RBAC_PERM_COMMAND_NPC_DELETE, false, &HandleNpcDeleteCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand npcFollowCommandTable[] = { - { "stop", SEC_GAMEMASTER, false, &HandleNpcUnFollowCommand, "", NULL }, - { "", SEC_GAMEMASTER, false, &HandleNpcFollowCommand, "", NULL }, - { NULL, SEC_PLAYER, false, NULL, "", NULL } + { "stop", RBAC_PERM_COMMAND_NPC_FOLLOW_STOP, false, &HandleNpcUnFollowCommand, "", NULL }, + { "", RBAC_PERM_COMMAND_NPC_FOLLOW, false, &HandleNpcFollowCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand npcSetCommandTable[] = { - { "allowmove", SEC_ADMINISTRATOR, false, &HandleNpcSetAllowMovementCommand, "", NULL }, - { "entry", SEC_ADMINISTRATOR, false, &HandleNpcSetEntryCommand, "", NULL }, - { "factionid", SEC_GAMEMASTER, false, &HandleNpcSetFactionIdCommand, "", NULL }, - { "flag", SEC_GAMEMASTER, false, &HandleNpcSetFlagCommand, "", NULL }, - { "level", SEC_GAMEMASTER, false, &HandleNpcSetLevelCommand, "", NULL }, - { "link", SEC_GAMEMASTER, false, &HandleNpcSetLinkCommand, "", NULL }, - { "model", SEC_GAMEMASTER, false, &HandleNpcSetModelCommand, "", NULL }, - { "movetype", SEC_GAMEMASTER, false, &HandleNpcSetMoveTypeCommand, "", NULL }, - { "phase", SEC_GAMEMASTER, false, &HandleNpcSetPhaseCommand, "", NULL }, - { "spawndist", SEC_GAMEMASTER, false, &HandleNpcSetSpawnDistCommand, "", NULL }, - { "spawntime", SEC_GAMEMASTER, false, &HandleNpcSetSpawnTimeCommand, "", NULL }, - { "data", SEC_ADMINISTRATOR, false, &HandleNpcSetDataCommand, "", NULL }, - //{ @todo fix or remove these commands - { "name", SEC_GAMEMASTER, false, &HandleNpcSetNameCommand, "", NULL }, - { "subname", SEC_GAMEMASTER, false, &HandleNpcSetSubNameCommand, "", NULL }, - //} - { NULL, SEC_PLAYER, false, NULL, "", NULL } + { "allowmove", RBAC_PERM_COMMAND_NPC_SET_ALLOWMOVE, false, &HandleNpcSetAllowMovementCommand, "", NULL }, + { "entry", RBAC_PERM_COMMAND_NPC_SET_ENTRY, false, &HandleNpcSetEntryCommand, "", NULL }, + { "factionid", RBAC_PERM_COMMAND_NPC_SET_FACTIONID, false, &HandleNpcSetFactionIdCommand, "", NULL }, + { "flag", RBAC_PERM_COMMAND_NPC_SET_FLAG, false, &HandleNpcSetFlagCommand, "", NULL }, + { "level", RBAC_PERM_COMMAND_NPC_SET_LEVEL, false, &HandleNpcSetLevelCommand, "", NULL }, + { "link", RBAC_PERM_COMMAND_NPC_SET_LINK, false, &HandleNpcSetLinkCommand, "", NULL }, + { "model", RBAC_PERM_COMMAND_NPC_SET_MODEL, false, &HandleNpcSetModelCommand, "", NULL }, + { "movetype", RBAC_PERM_COMMAND_NPC_SET_MOVETYPE, false, &HandleNpcSetMoveTypeCommand, "", NULL }, + { "phase", RBAC_PERM_COMMAND_NPC_SET_PHASE, false, &HandleNpcSetPhaseCommand, "", NULL }, + { "spawndist", RBAC_PERM_COMMAND_NPC_SET_SPAWNDIST, false, &HandleNpcSetSpawnDistCommand, "", NULL }, + { "spawntime", RBAC_PERM_COMMAND_NPC_SET_SPAWNTIME, false, &HandleNpcSetSpawnTimeCommand, "", NULL }, + { "data", RBAC_PERM_COMMAND_NPC_SET_DATA, false, &HandleNpcSetDataCommand, "", NULL }, + //{ "name", RBAC_PERM_COMMAND_NPC_SET_NAME, false, &HandleNpcSetNameCommand, "", NULL }, + //{ "subname", RBAC_PERM_COMMAND_NPC_SET_SUBNAME, false, &HandleNpcSetSubNameCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand npcCommandTable[] = { - { "info", SEC_ADMINISTRATOR, false, &HandleNpcInfoCommand, "", NULL }, - { "near", SEC_GAMEMASTER, false, &HandleNpcNearCommand, "", NULL }, - { "move", SEC_GAMEMASTER, false, &HandleNpcMoveCommand, "", NULL }, - { "playemote", SEC_ADMINISTRATOR, false, &HandleNpcPlayEmoteCommand, "", NULL }, - { "say", SEC_MODERATOR, false, &HandleNpcSayCommand, "", NULL }, - { "textemote", SEC_MODERATOR, false, &HandleNpcTextEmoteCommand, "", NULL }, - { "whisper", SEC_MODERATOR, false, &HandleNpcWhisperCommand, "", NULL }, - { "yell", SEC_MODERATOR, false, &HandleNpcYellCommand, "", NULL }, - { "tame", SEC_GAMEMASTER, false, &HandleNpcTameCommand, "", NULL }, - { "add", SEC_GAMEMASTER, false, NULL, "", npcAddCommandTable }, - { "delete", SEC_GAMEMASTER, false, NULL, "", npcDeleteCommandTable }, - { "follow", SEC_GAMEMASTER, false, NULL, "", npcFollowCommandTable }, - { "set", SEC_GAMEMASTER, false, NULL, "", npcSetCommandTable }, - { NULL, SEC_PLAYER, false, NULL, "", NULL } + { "info", RBAC_PERM_COMMAND_NPC_INFO, false, &HandleNpcInfoCommand, "", NULL }, + { "near", RBAC_PERM_COMMAND_NPC_NEAR, false, &HandleNpcNearCommand, "", NULL }, + { "move", RBAC_PERM_COMMAND_NPC_MOVE, false, &HandleNpcMoveCommand, "", NULL }, + { "playemote", RBAC_PERM_COMMAND_NPC_PLAYEMOTE, false, &HandleNpcPlayEmoteCommand, "", NULL }, + { "say", RBAC_PERM_COMMAND_NPC_SAY, false, &HandleNpcSayCommand, "", NULL }, + { "textemote", RBAC_PERM_COMMAND_NPC_TEXTEMOTE, false, &HandleNpcTextEmoteCommand, "", NULL }, + { "whisper", RBAC_PERM_COMMAND_NPC_WHISPER, false, &HandleNpcWhisperCommand, "", NULL }, + { "yell", RBAC_PERM_COMMAND_NPC_YELL, false, &HandleNpcYellCommand, "", NULL }, + { "tame", RBAC_PERM_COMMAND_NPC_TAME, false, &HandleNpcTameCommand, "", NULL }, + { "add", RBAC_PERM_COMMAND_NPC_ADD, false, NULL, "", npcAddCommandTable }, + { "delete", RBAC_PERM_COMMAND_NPC_DELETE, false, NULL, "", npcDeleteCommandTable }, + { "follow", RBAC_PERM_COMMAND_NPC_FOLLOW, false, NULL, "", npcFollowCommandTable }, + { "set", RBAC_PERM_COMMAND_NPC_SET, false, NULL, "", npcSetCommandTable }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand commandTable[] = { - { "npc", SEC_MODERATOR, false, NULL, "", npcCommandTable }, - { NULL, SEC_PLAYER, false, NULL, "", NULL } + { "npc", RBAC_PERM_COMMAND_NPC, false, NULL, "", npcCommandTable }, + { NULL, 0, false, NULL, "", NULL } }; return commandTable; } @@ -243,10 +229,15 @@ public: char* team = strtok(NULL, " "); int32 teamval = 0; - if (team) { teamval = atoi(team); } - if (teamval < 0) { teamval = 0; } + if (team) + teamval = atoi(team); + + if (teamval < 0) + teamval = 0; uint32 id = atoi(charID); + if (!sObjectMgr->GetCreatureTemplate(id)) + return false; Player* chr = handler->GetSession()->GetPlayer(); float x = chr->GetPositionX(); @@ -742,8 +733,8 @@ public: handler->PSendSysMessage(LANG_NPCINFO_UNIT_FIELD_FLAGS, target->GetUInt32Value(UNIT_FIELD_FLAGS)); for (uint8 i = 0; i < MAX_UNIT_FLAGS; ++i) - if (target->GetUInt32Value(UNIT_FIELD_FLAGS) & unitFlags[i].flag) - handler->PSendSysMessage(unitFlags[i].text, unitFlags[i].flag); + if (target->GetUInt32Value(UNIT_FIELD_FLAGS) & unitFlags[i].Value) + handler->PSendSysMessage("%s (0x%X)", unitFlags[i].Name, unitFlags[i].Value); handler->PSendSysMessage(LANG_NPCINFO_FLAGS, target->GetUInt32Value(UNIT_FIELD_FLAGS_2), target->GetUInt32Value(UNIT_DYNAMIC_FLAGS), target->getFaction()); handler->PSendSysMessage(LANG_COMMAND_RAWPAWNTIMES, defRespawnDelayStr.c_str(), curRespawnDelayStr.c_str()); @@ -755,13 +746,13 @@ public: handler->PSendSysMessage(LANG_NPCINFO_AIINFO, target->GetAIName().c_str(), target->GetScriptName().c_str()); for (uint8 i = 0; i < NPCFLAG_COUNT; i++) - if (npcflags & npcFlagTexts[i].flag) - handler->PSendSysMessage(npcFlagTexts[i].text, npcFlagTexts[i].flag); + if (npcflags & npcFlagTexts[i].Value) + handler->PSendSysMessage(npcFlagTexts[i].Name); handler->PSendSysMessage(LANG_NPCINFO_MECHANIC_IMMUNE, mechanicImmuneMask); for (uint8 i = 0; i < MAX_MECHANIC; ++i) - if ((mechanicImmuneMask << 1) & mechanicImmunes[i].flag) - handler->PSendSysMessage(mechanicImmunes[i].text, mechanicImmunes[i].flag); + if ((mechanicImmuneMask << 1) & mechanicImmunes[i].Value) + handler->PSendSysMessage("%s (0x%X)", mechanicImmunes[i].Name, mechanicImmunes[i].Value); return true; } @@ -1366,6 +1357,9 @@ public: if (!id) return false; + if (!sObjectMgr->GetCreatureTemplate(id)) + return false; + chr->SummonCreature(id, *chr, TEMPSUMMON_CORPSE_DESPAWN, 120); return true; diff --git a/src/server/scripts/Commands/cs_pet.cpp b/src/server/scripts/Commands/cs_pet.cpp new file mode 100644 index 00000000000..315cf06e995 --- /dev/null +++ b/src/server/scripts/Commands/cs_pet.cpp @@ -0,0 +1,190 @@ +/* + * Copyright (C) 2008-2013 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 "Chat.h" +#include "Language.h" +#include "Pet.h" +#include "Player.h" +#include "ObjectMgr.h" +#include "ScriptMgr.h" + +class pet_commandscript : public CommandScript +{ +public: + pet_commandscript() : CommandScript("pet_commandscript") { } + + ChatCommand* GetCommands() const OVERRIDE + { + static ChatCommand petCommandTable[] = + { + { "create", RBAC_PERM_COMMAND_PET_CREATE, false, &HandlePetCreateCommand, "", NULL }, + { "learn", RBAC_PERM_COMMAND_PET_LEARN, false, &HandlePetLearnCommand, "", NULL }, + { "unlearn", RBAC_PERM_COMMAND_PET_UNLEARN, false, &HandlePetUnlearnCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } + }; + + static ChatCommand commandTable[] = + { + { "pet", RBAC_PERM_COMMAND_PET, false, NULL, "", petCommandTable }, + { NULL, 0, false, NULL, "", NULL } + }; + return commandTable; + } + static bool HandlePetCreateCommand(ChatHandler* handler, char const* /*args*/) + { + Player* player = handler->GetSession()->GetPlayer(); + Creature* creatureTarget = handler->getSelectedCreature(); + + if (!creatureTarget || creatureTarget->IsPet() || creatureTarget->GetTypeId() == TYPEID_PLAYER) + { + handler->PSendSysMessage(LANG_SELECT_CREATURE); + handler->SetSentErrorMessage(true); + return false; + } + + CreatureTemplate const* creatrueTemplate = creatureTarget->GetCreatureTemplate(); + // Creatures with family 0 crashes the server + if (!creatrueTemplate->family) + { + handler->PSendSysMessage("This creature cannot be tamed. (family id: 0)."); + handler->SetSentErrorMessage(true); + return false; + } + + if (player->GetPetGUID()) + { + handler->PSendSysMessage("You already have a pet"); + handler->SetSentErrorMessage(true); + return false; + } + + // Everything looks OK, create new pet + Pet* pet = new Pet(player, HUNTER_PET); + if (!pet->CreateBaseAtCreature(creatureTarget)) + { + delete pet; + handler->PSendSysMessage("Error 1"); + return false; + } + + creatureTarget->setDeathState(JUST_DIED); + creatureTarget->RemoveCorpse(); + creatureTarget->SetHealth(0); // just for nice GM-mode view + + pet->SetUInt64Value(UNIT_FIELD_CREATEDBY, player->GetGUID()); + pet->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, player->getFaction()); + + if (!pet->InitStatsForLevel(creatureTarget->getLevel())) + { + TC_LOG_ERROR(LOG_FILTER_GENERAL, "InitStatsForLevel() in EffectTameCreature failed! Pet deleted."); + handler->PSendSysMessage("Error 2"); + delete pet; + return false; + } + + // prepare visual effect for levelup + pet->SetUInt32Value(UNIT_FIELD_LEVEL, creatureTarget->getLevel()-1); + + pet->GetCharmInfo()->SetPetNumber(sObjectMgr->GeneratePetNumber(), true); + // this enables pet details window (Shift+P) + pet->InitPetCreateSpells(); + pet->SetFullHealth(); + + pet->GetMap()->AddToMap(pet->ToCreature()); + + // visual effect for levelup + pet->SetUInt32Value(UNIT_FIELD_LEVEL, creatureTarget->getLevel()); + + player->SetMinion(pet, true); + pet->SavePetToDB(PET_SAVE_AS_CURRENT); + player->PetSpellInitialize(); + + return true; + } + + static bool HandlePetLearnCommand(ChatHandler* handler, char const* args) + { + if (!*args) + return false; + + Player* player = handler->GetSession()->GetPlayer(); + Pet* pet = player->GetPet(); + + if (!pet) + { + handler->PSendSysMessage("You have no pet"); + handler->SetSentErrorMessage(true); + return false; + } + + uint32 spellId = handler->extractSpellIdFromLink((char*)args); + + if (!spellId || !sSpellMgr->GetSpellInfo(spellId)) + return false; + + // Check if pet already has it + if (pet->HasSpell(spellId)) + { + handler->PSendSysMessage("Pet already has spell: %u", spellId); + handler->SetSentErrorMessage(true); + return false; + } + + // Check if spell is valid + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); + if (!spellInfo || !SpellMgr::IsSpellValid(spellInfo)) + { + handler->PSendSysMessage(LANG_COMMAND_SPELL_BROKEN, spellId); + handler->SetSentErrorMessage(true); + return false; + } + + pet->learnSpell(spellId); + + handler->PSendSysMessage("Pet has learned spell %u", spellId); + return true; + } + + static bool HandlePetUnlearnCommand(ChatHandler* handler, char const* args) + { + if (!*args) + return false; + + Player* player = handler->GetSession()->GetPlayer(); + Pet* pet = player->GetPet(); + if (!pet) + { + handler->PSendSysMessage("You have no pet"); + handler->SetSentErrorMessage(true); + return false; + } + + uint32 spellId = handler->extractSpellIdFromLink((char*)args); + + if (pet->HasSpell(spellId)) + pet->removeSpell(spellId, false); + else + handler->PSendSysMessage("Pet doesn't have that spell"); + + return true; + } +}; + +void AddSC_pet_commandscript() +{ + new pet_commandscript(); +} diff --git a/src/server/scripts/Commands/cs_quest.cpp b/src/server/scripts/Commands/cs_quest.cpp index 6b7d10ff7b1..3ad1fea74a2 100644 --- a/src/server/scripts/Commands/cs_quest.cpp +++ b/src/server/scripts/Commands/cs_quest.cpp @@ -37,16 +37,16 @@ public: { static ChatCommand questCommandTable[] = { - { "add", SEC_ADMINISTRATOR, false, &HandleQuestAdd, "", NULL }, - { "complete", SEC_ADMINISTRATOR, false, &HandleQuestComplete, "", NULL }, - { "remove", SEC_ADMINISTRATOR, false, &HandleQuestRemove, "", NULL }, - { "reward", SEC_ADMINISTRATOR, false, &HandleQuestReward, "", NULL }, - { NULL, SEC_PLAYER, false, NULL, "", NULL } + { "add", RBAC_PERM_COMMAND_QUEST_ADD, false, &HandleQuestAdd, "", NULL }, + { "complete", RBAC_PERM_COMMAND_QUEST_COMPLETE, false, &HandleQuestComplete, "", NULL }, + { "remove", RBAC_PERM_COMMAND_QUEST_REMOVE, false, &HandleQuestRemove, "", NULL }, + { "reward", RBAC_PERM_COMMAND_QUEST_REWARD, false, &HandleQuestReward, "", NULL }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand commandTable[] = { - { "quest", SEC_ADMINISTRATOR, false, NULL, "", questCommandTable }, - { NULL, SEC_PLAYER, false, NULL, "", NULL } + { "quest", RBAC_PERM_COMMAND_QUEST, false, NULL, "", questCommandTable }, + { NULL, 0, false, NULL, "", NULL } }; return commandTable; } @@ -205,24 +205,17 @@ public: for (uint8 i = 0; i < QUEST_OBJECTIVES_COUNT; ++i) { int32 creature = quest->RequiredNpcOrGo[i]; - uint32 creaturecount = quest->RequiredNpcOrGoCount[i]; + uint32 creatureCount = quest->RequiredNpcOrGoCount[i]; - if (uint32 spell_id = quest->RequiredSpellCast[i]) + if (creature > 0) { - for (uint16 z = 0; z < creaturecount; ++z) - player->CastedCreatureOrGO(creature, 0, spell_id); - } - else if (creature > 0) - { - if (CreatureTemplate const* cInfo = sObjectMgr->GetCreatureTemplate(creature)) - for (uint16 z = 0; z < creaturecount; ++z) - player->KilledMonster(cInfo, 0); + if (CreatureTemplate const* creatureInfo = sObjectMgr->GetCreatureTemplate(creature)) + for (uint16 z = 0; z < creatureCount; ++z) + player->KilledMonster(creatureInfo, 0); } else if (creature < 0) - { - for (uint16 z = 0; z < creaturecount; ++z) - player->CastedCreatureOrGO(creature, 0, 0); - } + for (uint16 z = 0; z < creatureCount; ++z) + player->KillCreditGO(creature, 0); } // If the quest requires reputation to complete diff --git a/src/server/scripts/Commands/cs_rbac.cpp b/src/server/scripts/Commands/cs_rbac.cpp index 667815ce16c..ba899fee077 100644 --- a/src/server/scripts/Commands/cs_rbac.cpp +++ b/src/server/scripts/Commands/cs_rbac.cpp @@ -53,58 +53,58 @@ public: {
static ChatCommand rbacGroupsCommandTable[] =
{
- { "add", SEC_ADMINISTRATOR, true, &HandleRBACGroupAddCommand, "", NULL },
- { "remove", SEC_ADMINISTRATOR, true, &HandleRBACGroupRemoveCommand, "", NULL },
- { "", SEC_ADMINISTRATOR, true, &HandleRBACGroupListCommand, "", NULL },
- { NULL, SEC_ADMINISTRATOR, false, NULL, "", NULL }
+ { "add", RBAC_PERM_COMMAND_RBAC_ACC_GROUP_ADD, true, &HandleRBACGroupAddCommand, "", NULL },
+ { "remove", RBAC_PERM_COMMAND_RBAC_ACC_GROUP_DEL, true, &HandleRBACGroupRemoveCommand, "", NULL },
+ { "", RBAC_PERM_COMMAND_RBAC_ACC_GROUP, true, &HandleRBACGroupListCommand, "", NULL },
+ { NULL, 0, false, NULL, "", NULL }
};
static ChatCommand rbacRolesCommandTable[] =
{
- { "grant", SEC_ADMINISTRATOR, true, &HandleRBACRoleGrantCommand, "", NULL },
- { "deny", SEC_ADMINISTRATOR, true, &HandleRBACRoleDenyCommand, "", NULL },
- { "revoke", SEC_ADMINISTRATOR, true, &HandleRBACRoleRevokeCommand, "", NULL },
- { "", SEC_ADMINISTRATOR, true, &HandleRBACRoleListCommand, "", NULL },
- { NULL, SEC_ADMINISTRATOR, false, NULL, "", NULL }
+ { "grant", RBAC_PERM_COMMAND_RBAC_ACC_ROLE_GRANT, true, &HandleRBACRoleGrantCommand, "", NULL },
+ { "deny", RBAC_PERM_COMMAND_RBAC_ACC_ROLE_DENY, true, &HandleRBACRoleDenyCommand, "", NULL },
+ { "revoke", RBAC_PERM_COMMAND_RBAC_ACC_ROLE_REVOKE, true, &HandleRBACRoleRevokeCommand, "", NULL },
+ { "", RBAC_PERM_COMMAND_RBAC_ACC_ROLE, true, &HandleRBACRoleListCommand, "", NULL },
+ { NULL, 0, false, NULL, "", NULL }
};
static ChatCommand rbacPermsCommandTable[] =
{
- { "grant", SEC_ADMINISTRATOR, true, &HandleRBACPermGrantCommand, "", NULL },
- { "deny", SEC_ADMINISTRATOR, true, &HandleRBACPermDenyCommand, "", NULL },
- { "revoke", SEC_ADMINISTRATOR, true, &HandleRBACPermRevokeCommand, "", NULL },
- { "", SEC_ADMINISTRATOR, true, &HandleRBACPermListCommand, "", NULL },
- { NULL, SEC_ADMINISTRATOR, false, NULL, "", NULL }
+ { "grant", RBAC_PERM_COMMAND_RBAC_ACC_PERM_GRANT, true, &HandleRBACPermGrantCommand, "", NULL },
+ { "deny", RBAC_PERM_COMMAND_RBAC_ACC_PERM_DENY, true, &HandleRBACPermDenyCommand, "", NULL },
+ { "revoke", RBAC_PERM_COMMAND_RBAC_ACC_PERM_REVOKE, true, &HandleRBACPermRevokeCommand, "", NULL },
+ { "", RBAC_PERM_COMMAND_RBAC_ACC_PERM, true, &HandleRBACPermListCommand, "", NULL },
+ { NULL, 0, false, NULL, "", NULL }
};
static ChatCommand rbacListCommandTable[] =
{
- { "groups", SEC_ADMINISTRATOR, true, &HandleRBACListGroupsCommand, "", NULL },
- { "roles", SEC_ADMINISTRATOR, true, &HandleRBACListRolesCommand, "", NULL },
- { "permissions", SEC_ADMINISTRATOR, true, &HandleRBACListPermissionsCommand, "", NULL },
- { NULL, SEC_ADMINISTRATOR, false, NULL, "", NULL }
+ { "groups", RBAC_PERM_COMMAND_RBAC_LIST_GROUPS, true, &HandleRBACListGroupsCommand, "", NULL },
+ { "roles", RBAC_PERM_COMMAND_RBAC_LIST_ROLES, true, &HandleRBACListRolesCommand, "", NULL },
+ { "permissions", RBAC_PERM_COMMAND_RBAC_LIST_PERMS, true, &HandleRBACListPermissionsCommand, "", NULL },
+ { NULL, 0, false, NULL, "", NULL }
};
static ChatCommand rbacAccountCommandTable[] =
{
- { "group", SEC_ADMINISTRATOR, true, NULL, "", rbacGroupsCommandTable },
- { "role", SEC_ADMINISTRATOR, true, NULL, "", rbacRolesCommandTable },
- { "permission", SEC_ADMINISTRATOR, true, NULL, "", rbacPermsCommandTable },
- { "", SEC_ADMINISTRATOR, true, &HandleRBACAccountPermissionCommand, "", NULL },
- { NULL, SEC_ADMINISTRATOR, false, NULL, "", NULL }
+ { "group", RBAC_PERM_COMMAND_RBAC_ACC_GROUP, true, NULL, "", rbacGroupsCommandTable },
+ { "role", RBAC_PERM_COMMAND_RBAC_ACC_ROLE, true, NULL, "", rbacRolesCommandTable },
+ { "permission", RBAC_PERM_COMMAND_RBAC_ACC_PERM, true, NULL, "", rbacPermsCommandTable },
+ { "", RBAC_PERM_COMMAND_RBAC_ACC, true, &HandleRBACAccountPermissionCommand, "", NULL },
+ { NULL, 0, false, NULL, "", NULL }
};
static ChatCommand rbacCommandTable[] =
{
- { "account", SEC_ADMINISTRATOR, true, NULL, "", rbacAccountCommandTable },
- { "list", SEC_ADMINISTRATOR, true, NULL, "", rbacListCommandTable },
- { NULL, SEC_ADMINISTRATOR, false, NULL, "", NULL }
+ { "account", RBAC_PERM_COMMAND_RBAC_ACC, true, NULL, "", rbacAccountCommandTable },
+ { "list", RBAC_PERM_COMMAND_RBAC_LIST, true, NULL, "", rbacListCommandTable },
+ { NULL, 0, false, NULL, "", NULL }
};
static ChatCommand commandTable[] =
{
- { "rbac", SEC_ADMINISTRATOR, true, NULL, "", rbacCommandTable },
- { NULL, SEC_ADMINISTRATOR, false, NULL, "", NULL }
+ { "rbac", RBAC_PERM_COMMAND_RBAC, true, NULL, "", rbacCommandTable },
+ { NULL, 0, false, NULL, "", NULL }
};
return commandTable;
diff --git a/src/server/scripts/Commands/cs_reload.cpp b/src/server/scripts/Commands/cs_reload.cpp index 5ba9e240d50..694ce097455 100644 --- a/src/server/scripts/Commands/cs_reload.cpp +++ b/src/server/scripts/Commands/cs_reload.cpp @@ -50,116 +50,115 @@ public: { static ChatCommand reloadAllCommandTable[] = { - { "achievement", SEC_ADMINISTRATOR, true, &HandleReloadAllAchievementCommand, "", NULL }, - { "area", SEC_ADMINISTRATOR, true, &HandleReloadAllAreaCommand, "", NULL }, - { "gossips", SEC_ADMINISTRATOR, true, &HandleReloadAllGossipsCommand, "", NULL }, - { "item", SEC_ADMINISTRATOR, true, &HandleReloadAllItemCommand, "", NULL }, - { "locales", SEC_ADMINISTRATOR, true, &HandleReloadAllLocalesCommand, "", NULL }, - { "loot", SEC_ADMINISTRATOR, true, &HandleReloadAllLootCommand, "", NULL }, - { "npc", SEC_ADMINISTRATOR, true, &HandleReloadAllNpcCommand, "", NULL }, - { "quest", SEC_ADMINISTRATOR, true, &HandleReloadAllQuestCommand, "", NULL }, - { "scripts", SEC_ADMINISTRATOR, true, &HandleReloadAllScriptsCommand, "", NULL }, - { "spell", SEC_ADMINISTRATOR, true, &HandleReloadAllSpellCommand, "", NULL }, - { "", SEC_ADMINISTRATOR, true, &HandleReloadAllCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "achievement", RBAC_PERM_COMMANDS_RELOAD_ALL_ACHIEVEMENT, true, &HandleReloadAllAchievementCommand, "", NULL }, + { "area", RBAC_PERM_COMMANDS_RELOAD_ALL_AREA, true, &HandleReloadAllAreaCommand, "", NULL }, + { "gossips", RBAC_PERM_COMMANDS_RELOAD_ALL_GOSSIP, true, &HandleReloadAllGossipsCommand, "", NULL }, + { "item", RBAC_PERM_COMMANDS_RELOAD_ALL_ITEM, true, &HandleReloadAllItemCommand, "", NULL }, + { "locales", RBAC_PERM_COMMANDS_RELOAD_ALL_LOCALES, true, &HandleReloadAllLocalesCommand, "", NULL }, + { "loot", RBAC_PERM_COMMANDS_RELOAD_ALL_LOOT, true, &HandleReloadAllLootCommand, "", NULL }, + { "npc", RBAC_PERM_COMMANDS_RELOAD_ALL_NPC, true, &HandleReloadAllNpcCommand, "", NULL }, + { "quest", RBAC_PERM_COMMANDS_RELOAD_ALL_QUEST, true, &HandleReloadAllQuestCommand, "", NULL }, + { "scripts", RBAC_PERM_COMMANDS_RELOAD_ALL_SCRIPTS, true, &HandleReloadAllScriptsCommand, "", NULL }, + { "spell", RBAC_PERM_COMMANDS_RELOAD_ALL_SPELL, true, &HandleReloadAllSpellCommand, "", NULL }, + { "", RBAC_PERM_COMMANDS_RELOAD_ALL, true, &HandleReloadAllCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand reloadCommandTable[] = { - { "auctions", SEC_ADMINISTRATOR, true, &HandleReloadAuctionsCommand, "", NULL }, - { "access_requirement", SEC_ADMINISTRATOR, true, &HandleReloadAccessRequirementCommand, "", NULL }, - { "achievement_criteria_data", SEC_ADMINISTRATOR, true, &HandleReloadAchievementCriteriaDataCommand, "", NULL }, - { "achievement_reward", SEC_ADMINISTRATOR, true, &HandleReloadAchievementRewardCommand, "", NULL }, - { "all", SEC_ADMINISTRATOR, true, NULL, "", reloadAllCommandTable }, - { "areatrigger_involvedrelation", SEC_ADMINISTRATOR, true, &HandleReloadQuestAreaTriggersCommand, "", NULL }, - { "areatrigger_tavern", SEC_ADMINISTRATOR, true, &HandleReloadAreaTriggerTavernCommand, "", NULL }, - { "areatrigger_teleport", SEC_ADMINISTRATOR, true, &HandleReloadAreaTriggerTeleportCommand, "", NULL }, - { "autobroadcast", SEC_ADMINISTRATOR, true, &HandleReloadAutobroadcastCommand, "", NULL }, - { "command", SEC_ADMINISTRATOR, true, &HandleReloadCommandCommand, "", NULL }, - { "conditions", SEC_ADMINISTRATOR, true, &HandleReloadConditions, "", NULL }, - { "config", SEC_ADMINISTRATOR, true, &HandleReloadConfigCommand, "", NULL }, - { "creature_text", SEC_ADMINISTRATOR, true, &HandleReloadCreatureText, "", NULL }, - { "creature_questender", SEC_ADMINISTRATOR, true, &HandleReloadCreatureQuestEnderCommand, "", NULL }, - { "creature_linked_respawn", SEC_GAMEMASTER, true, &HandleReloadLinkedRespawnCommand, "", NULL }, - { "creature_loot_template", SEC_ADMINISTRATOR, true, &HandleReloadLootTemplatesCreatureCommand, "", NULL }, - { "creature_onkill_reputation", SEC_ADMINISTRATOR, true, &HandleReloadOnKillReputationCommand, "", NULL }, - { "creature_queststarter", SEC_ADMINISTRATOR, true, &HandleReloadCreatureQuestStarterCommand, "", NULL }, - { "creature_summon_groups", SEC_ADMINISTRATOR, true, &HandleReloadCreatureSummonGroupsCommand, "", NULL }, - { "creature_template", SEC_ADMINISTRATOR, true, &HandleReloadCreatureTemplateCommand, "", NULL }, - //{ "db_script_string", SEC_ADMINISTRATOR, true, &HandleReloadDbScriptStringCommand, "", NULL }, - { "disables", SEC_ADMINISTRATOR, true, &HandleReloadDisablesCommand, "", NULL }, - { "disenchant_loot_template", SEC_ADMINISTRATOR, true, &HandleReloadLootTemplatesDisenchantCommand, "", NULL }, - { "event_scripts", SEC_ADMINISTRATOR, true, &HandleReloadEventScriptsCommand, "", NULL }, - { "fishing_loot_template", SEC_ADMINISTRATOR, true, &HandleReloadLootTemplatesFishingCommand, "", NULL }, - { "game_graveyard_zone", SEC_ADMINISTRATOR, true, &HandleReloadGameGraveyardZoneCommand, "", NULL }, - { "game_tele", SEC_ADMINISTRATOR, true, &HandleReloadGameTeleCommand, "", NULL }, - { "gameobject_questender", SEC_ADMINISTRATOR, true, &HandleReloadGOQuestEnderCommand, "", NULL }, - { "gameobject_loot_template", SEC_ADMINISTRATOR, true, &HandleReloadLootTemplatesGameobjectCommand, "", NULL }, - { "gameobject_queststarter", SEC_ADMINISTRATOR, true, &HandleReloadGOQuestStarterCommand, "", NULL }, - { "gm_tickets", SEC_ADMINISTRATOR, true, &HandleReloadGMTicketsCommand, "", NULL }, - { "gossip_menu", SEC_ADMINISTRATOR, true, &HandleReloadGossipMenuCommand, "", NULL }, - { "gossip_menu_option", SEC_ADMINISTRATOR, true, &HandleReloadGossipMenuOptionCommand, "", NULL }, - { "item_enchantment_template", SEC_ADMINISTRATOR, true, &HandleReloadItemEnchantementsCommand, "", NULL }, - { "item_loot_template", SEC_ADMINISTRATOR, true, &HandleReloadLootTemplatesItemCommand, "", NULL }, - { "lfg_dungeon_rewards", SEC_ADMINISTRATOR, true, &HandleReloadLfgRewardsCommand, "", NULL }, - { "locales_achievement_reward", SEC_ADMINISTRATOR, true, &HandleReloadLocalesAchievementRewardCommand, "", NULL }, - { "locales_creature", SEC_ADMINISTRATOR, true, &HandleReloadLocalesCreatureCommand, "", NULL }, - { "locales_creature_text", SEC_ADMINISTRATOR, true, &HandleReloadLocalesCreatureTextCommand, "", NULL }, - { "locales_gameobject", SEC_ADMINISTRATOR, true, &HandleReloadLocalesGameobjectCommand, "", NULL }, - { "locales_gossip_menu_option", SEC_ADMINISTRATOR, true, &HandleReloadLocalesGossipMenuOptionCommand, "", NULL }, - { "locales_item", SEC_ADMINISTRATOR, true, &HandleReloadLocalesItemCommand, "", NULL }, - { "locales_npc_text", SEC_ADMINISTRATOR, true, &HandleReloadLocalesNpcTextCommand, "", NULL }, - { "locales_page_text", SEC_ADMINISTRATOR, true, &HandleReloadLocalesPageTextCommand, "", NULL }, - { "locales_points_of_interest", SEC_ADMINISTRATOR, true, &HandleReloadLocalesPointsOfInterestCommand, "", NULL }, - { "locales_quest", SEC_ADMINISTRATOR, true, &HandleReloadLocalesQuestCommand, "", NULL }, - { "mail_level_reward", SEC_ADMINISTRATOR, true, &HandleReloadMailLevelRewardCommand, "", NULL }, - { "mail_loot_template", SEC_ADMINISTRATOR, true, &HandleReloadLootTemplatesMailCommand, "", NULL }, - { "milling_loot_template", SEC_ADMINISTRATOR, true, &HandleReloadLootTemplatesMillingCommand, "", NULL }, - { "npc_spellclick_spells", SEC_ADMINISTRATOR, true, &HandleReloadSpellClickSpellsCommand, "", NULL}, - { "npc_trainer", SEC_ADMINISTRATOR, true, &HandleReloadNpcTrainerCommand, "", NULL }, - { "npc_vendor", SEC_ADMINISTRATOR, true, &HandleReloadNpcVendorCommand, "", NULL }, - { "page_text", SEC_ADMINISTRATOR, true, &HandleReloadPageTextsCommand, "", NULL }, - { "phasedefinitions", SEC_ADMINISTRATOR, true, &HandleReloadPhaseDefinitionsCommand, "", NULL }, - { "pickpocketing_loot_template", SEC_ADMINISTRATOR, true, &HandleReloadLootTemplatesPickpocketingCommand, "", NULL}, - { "points_of_interest", SEC_ADMINISTRATOR, true, &HandleReloadPointsOfInterestCommand, "", NULL }, - { "prospecting_loot_template", SEC_ADMINISTRATOR, true, &HandleReloadLootTemplatesProspectingCommand, "", NULL }, - { "quest_poi", SEC_ADMINISTRATOR, true, &HandleReloadQuestPOICommand, "", NULL }, - { "quest_template", SEC_ADMINISTRATOR, true, &HandleReloadQuestTemplateCommand, "", NULL }, - { "rbac", SEC_ADMINISTRATOR, true, &HandleReloadRBACCommand, "", NULL }, - { "reference_loot_template", SEC_ADMINISTRATOR, true, &HandleReloadLootTemplatesReferenceCommand, "", NULL }, - { "reserved_name", SEC_ADMINISTRATOR, true, &HandleReloadReservedNameCommand, "", NULL }, - { "reputation_reward_rate", SEC_ADMINISTRATOR, true, &HandleReloadReputationRewardRateCommand, "", NULL }, - { "reputation_spillover_template", SEC_ADMINISTRATOR, true, &HandleReloadReputationRewardRateCommand, "", NULL }, - { "skill_discovery_template", SEC_ADMINISTRATOR, true, &HandleReloadSkillDiscoveryTemplateCommand, "", NULL }, - { "skill_extra_item_template", SEC_ADMINISTRATOR, true, &HandleReloadSkillExtraItemTemplateCommand, "", NULL }, - { "skill_fishing_base_level", SEC_ADMINISTRATOR, true, &HandleReloadSkillFishingBaseLevelCommand, "", NULL }, - { "skinning_loot_template", SEC_ADMINISTRATOR, true, &HandleReloadLootTemplatesSkinningCommand, "", NULL }, - { "smart_scripts", SEC_ADMINISTRATOR, true, &HandleReloadSmartScripts, "", NULL }, - { "spell_required", SEC_ADMINISTRATOR, true, &HandleReloadSpellRequiredCommand, "", NULL }, - { "spell_area", SEC_ADMINISTRATOR, true, &HandleReloadSpellAreaCommand, "", NULL }, - { "spell_bonus_data", SEC_ADMINISTRATOR, true, &HandleReloadSpellBonusesCommand, "", NULL }, - { "spell_group", SEC_ADMINISTRATOR, true, &HandleReloadSpellGroupsCommand, "", NULL }, - { "spell_learn_spell", SEC_ADMINISTRATOR, true, &HandleReloadSpellLearnSpellCommand, "", NULL }, - { "spell_loot_template", SEC_ADMINISTRATOR, true, &HandleReloadLootTemplatesSpellCommand, "", NULL }, - { "spell_linked_spell", SEC_ADMINISTRATOR, true, &HandleReloadSpellLinkedSpellCommand, "", NULL }, - { "spell_pet_auras", SEC_ADMINISTRATOR, true, &HandleReloadSpellPetAurasCommand, "", NULL }, - { "spell_proc_event", SEC_ADMINISTRATOR, true, &HandleReloadSpellProcEventCommand, "", NULL }, - { "spell_proc", SEC_ADMINISTRATOR, true, &HandleReloadSpellProcsCommand, "", NULL }, - { "spell_scripts", SEC_ADMINISTRATOR, true, &HandleReloadSpellScriptsCommand, "", NULL }, - { "spell_target_position", SEC_ADMINISTRATOR, true, &HandleReloadSpellTargetPositionCommand, "", NULL }, - { "spell_threats", SEC_ADMINISTRATOR, true, &HandleReloadSpellThreatsCommand, "", NULL }, - { "spell_group_stack_rules", SEC_ADMINISTRATOR, true, &HandleReloadSpellGroupStackRulesCommand, "", NULL }, - { "trinity_string", SEC_ADMINISTRATOR, true, &HandleReloadTrinityStringCommand, "", NULL }, - { "warden_action", SEC_ADMINISTRATOR, true, &HandleReloadWardenactionCommand, "", NULL }, - { "waypoint_scripts", SEC_ADMINISTRATOR, true, &HandleReloadWpScriptsCommand, "", NULL }, - { "waypoint_data", SEC_ADMINISTRATOR, true, &HandleReloadWpCommand, "", NULL }, - { "vehicle_accessory", SEC_ADMINISTRATOR, true, &HandleReloadVehicleAccessoryCommand, "", NULL }, - { "vehicle_template_accessory", SEC_ADMINISTRATOR, true, &HandleReloadVehicleTemplateAccessoryCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "auctions", RBAC_PERM_COMMANDS_RELOAD_AUCTIONS, true, &HandleReloadAuctionsCommand, "", NULL }, + { "access_requirement", RBAC_PERM_COMMANDS_RELOAD_ACCESS_REQUIREMENT, true, &HandleReloadAccessRequirementCommand, "", NULL }, + { "achievement_criteria_data", RBAC_PERM_COMMANDS_RELOAD_ACHIEVEMENT_CRITERIA_DATA, true, &HandleReloadAchievementCriteriaDataCommand, "", NULL }, + { "achievement_reward", RBAC_PERM_COMMANDS_RELOAD_ACHIEVEMENT_REWARD, true, &HandleReloadAchievementRewardCommand, "", NULL }, + { "all", RBAC_PERM_COMMANDS_RELOAD_ALL, true, NULL, "", reloadAllCommandTable }, + { "areatrigger_involvedrelation", RBAC_PERM_COMMANDS_RELOAD_AREATRIGGER_INVOLVEDRELATION, true, &HandleReloadQuestAreaTriggersCommand, "", NULL }, + { "areatrigger_tavern", RBAC_PERM_COMMANDS_RELOAD_AREATRIGGER_TAVERN, true, &HandleReloadAreaTriggerTavernCommand, "", NULL }, + { "areatrigger_teleport", RBAC_PERM_COMMANDS_RELOAD_AREATRIGGER_TELEPORT, true, &HandleReloadAreaTriggerTeleportCommand, "", NULL }, + { "autobroadcast", RBAC_PERM_COMMANDS_RELOAD_AUTOBROADCAST, true, &HandleReloadAutobroadcastCommand, "", NULL }, + { "command", RBAC_PERM_COMMANDS_RELOAD_COMMAND, true, &HandleReloadCommandCommand, "", NULL }, + { "conditions", RBAC_PERM_COMMANDS_RELOAD_CONDITIONS, true, &HandleReloadConditions, "", NULL }, + { "config", RBAC_PERM_COMMANDS_RELOAD_CONFIG, true, &HandleReloadConfigCommand, "", NULL }, + { "creature_text", RBAC_PERM_COMMANDS_RELOAD_CREATURE_TEXT, true, &HandleReloadCreatureText, "", NULL }, + { "creature_questender", RBAC_PERM_COMMANDS_RELOAD_CREATURE_QUESTENDER, true, &HandleReloadCreatureQuestEnderCommand, "", NULL }, + { "creature_linked_respawn", RBAC_PERM_COMMANDS_RELOAD_CREATURE_LINKED_RESPAWN, true, &HandleReloadLinkedRespawnCommand, "", NULL }, + { "creature_loot_template", RBAC_PERM_COMMANDS_RELOAD_CREATURE_LOOT_TEMPLATE, true, &HandleReloadLootTemplatesCreatureCommand, "", NULL }, + { "creature_onkill_reputation", RBAC_PERM_COMMANDS_RELOAD_CREATURE_ONKILL_REPUTATION, true, &HandleReloadOnKillReputationCommand, "", NULL }, + { "creature_queststarter", RBAC_PERM_COMMANDS_RELOAD_CREATURE_QUESTSTARTER, true, &HandleReloadCreatureQuestStarterCommand, "", NULL }, + { "creature_summon_groups", RBAC_PERM_COMMANDS_RELOAD_CREATURE_SUMMON_GROUPS, true, &HandleReloadCreatureSummonGroupsCommand, "", NULL }, + { "creature_template", RBAC_PERM_COMMANDS_RELOAD_CREATURE_TEMPLATE, true, &HandleReloadCreatureTemplateCommand, "", NULL }, + //{ "db_script_string", RBAC_PERM_COMMANDS_RELOAD_, true, &HandleReloadDbScriptStringCommand, "", NULL }, + { "disables", RBAC_PERM_COMMANDS_RELOAD_DISABLES, true, &HandleReloadDisablesCommand, "", NULL }, + { "disenchant_loot_template", RBAC_PERM_COMMANDS_RELOAD_DISENCHANT_LOOT_TEMPLATE, true, &HandleReloadLootTemplatesDisenchantCommand, "", NULL }, + { "event_scripts", RBAC_PERM_COMMANDS_RELOAD_EVENT_SCRIPTS, true, &HandleReloadEventScriptsCommand, "", NULL }, + { "fishing_loot_template", RBAC_PERM_COMMANDS_RELOAD_FISHING_LOOT_TEMPLATE, true, &HandleReloadLootTemplatesFishingCommand, "", NULL }, + { "game_graveyard_zone", RBAC_PERM_COMMANDS_RELOAD_GAME_GRAVEYARD_ZONE, true, &HandleReloadGameGraveyardZoneCommand, "", NULL }, + { "game_tele", RBAC_PERM_COMMANDS_RELOAD_GAME_TELE, true, &HandleReloadGameTeleCommand, "", NULL }, + { "gameobject_questender", RBAC_PERM_COMMANDS_RELOAD_GAMEOBJECT_QUESTENDER, true, &HandleReloadGOQuestEnderCommand, "", NULL }, + { "gameobject_loot_template", RBAC_PERM_COMMANDS_RELOAD_GAMEOBJECT_QUEST_LOOT_TEMPLATE, true, &HandleReloadLootTemplatesGameobjectCommand, "", NULL }, + { "gameobject_queststarter", RBAC_PERM_COMMANDS_RELOAD_GAMEOBJECT_QUESTSTARTER, true, &HandleReloadGOQuestStarterCommand, "", NULL }, + { "gm_tickets", RBAC_PERM_COMMANDS_RELOAD_GM_TICKETS, true, &HandleReloadGMTicketsCommand, "", NULL }, + { "gossip_menu", RBAC_PERM_COMMANDS_RELOAD_GOSSIP_MENU, true, &HandleReloadGossipMenuCommand, "", NULL }, + { "gossip_menu_option", RBAC_PERM_COMMANDS_RELOAD_GOSSIP_MENU_OPTION, true, &HandleReloadGossipMenuOptionCommand, "", NULL }, + { "item_enchantment_template", RBAC_PERM_COMMANDS_RELOAD_ITEM_ENCHANTMENT_TEMPLATE, true, &HandleReloadItemEnchantementsCommand, "", NULL }, + { "item_loot_template", RBAC_PERM_COMMANDS_RELOAD_ITEM_LOOT_TEMPLATE, true, &HandleReloadLootTemplatesItemCommand, "", NULL }, + { "lfg_dungeon_rewards", RBAC_PERM_COMMANDS_RELOAD_LFG_DUNGEON_REWARDS, true, &HandleReloadLfgRewardsCommand, "", NULL }, + { "locales_achievement_reward", RBAC_PERM_COMMANDS_RELOAD_LOCALES_ACHIEVEMENT_REWARD, true, &HandleReloadLocalesAchievementRewardCommand, "", NULL }, + { "locales_creature", RBAC_PERM_COMMANDS_RELOAD_LOCALES_CRETURE, true, &HandleReloadLocalesCreatureCommand, "", NULL }, + { "locales_creature_text", RBAC_PERM_COMMANDS_RELOAD_LOCALES_CRETURE_TEXT, true, &HandleReloadLocalesCreatureTextCommand, "", NULL }, + { "locales_gameobject", RBAC_PERM_COMMANDS_RELOAD_LOCALES_GAMEOBJECT, true, &HandleReloadLocalesGameobjectCommand, "", NULL }, + { "locales_gossip_menu_option", RBAC_PERM_COMMANDS_RELOAD_LOCALES_GOSSIP_MENU_OPTION, true, &HandleReloadLocalesGossipMenuOptionCommand, "", NULL }, + { "locales_item", RBAC_PERM_COMMANDS_RELOAD_LOCALES_ITEM, true, &HandleReloadLocalesItemCommand, "", NULL }, + { "locales_npc_text", RBAC_PERM_COMMANDS_RELOAD_LOCALES_NPC_TEXT, true, &HandleReloadLocalesNpcTextCommand, "", NULL }, + { "locales_page_text", RBAC_PERM_COMMANDS_RELOAD_LOCALES_PAGE_TEXT, true, &HandleReloadLocalesPageTextCommand, "", NULL }, + { "locales_points_of_interest", RBAC_PERM_COMMANDS_RELOAD_LOCALES_POINTS_OF_INTEREST, true, &HandleReloadLocalesPointsOfInterestCommand, "", NULL }, + { "locales_quest", RBAC_PERM_COMMANDS_RELOAD_LOCALES_QUEST, true, &HandleReloadLocalesQuestCommand, "", NULL }, + { "mail_level_reward", RBAC_PERM_COMMANDS_RELOAD_MAIL_LEVEL_REWARD, true, &HandleReloadMailLevelRewardCommand, "", NULL }, + { "mail_loot_template", RBAC_PERM_COMMANDS_RELOAD_MAIL_LOOT_TEMPLATE, true, &HandleReloadLootTemplatesMailCommand, "", NULL }, + { "milling_loot_template", RBAC_PERM_COMMANDS_RELOAD_MILLING_LOOT_TEMPLATE, true, &HandleReloadLootTemplatesMillingCommand, "", NULL }, + { "npc_spellclick_spells", RBAC_PERM_COMMANDS_RELOAD_NPC_SPELLCLICK_SPELLS, true, &HandleReloadSpellClickSpellsCommand, "", NULL}, + { "npc_trainer", RBAC_PERM_COMMANDS_RELOAD_NPC_TRAINER, true, &HandleReloadNpcTrainerCommand, "", NULL }, + { "npc_vendor", RBAC_PERM_COMMANDS_RELOAD_NPC_VENDOR, true, &HandleReloadNpcVendorCommand, "", NULL }, + { "page_text", RBAC_PERM_COMMANDS_RELOAD_PAGE_TEXT, true, &HandleReloadPageTextsCommand, "", NULL }, + { "pickpocketing_loot_template", RBAC_PERM_COMMANDS_RELOAD_PICKPOCKETING_LOOT_TEMPLATE, true, &HandleReloadLootTemplatesPickpocketingCommand, "", NULL}, + { "points_of_interest", RBAC_PERM_COMMANDS_RELOAD_POINTS_OF_INTEREST, true, &HandleReloadPointsOfInterestCommand, "", NULL }, + { "prospecting_loot_template", RBAC_PERM_COMMANDS_RELOAD_PROSPECTING_LOOT_TEMPLATE, true, &HandleReloadLootTemplatesProspectingCommand, "", NULL }, + { "quest_poi", RBAC_PERM_COMMANDS_RELOAD_QUEST_POI, true, &HandleReloadQuestPOICommand, "", NULL }, + { "quest_template", RBAC_PERM_COMMANDS_RELOAD_QUEST_TEMPLATE, true, &HandleReloadQuestTemplateCommand, "", NULL }, + { "rbac", RBAC_PERM_COMMANDS_RELOAD_RBAC, true, &HandleReloadRBACCommand, "", NULL }, + { "reference_loot_template", RBAC_PERM_COMMANDS_RELOAD_REFERENCE_LOOT_TEMPLATE, true, &HandleReloadLootTemplatesReferenceCommand, "", NULL }, + { "reserved_name", RBAC_PERM_COMMANDS_RELOAD_RESERVED_NAME, true, &HandleReloadReservedNameCommand, "", NULL }, + { "reputation_reward_rate", RBAC_PERM_COMMANDS_RELOAD_REPUTATION_REWARD_RATE, true, &HandleReloadReputationRewardRateCommand, "", NULL }, + { "reputation_spillover_template", RBAC_PERM_COMMANDS_RELOAD_SPILLOVER_TEMPLATE, true, &HandleReloadReputationRewardRateCommand, "", NULL }, + { "skill_discovery_template", RBAC_PERM_COMMANDS_RELOAD_SKILL_DISCOVERY_TEMPLATE, true, &HandleReloadSkillDiscoveryTemplateCommand, "", NULL }, + { "skill_extra_item_template", RBAC_PERM_COMMANDS_RELOAD_SKILL_EXTRA_ITEM_TEMPLATE, true, &HandleReloadSkillExtraItemTemplateCommand, "", NULL }, + { "skill_fishing_base_level", RBAC_PERM_COMMANDS_RELOAD_SKILL_FISHING_BASE_LEVEL, true, &HandleReloadSkillFishingBaseLevelCommand, "", NULL }, + { "skinning_loot_template", RBAC_PERM_COMMANDS_RELOAD_SKINNING_LOOT_TEMPLATE, true, &HandleReloadLootTemplatesSkinningCommand, "", NULL }, + { "smart_scripts", RBAC_PERM_COMMANDS_RELOAD_SMART_SCRIPTS, true, &HandleReloadSmartScripts, "", NULL }, + { "spell_required", RBAC_PERM_COMMANDS_RELOAD_SPELL_REQUIRED, true, &HandleReloadSpellRequiredCommand, "", NULL }, + { "spell_area", RBAC_PERM_COMMANDS_RELOAD_SPELL_AREA, true, &HandleReloadSpellAreaCommand, "", NULL }, + { "spell_bonus_data", RBAC_PERM_COMMANDS_RELOAD_SPELL_BONUS_DATA, true, &HandleReloadSpellBonusesCommand, "", NULL }, + { "spell_group", RBAC_PERM_COMMANDS_RELOAD_SPELL_GROUP, true, &HandleReloadSpellGroupsCommand, "", NULL }, + { "spell_learn_spell", RBAC_PERM_COMMANDS_RELOAD_SPELL_LEARN_SPELL, true, &HandleReloadSpellLearnSpellCommand, "", NULL }, + { "spell_loot_template", RBAC_PERM_COMMANDS_RELOAD_SPELL_LOOT_TEMPLATE, true, &HandleReloadLootTemplatesSpellCommand, "", NULL }, + { "spell_linked_spell", RBAC_PERM_COMMANDS_RELOAD_SPELL_LINKED_SPELL, true, &HandleReloadSpellLinkedSpellCommand, "", NULL }, + { "spell_pet_auras", RBAC_PERM_COMMANDS_RELOAD_SPELL_PET_AURAS, true, &HandleReloadSpellPetAurasCommand, "", NULL }, + { "spell_proc_event", RBAC_PERM_COMMANDS_RELOAD_SPELL_PROC_EVENT, true, &HandleReloadSpellProcEventCommand, "", NULL }, + { "spell_proc", RBAC_PERM_COMMANDS_RELOAD_SPELL_PROC, true, &HandleReloadSpellProcsCommand, "", NULL }, + { "spell_scripts", RBAC_PERM_COMMANDS_RELOAD_SPELL_SCRIPTS, true, &HandleReloadSpellScriptsCommand, "", NULL }, + { "spell_target_position", RBAC_PERM_COMMANDS_RELOAD_SPELL_TARGET_POSITION, true, &HandleReloadSpellTargetPositionCommand, "", NULL }, + { "spell_threats", RBAC_PERM_COMMANDS_RELOAD_SPELL_THREATS, true, &HandleReloadSpellThreatsCommand, "", NULL }, + { "spell_group_stack_rules", RBAC_PERM_COMMANDS_RELOAD_SPELL_GROUP_STACK_RULES, true, &HandleReloadSpellGroupStackRulesCommand, "", NULL }, + { "trinity_string", RBAC_PERM_COMMANDS_RELOAD_TRINITY_STRING, true, &HandleReloadTrinityStringCommand, "", NULL }, + { "warden_action", RBAC_PERM_COMMANDS_RELOAD_WARDEN_ACTION, true, &HandleReloadWardenactionCommand, "", NULL }, + { "waypoint_scripts", RBAC_PERM_COMMANDS_RELOAD_WAYPOINT_SCRIPTS, true, &HandleReloadWpScriptsCommand, "", NULL }, + { "waypoint_data", RBAC_PERM_COMMANDS_RELOAD_WAYPOINT_DATA, true, &HandleReloadWpCommand, "", NULL }, + { "vehicle_accessory", RBAC_PERM_COMMANDS_RELOAD_VEHICLE_ACCESORY, true, &HandleReloadVehicleAccessoryCommand, "", NULL }, + { "vehicle_template_accessory", RBAC_PERM_COMMANDS_RELOAD_VEHICLE_TEMPLATE_ACCESSORY, true, &HandleReloadVehicleTemplateAccessoryCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand commandTable[] = { - { "reload", SEC_ADMINISTRATOR, true, NULL, "", reloadCommandTable }, - { NULL, 0, false, NULL, "", NULL } + { "reload", RBAC_PERM_COMMANDS_RELOAD, true, NULL, "", reloadCommandTable }, + { NULL, 0, false, NULL, "", NULL } }; return commandTable; } diff --git a/src/server/scripts/Commands/cs_reset.cpp b/src/server/scripts/Commands/cs_reset.cpp index 0d7145d32e8..95ee15d05f2 100644 --- a/src/server/scripts/Commands/cs_reset.cpp +++ b/src/server/scripts/Commands/cs_reset.cpp @@ -39,19 +39,19 @@ public: { static ChatCommand resetCommandTable[] = { - { "achievements", SEC_ADMINISTRATOR, true, &HandleResetAchievementsCommand, "", NULL }, - { "honor", SEC_ADMINISTRATOR, true, &HandleResetHonorCommand, "", NULL }, - { "level", SEC_ADMINISTRATOR, true, &HandleResetLevelCommand, "", NULL }, - { "spells", SEC_ADMINISTRATOR, true, &HandleResetSpellsCommand, "", NULL }, - { "stats", SEC_ADMINISTRATOR, true, &HandleResetStatsCommand, "", NULL }, - { "talents", SEC_ADMINISTRATOR, true, &HandleResetTalentsCommand, "", NULL }, - { "all", SEC_ADMINISTRATOR, true, &HandleResetAllCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "achievements", RBAC_PERM_COMMAND_RESET_ACHIEVEMENTS, true, &HandleResetAchievementsCommand, "", NULL }, + { "honor", RBAC_PERM_COMMAND_RESET_HONOR, true, &HandleResetHonorCommand, "", NULL }, + { "level", RBAC_PERM_COMMAND_RESET_LEVEL, true, &HandleResetLevelCommand, "", NULL }, + { "spells", RBAC_PERM_COMMAND_RESET_SPELLS, true, &HandleResetSpellsCommand, "", NULL }, + { "stats", RBAC_PERM_COMMAND_RESET_STATS, true, &HandleResetStatsCommand, "", NULL }, + { "talents", RBAC_PERM_COMMAND_RESET_TALENTS, true, &HandleResetTalentsCommand, "", NULL }, + { "all", RBAC_PERM_COMMAND_RESET_ALL, true, &HandleResetAllCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand commandTable[] = { - { "reset", SEC_ADMINISTRATOR, true, NULL, "", resetCommandTable }, - { NULL, 0, false, NULL, "", NULL } + { "reset", RBAC_PERM_COMMAND_RESET, true, NULL, "", resetCommandTable }, + { NULL, 0, false, NULL, "", NULL } }; return commandTable; } diff --git a/src/server/scripts/Commands/cs_send.cpp b/src/server/scripts/Commands/cs_send.cpp new file mode 100644 index 00000000000..5d50113249a --- /dev/null +++ b/src/server/scripts/Commands/cs_send.cpp @@ -0,0 +1,289 @@ +/* + * Copyright (C) 2008-2013 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 "Chat.h" +#include "Language.h" +#include "Pet.h" +#include "Player.h" +#include "ObjectMgr.h" +#include "ScriptMgr.h" + +class send_commandscript : public CommandScript +{ +public: + send_commandscript() : CommandScript("send_commandscript") { } + + ChatCommand* GetCommands() const OVERRIDE + { + static ChatCommand sendCommandTable[] = + { + { "items", RBAC_PERM_COMMAND_SEND_ITEMS, true, &HandleSendItemsCommand, "", NULL }, + { "mail", RBAC_PERM_COMMAND_SEND_MAIL, true, &HandleSendMailCommand, "", NULL }, + { "message", RBAC_PERM_COMMAND_SEND_MESSAGE, true, &HandleSendMessageCommand, "", NULL }, + { "money", RBAC_PERM_COMMAND_SEND_MONEY, true, &HandleSendMoneyCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } + }; + + static ChatCommand commandTable[] = + { + { "send", RBAC_PERM_COMMAND_SEND, false, NULL, "", sendCommandTable }, + { NULL, 0, false, NULL, "", NULL } + }; + return commandTable; + } + + // Send mail by command + static bool HandleSendMailCommand(ChatHandler* handler, char const* args) + { + // format: name "subject text" "mail text" + Player* target; + uint64 targetGuid; + std::string targetName; + if (!handler->extractPlayerTarget((char*)args, &target, &targetGuid, &targetName)) + return false; + + char* tail1 = strtok(NULL, ""); + if (!tail1) + return false; + + char const* msgSubject = handler->extractQuotedArg(tail1); + if (!msgSubject) + return false; + + char* tail2 = strtok(NULL, ""); + if (!tail2) + return false; + + char const* msgText = handler->extractQuotedArg(tail2); + if (!msgText) + return false; + + // msgSubject, msgText isn't NUL after prev. check + std::string subject = msgSubject; + std::string text = msgText; + + // from console show not existed sender + MailSender sender(MAIL_NORMAL, handler->GetSession() ? handler->GetSession()->GetPlayer()->GetGUIDLow() : 0, MAIL_STATIONERY_GM); + + /// @todo Fix poor design + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + MailDraft(subject, text) + .SendMailTo(trans, MailReceiver(target, GUID_LOPART(targetGuid)), sender); + + CharacterDatabase.CommitTransaction(trans); + + std::string nameLink = handler->playerLink(targetName); + handler->PSendSysMessage(LANG_MAIL_SENT, nameLink.c_str()); + return true; + } + + // Send items by mail + static bool HandleSendItemsCommand(ChatHandler* handler, char const* args) + { + // format: name "subject text" "mail text" item1[:count1] item2[:count2] ... item12[:count12] + Player* receiver; + uint64 receiverGuid; + std::string receiverName; + if (!handler->extractPlayerTarget((char*)args, &receiver, &receiverGuid, &receiverName)) + return false; + + char* tail1 = strtok(NULL, ""); + if (!tail1) + return false; + + char const* msgSubject = handler->extractQuotedArg(tail1); + if (!msgSubject) + return false; + + char* tail2 = strtok(NULL, ""); + if (!tail2) + return false; + + char const* msgText = handler->extractQuotedArg(tail2); + if (!msgText) + return false; + + // msgSubject, msgText isn't NUL after prev. check + std::string subject = msgSubject; + std::string text = msgText; + + // extract items + typedef std::pair<uint32, uint32> ItemPair; + typedef std::list< ItemPair > ItemPairs; + ItemPairs items; + + // get all tail string + char* tail = strtok(NULL, ""); + + // get from tail next item str + while (char* itemStr = strtok(tail, " ")) + { + // and get new tail + tail = strtok(NULL, ""); + + // parse item str + char const* itemIdStr = strtok(itemStr, ":"); + char const* itemCountStr = strtok(NULL, " "); + + uint32 itemId = atoi(itemIdStr); + if (!itemId) + return false; + + ItemTemplate const* item_proto = sObjectMgr->GetItemTemplate(itemId); + if (!item_proto) + { + handler->PSendSysMessage(LANG_COMMAND_ITEMIDINVALID, itemId); + handler->SetSentErrorMessage(true); + return false; + } + + uint32 itemCount = itemCountStr ? atoi(itemCountStr) : 1; + if (itemCount < 1 || (item_proto->MaxCount > 0 && itemCount > uint32(item_proto->MaxCount))) + { + handler->PSendSysMessage(LANG_COMMAND_INVALID_ITEM_COUNT, itemCount, itemId); + handler->SetSentErrorMessage(true); + return false; + } + + while (itemCount > item_proto->GetMaxStackSize()) + { + items.push_back(ItemPair(itemId, item_proto->GetMaxStackSize())); + itemCount -= item_proto->GetMaxStackSize(); + } + + items.push_back(ItemPair(itemId, itemCount)); + + if (items.size() > MAX_MAIL_ITEMS) + { + handler->PSendSysMessage(LANG_COMMAND_MAIL_ITEMS_LIMIT, MAX_MAIL_ITEMS); + handler->SetSentErrorMessage(true); + return false; + } + } + + // from console show not existed sender + MailSender sender(MAIL_NORMAL, handler->GetSession() ? handler->GetSession()->GetPlayer()->GetGUIDLow() : 0, MAIL_STATIONERY_GM); + + // fill mail + MailDraft draft(subject, text); + + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + + for (ItemPairs::const_iterator itr = items.begin(); itr != items.end(); ++itr) + { + if (Item* item = Item::CreateItem(itr->first, itr->second, handler->GetSession() ? handler->GetSession()->GetPlayer() : 0)) + { + item->SaveToDB(trans); // save for prevent lost at next mail load, if send fail then item will deleted + draft.AddItem(item); + } + } + + draft.SendMailTo(trans, MailReceiver(receiver, GUID_LOPART(receiverGuid)), sender); + CharacterDatabase.CommitTransaction(trans); + + std::string nameLink = handler->playerLink(receiverName); + handler->PSendSysMessage(LANG_MAIL_SENT, nameLink.c_str()); + return true; + } + /// Send money by mail + static bool HandleSendMoneyCommand(ChatHandler* handler, char const* args) + { + /// format: name "subject text" "mail text" money + + Player* receiver; + uint64 receiverGuid; + std::string receiverName; + if (!handler->extractPlayerTarget((char*)args, &receiver, &receiverGuid, &receiverName)) + return false; + + char* tail1 = strtok(NULL, ""); + if (!tail1) + return false; + + char* msgSubject = handler->extractQuotedArg(tail1); + if (!msgSubject) + return false; + + char* tail2 = strtok(NULL, ""); + if (!tail2) + return false; + + char* msgText = handler->extractQuotedArg(tail2); + if (!msgText) + return false; + + char* moneyStr = strtok(NULL, ""); + int32 money = moneyStr ? atoi(moneyStr) : 0; + if (money <= 0) + return false; + + // msgSubject, msgText isn't NUL after prev. check + std::string subject = msgSubject; + std::string text = msgText; + + // from console show not existed sender + MailSender sender(MAIL_NORMAL, handler->GetSession() ? handler->GetSession()->GetPlayer()->GetGUIDLow() : 0, MAIL_STATIONERY_GM); + + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + + MailDraft(subject, text) + .AddMoney(money) + .SendMailTo(trans, MailReceiver(receiver, GUID_LOPART(receiverGuid)), sender); + + CharacterDatabase.CommitTransaction(trans); + + std::string nameLink = handler->playerLink(receiverName); + handler->PSendSysMessage(LANG_MAIL_SENT, nameLink.c_str()); + return true; + } + /// Send a message to a player in game + static bool HandleSendMessageCommand(ChatHandler* handler, char const* args) + { + /// - Find the player + Player* player; + if (!handler->extractPlayerTarget((char*)args, &player)) + return false; + + char* msgStr = strtok(NULL, ""); + if (!msgStr) + return false; + + ///- Check that he is not logging out. + if (player->GetSession()->isLogingOut()) + { + handler->SendSysMessage(LANG_PLAYER_NOT_FOUND); + handler->SetSentErrorMessage(true); + return false; + } + + /// - Send the message + // Use SendAreaTriggerMessage for fastest delivery. + player->GetSession()->SendAreaTriggerMessage("%s", msgStr); + player->GetSession()->SendAreaTriggerMessage("|cffff0000[Message from administrator]:|r"); + + // Confirmation message + std::string nameLink = handler->GetNameLink(player); + handler->PSendSysMessage(LANG_SENDMESSAGE, nameLink.c_str(), msgStr); + + return true; + } +}; + +void AddSC_send_commandscript() +{ + new send_commandscript(); +} diff --git a/src/server/scripts/Commands/cs_server.cpp b/src/server/scripts/Commands/cs_server.cpp index ec8771cc2f4..71f232d33a6 100644 --- a/src/server/scripts/Commands/cs_server.cpp +++ b/src/server/scripts/Commands/cs_server.cpp @@ -39,60 +39,60 @@ public: { static ChatCommand serverIdleRestartCommandTable[] = { - { "cancel", SEC_ADMINISTRATOR, true, &HandleServerShutDownCancelCommand, "", NULL }, - { "" , SEC_ADMINISTRATOR, true, &HandleServerIdleRestartCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "cancel", RBAC_PERM_COMMAND_SERVER_IDLERESTART_CANCEL, true, &HandleServerShutDownCancelCommand, "", NULL }, + { "" , RBAC_PERM_COMMAND_SERVER_IDLERESTART, true, &HandleServerIdleRestartCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand serverIdleShutdownCommandTable[] = { - { "cancel", SEC_ADMINISTRATOR, true, &HandleServerShutDownCancelCommand, "", NULL }, - { "" , SEC_ADMINISTRATOR, true, &HandleServerIdleShutDownCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "cancel", RBAC_PERM_COMMAND_SERVER_IDLESHUTDOWN_CANCEL, true, &HandleServerShutDownCancelCommand, "", NULL }, + { "" , RBAC_PERM_COMMAND_SERVER_IDLESHUTDOWN, true, &HandleServerIdleShutDownCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand serverRestartCommandTable[] = { - { "cancel", SEC_ADMINISTRATOR, true, &HandleServerShutDownCancelCommand, "", NULL }, - { "" , SEC_ADMINISTRATOR, true, &HandleServerRestartCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "cancel", RBAC_PERM_COMMAND_SERVER_RESTART_CANCEL, true, &HandleServerShutDownCancelCommand, "", NULL }, + { "" , RBAC_PERM_COMMAND_SERVER_RESTART, true, &HandleServerRestartCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand serverShutdownCommandTable[] = { - { "cancel", SEC_ADMINISTRATOR, true, &HandleServerShutDownCancelCommand, "", NULL }, - { "" , SEC_ADMINISTRATOR, true, &HandleServerShutDownCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "cancel", RBAC_PERM_COMMAND_SERVER_SHUTDOWN_CANCEL, true, &HandleServerShutDownCancelCommand, "", NULL }, + { "" , RBAC_PERM_COMMAND_SERVER_SHUTDOWN, true, &HandleServerShutDownCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand serverSetCommandTable[] = { - { "difftime", SEC_CONSOLE, true, &HandleServerSetDiffTimeCommand, "", NULL }, - { "loglevel", SEC_CONSOLE, true, &HandleServerSetLogLevelCommand, "", NULL }, - { "motd", SEC_ADMINISTRATOR, true, &HandleServerSetMotdCommand, "", NULL }, - { "closed", SEC_ADMINISTRATOR, true, &HandleServerSetClosedCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "difftime", RBAC_PERM_COMMAND_SERVER_SET_DIFFTIME, true, &HandleServerSetDiffTimeCommand, "", NULL }, + { "loglevel", RBAC_PERM_COMMAND_SERVER_SET_LOGLEVEL, true, &HandleServerSetLogLevelCommand, "", NULL }, + { "motd", RBAC_PERM_COMMAND_SERVER_SET_MOTD, true, &HandleServerSetMotdCommand, "", NULL }, + { "closed", RBAC_PERM_COMMAND_SERVER_SET_CLOSED, true, &HandleServerSetClosedCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand serverCommandTable[] = { - { "corpses", SEC_GAMEMASTER, true, &HandleServerCorpsesCommand, "", NULL }, - { "exit", SEC_CONSOLE, true, &HandleServerExitCommand, "", NULL }, - { "idlerestart", SEC_ADMINISTRATOR, true, NULL, "", serverIdleRestartCommandTable }, - { "idleshutdown", SEC_ADMINISTRATOR, true, NULL, "", serverIdleShutdownCommandTable }, - { "info", SEC_PLAYER, true, &HandleServerInfoCommand, "", NULL }, - { "motd", SEC_PLAYER, true, &HandleServerMotdCommand, "", NULL }, - { "plimit", SEC_ADMINISTRATOR, true, &HandleServerPLimitCommand, "", NULL }, - { "restart", SEC_ADMINISTRATOR, true, NULL, "", serverRestartCommandTable }, - { "shutdown", SEC_ADMINISTRATOR, true, NULL, "", serverShutdownCommandTable }, - { "set", SEC_ADMINISTRATOR, true, NULL, "", serverSetCommandTable }, - { NULL, 0, false, NULL, "", NULL } + { "corpses", RBAC_PERM_COMMAND_SERVER_CORPSES, true, &HandleServerCorpsesCommand, "", NULL }, + { "exit", RBAC_PERM_COMMAND_SERVER_EXIT, true, &HandleServerExitCommand, "", NULL }, + { "idlerestart", RBAC_PERM_COMMAND_SERVER_IDLERESTART, true, NULL, "", serverIdleRestartCommandTable }, + { "idleshutdown", RBAC_PERM_COMMAND_SERVER_IDLESHUTDOWN, true, NULL, "", serverIdleShutdownCommandTable }, + { "info", RBAC_PERM_COMMAND_SERVER_INFO, true, &HandleServerInfoCommand, "", NULL }, + { "motd", RBAC_PERM_COMMAND_SERVER_MOTD, true, &HandleServerMotdCommand, "", NULL }, + { "plimit", RBAC_PERM_COMMAND_SERVER_PLIMIT, true, &HandleServerPLimitCommand, "", NULL }, + { "restart", RBAC_PERM_COMMAND_SERVER_RESTART, true, NULL, "", serverRestartCommandTable }, + { "shutdown", RBAC_PERM_COMMAND_SERVER_SHUTDOWN, true, NULL, "", serverShutdownCommandTable }, + { "set", RBAC_PERM_COMMAND_SERVER_SET, true, NULL, "", serverSetCommandTable }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand commandTable[] = { - { "server", SEC_ADMINISTRATOR, true, NULL, "", serverCommandTable }, - { NULL, 0, false, NULL, "", NULL } + { "server", RBAC_PERM_COMMAND_SERVER, true, NULL, "", serverCommandTable }, + { NULL, 0, false, NULL, "", NULL } }; return commandTable; } diff --git a/src/server/scripts/Commands/cs_tele.cpp b/src/server/scripts/Commands/cs_tele.cpp index 12276102df1..dec9895af26 100644 --- a/src/server/scripts/Commands/cs_tele.cpp +++ b/src/server/scripts/Commands/cs_tele.cpp @@ -39,17 +39,17 @@ public: { static ChatCommand teleCommandTable[] = { - { "add", SEC_ADMINISTRATOR, false, &HandleTeleAddCommand, "", NULL }, - { "del", SEC_ADMINISTRATOR, true, &HandleTeleDelCommand, "", NULL }, - { "name", SEC_MODERATOR, true, &HandleTeleNameCommand, "", NULL }, - { "group", SEC_MODERATOR, false, &HandleTeleGroupCommand, "", NULL }, - { "", SEC_MODERATOR, false, &HandleTeleCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "add", RBAC_PERM_COMMAND_TELE_ADD, false, &HandleTeleAddCommand, "", NULL }, + { "del", RBAC_PERM_COMMAND_TELE_DEL, true, &HandleTeleDelCommand, "", NULL }, + { "name", RBAC_PERM_COMMAND_TELE_NAME, true, &HandleTeleNameCommand, "", NULL }, + { "group", RBAC_PERM_COMMAND_TELE_GROUP, false, &HandleTeleGroupCommand, "", NULL }, + { "", RBAC_PERM_COMMAND_TELE, false, &HandleTeleCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand commandTable[] = { - { "tele", SEC_MODERATOR, false, NULL, "", teleCommandTable }, - { NULL, 0, false, NULL, "", NULL } + { "tele", RBAC_PERM_COMMAND_TELE, false, NULL, "", teleCommandTable }, + { NULL, 0, false, NULL, "", NULL } }; return commandTable; } diff --git a/src/server/scripts/Commands/cs_ticket.cpp b/src/server/scripts/Commands/cs_ticket.cpp index 0795b2ab90c..1c60a8143b4 100644 --- a/src/server/scripts/Commands/cs_ticket.cpp +++ b/src/server/scripts/Commands/cs_ticket.cpp @@ -40,34 +40,34 @@ public: { static ChatCommand ticketResponseCommandTable[] = { - { "append", SEC_MODERATOR, true, &HandleGMTicketResponseAppendCommand, "", NULL }, - { "appendln", SEC_MODERATOR, true, &HandleGMTicketResponseAppendLnCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "append", RBAC_PERM_COMMAND_TICKET_RESPONSE_APPEND, true, &HandleGMTicketResponseAppendCommand, "", NULL }, + { "appendln", RBAC_PERM_COMMAND_TICKET_RESPONSE_APPENDLN, true, &HandleGMTicketResponseAppendLnCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand ticketCommandTable[] = { - { "assign", SEC_GAMEMASTER, true, &HandleGMTicketAssignToCommand, "", NULL }, - { "close", SEC_MODERATOR, true, &HandleGMTicketCloseByIdCommand, "", NULL }, - { "closedlist", SEC_MODERATOR, true, &HandleGMTicketListClosedCommand, "", NULL }, - { "comment", SEC_MODERATOR, true, &HandleGMTicketCommentCommand, "", NULL }, - { "complete", SEC_MODERATOR, true, &HandleGMTicketCompleteCommand, "", NULL }, - { "delete", SEC_ADMINISTRATOR, true, &HandleGMTicketDeleteByIdCommand, "", NULL }, - { "escalate", SEC_MODERATOR, true, &HandleGMTicketEscalateCommand, "", NULL }, - { "escalatedlist", SEC_GAMEMASTER, true, &HandleGMTicketListEscalatedCommand, "", NULL }, - { "list", SEC_MODERATOR, true, &HandleGMTicketListCommand, "", NULL }, - { "onlinelist", SEC_MODERATOR, true, &HandleGMTicketListOnlineCommand, "", NULL }, - { "reset", SEC_ADMINISTRATOR, true, &HandleGMTicketResetCommand, "", NULL }, - { "response", SEC_MODERATOR, true, NULL, "", ticketResponseCommandTable }, - { "togglesystem", SEC_ADMINISTRATOR, true, &HandleToggleGMTicketSystem, "", NULL }, - { "unassign", SEC_GAMEMASTER, true, &HandleGMTicketUnAssignCommand, "", NULL }, - { "viewid", SEC_MODERATOR, true, &HandleGMTicketGetByIdCommand, "", NULL }, - { "viewname", SEC_MODERATOR, true, &HandleGMTicketGetByNameCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "assign", RBAC_PERM_COMMAND_TICKET_ASSIGN, true, &HandleGMTicketAssignToCommand, "", NULL }, + { "close", RBAC_PERM_COMMAND_TICKET_CLOSE, true, &HandleGMTicketCloseByIdCommand, "", NULL }, + { "closedlist", RBAC_PERM_COMMAND_TICKET_CLOSEDLIST, true, &HandleGMTicketListClosedCommand, "", NULL }, + { "comment", RBAC_PERM_COMMAND_TICKET_COMMENT, true, &HandleGMTicketCommentCommand, "", NULL }, + { "complete", RBAC_PERM_COMMAND_TICKET_COMPLETE, true, &HandleGMTicketCompleteCommand, "", NULL }, + { "delete", RBAC_PERM_COMMAND_TICKET_DELETE, true, &HandleGMTicketDeleteByIdCommand, "", NULL }, + { "escalate", RBAC_PERM_COMMAND_TICKET_ESCALATE, true, &HandleGMTicketEscalateCommand, "", NULL }, + { "escalatedlist", RBAC_PERM_COMMAND_TICKET_ESCALATEDLIST, true, &HandleGMTicketListEscalatedCommand, "", NULL }, + { "list", RBAC_PERM_COMMAND_TICKET_LIST, true, &HandleGMTicketListCommand, "", NULL }, + { "onlinelist", RBAC_PERM_COMMAND_TICKET_ONLINELIST, true, &HandleGMTicketListOnlineCommand, "", NULL }, + { "reset", RBAC_PERM_COMMAND_TICKET_RESET, true, &HandleGMTicketResetCommand, "", NULL }, + { "response", RBAC_PERM_COMMAND_TICKET_RESPONSE, true, NULL, "", ticketResponseCommandTable }, + { "togglesystem", RBAC_PERM_COMMAND_TICKET_TOGGLESYSTEM, true, &HandleToggleGMTicketSystem, "", NULL }, + { "unassign", RBAC_PERM_COMMAND_TICKET_UNASSIGN, true, &HandleGMTicketUnAssignCommand, "", NULL }, + { "viewid", RBAC_PERM_COMMAND_TICKET_VIEWID, true, &HandleGMTicketGetByIdCommand, "", NULL }, + { "viewname", RBAC_PERM_COMMAND_TICKET_VIEWNAME, true, &HandleGMTicketGetByNameCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand commandTable[] = { - { "ticket", SEC_MODERATOR, false, NULL, "", ticketCommandTable }, - { NULL, 0, false, NULL, "", NULL } + { "ticket", RBAC_PERM_COMMAND_TICKET, false, NULL, "", ticketCommandTable }, + { NULL, 0, false, NULL, "", NULL } }; return commandTable; } diff --git a/src/server/scripts/Commands/cs_titles.cpp b/src/server/scripts/Commands/cs_titles.cpp index 57ccbaa9657..1dc0ba76c17 100644 --- a/src/server/scripts/Commands/cs_titles.cpp +++ b/src/server/scripts/Commands/cs_titles.cpp @@ -37,21 +37,21 @@ public: { static ChatCommand titlesSetCommandTable[] = { - { "mask", SEC_GAMEMASTER, false, &HandleTitlesSetMaskCommand, "", NULL }, - { NULL, SEC_PLAYER, false, NULL, "", NULL } + { "mask", RBAC_PERM_COMMAND_TITLES_SET_MASK, false, &HandleTitlesSetMaskCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand titlesCommandTable[] = { - { "add", SEC_GAMEMASTER, false, &HandleTitlesAddCommand, "", NULL }, - { "current", SEC_GAMEMASTER, false, &HandleTitlesCurrentCommand, "", NULL }, - { "remove", SEC_GAMEMASTER, false, &HandleTitlesRemoveCommand, "", NULL }, - { "set", SEC_GAMEMASTER, false, NULL, "", titlesSetCommandTable }, - { NULL, SEC_PLAYER, false, NULL, "", NULL } + { "add", RBAC_PERM_COMMAND_TITLES_ADD, false, &HandleTitlesAddCommand, "", NULL }, + { "current", RBAC_PERM_COMMAND_TITLES_CURRENT, false, &HandleTitlesCurrentCommand, "", NULL }, + { "remove", RBAC_PERM_COMMAND_TITLES_REMOVE, false, &HandleTitlesRemoveCommand, "", NULL }, + { "set", RBAC_PERM_COMMAND_TITLES_SET, false, NULL, "", titlesSetCommandTable }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand commandTable[] = { - { "titles", SEC_GAMEMASTER, false, NULL, "", titlesCommandTable }, - { NULL, SEC_PLAYER, false, NULL, "", NULL } + { "titles", RBAC_PERM_COMMAND_TITLES, false, NULL, "", titlesCommandTable }, + { NULL, 0, false, NULL, "", NULL } }; return commandTable; } diff --git a/src/server/scripts/Commands/cs_wp.cpp b/src/server/scripts/Commands/cs_wp.cpp index f23255818e0..ff343a6380d 100644 --- a/src/server/scripts/Commands/cs_wp.cpp +++ b/src/server/scripts/Commands/cs_wp.cpp @@ -38,19 +38,19 @@ public: { static ChatCommand wpCommandTable[] = { - { "add", SEC_GAMEMASTER, false, &HandleWpAddCommand, "", NULL }, - { "event", SEC_GAMEMASTER, false, &HandleWpEventCommand, "", NULL }, - { "load", SEC_GAMEMASTER, false, &HandleWpLoadCommand, "", NULL }, - { "modify", SEC_GAMEMASTER, false, &HandleWpModifyCommand, "", NULL }, - { "unload", SEC_GAMEMASTER, false, &HandleWpUnLoadCommand, "", NULL }, - { "reload", SEC_ADMINISTRATOR, false, &HandleWpReloadCommand, "", NULL }, - { "show", SEC_GAMEMASTER, false, &HandleWpShowCommand, "", NULL }, - { NULL, 0, false, NULL, "", NULL } + { "add", RBAC_PERM_COMMAND_WP_ADD, false, &HandleWpAddCommand, "", NULL }, + { "event", RBAC_PERM_COMMAND_WP_EVENT, false, &HandleWpEventCommand, "", NULL }, + { "load", RBAC_PERM_COMMAND_WP_LOAD, false, &HandleWpLoadCommand, "", NULL }, + { "modify", RBAC_PERM_COMMAND_WP_MODIFY, false, &HandleWpModifyCommand, "", NULL }, + { "unload", RBAC_PERM_COMMAND_WP_UNLOAD, false, &HandleWpUnLoadCommand, "", NULL }, + { "reload", RBAC_PERM_COMMAND_WP_RELOAD, false, &HandleWpReloadCommand, "", NULL }, + { "show", RBAC_PERM_COMMAND_WP_SHOW, false, &HandleWpShowCommand, "", NULL }, + { NULL, 0, false, NULL, "", NULL } }; static ChatCommand commandTable[] = { - { "wp", SEC_GAMEMASTER, false, NULL, "", wpCommandTable }, - { NULL, 0, false, NULL, "", NULL } + { "wp", RBAC_PERM_COMMAND_WP, false, NULL, "", wpCommandTable }, + { NULL, 0, false, NULL, "", NULL } }; return commandTable; } diff --git a/src/server/scripts/EasternKingdoms/AlteracValley/boss_balinda.cpp b/src/server/scripts/EasternKingdoms/AlteracValley/boss_balinda.cpp index a1f33e57907..1b5a42a83ef 100644 --- a/src/server/scripts/EasternKingdoms/AlteracValley/boss_balinda.cpp +++ b/src/server/scripts/EasternKingdoms/AlteracValley/boss_balinda.cpp @@ -79,7 +79,7 @@ public: if (Creature* pBalinda = Unit::GetCreature(*me, balindaGUID)) if (me->GetDistance2d(pBalinda->GetHomePosition().GetPositionX(), pBalinda->GetHomePosition().GetPositionY()) > 50) EnterEvadeMode(); - resetTimer = 5 * IN_MILLISECONDS; + resetTimer = 5 * IN_MILLISECONDS; } else resetTimer -= diff; DoMeleeAttackIfReady(); diff --git a/src/server/scripts/EasternKingdoms/BaradinHold/baradin_hold.h b/src/server/scripts/EasternKingdoms/BaradinHold/baradin_hold.h index 82eaeaa4432..22df3858c43 100644 --- a/src/server/scripts/EasternKingdoms/BaradinHold/baradin_hold.h +++ b/src/server/scripts/EasternKingdoms/BaradinHold/baradin_hold.h @@ -18,6 +18,10 @@ #ifndef DEF_BARADIN_HOLD_H_ #define DEF_BARADIN_HOLD_H_ +#include "Map.h" +#include "Creature.h" +#include "ObjectMgr.h" + #define BHScriptName "instance_baradin_hold" uint32 const EncounterCount = 3; diff --git a/src/server/scripts/EasternKingdoms/BaradinHold/boss_occuthar.cpp b/src/server/scripts/EasternKingdoms/BaradinHold/boss_occuthar.cpp index 857f50b8696..e54de716d1a 100644 --- a/src/server/scripts/EasternKingdoms/BaradinHold/boss_occuthar.cpp +++ b/src/server/scripts/EasternKingdoms/BaradinHold/boss_occuthar.cpp @@ -18,6 +18,8 @@ #include "ScriptMgr.h" #include "ScriptedCreature.h" #include "Vehicle.h" +#include "SpellScript.h" +#include "SpellAuraEffects.h" #include "baradin_hold.h" enum Spells diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_razorgore.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_razorgore.cpp index be2aeb9e223..caf2719eff9 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_razorgore.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_razorgore.cpp @@ -169,7 +169,7 @@ public: { if (InstanceScript* instance = go->GetInstanceScript()) if (instance->GetData(DATA_EGG_EVENT) != DONE) - if (Creature* razor = Unit::GetCreature(*go, instance ? instance->GetData64(DATA_RAZORGORE_THE_UNTAMED) : 0)) + if (Creature* razor = Unit::GetCreature(*go, instance->GetData64(DATA_RAZORGORE_THE_UNTAMED))) { razor->Attack(player, true); player->CastSpell(razor, SPELL_MINDCONTROL); diff --git a/src/server/scripts/EasternKingdoms/CMakeLists.txt b/src/server/scripts/EasternKingdoms/CMakeLists.txt index 7bdcaf56523..73c8fb5cf5c 100644 --- a/src/server/scripts/EasternKingdoms/CMakeLists.txt +++ b/src/server/scripts/EasternKingdoms/CMakeLists.txt @@ -206,6 +206,7 @@ set(scripts_STAT_SRCS EasternKingdoms/Karazhan/boss_moroes.cpp EasternKingdoms/Karazhan/boss_terestian_illhoof.cpp EasternKingdoms/Karazhan/karazhan.h + EasternKingdoms/TheStockade/instance_the_stockade.cpp ) message(" -> Prepared: Eastern Kingdoms") diff --git a/src/server/scripts/EasternKingdoms/Karazhan/boss_moroes.cpp b/src/server/scripts/EasternKingdoms/Karazhan/boss_moroes.cpp index 473fe000939..780f781f58d 100644 --- a/src/server/scripts/EasternKingdoms/Karazhan/boss_moroes.cpp +++ b/src/server/scripts/EasternKingdoms/Karazhan/boss_moroes.cpp @@ -73,14 +73,12 @@ enum Spells SPELL_SHIELDWALL = 29390 }; -#define POS_Z 81.73f - -float Locations[4][3]= +Position const Locations[4] = { - {-10991.0f, -1884.33f, 0.614315f}, - {-10989.4f, -1885.88f, 0.904913f}, - {-10978.1f, -1887.07f, 2.035550f}, - {-10975.9f, -1885.81f, 2.253890f}, + {-10991.0f, -1884.33f, 81.73f, 0.614315f}, + {-10989.4f, -1885.88f, 81.73f, 0.904913f}, + {-10978.1f, -1887.07f, 81.73f, 2.035550f}, + {-10975.9f, -1885.81f, 81.73f, 2.253890f}, }; const uint32 Adds[6]= @@ -137,7 +135,7 @@ public: Enrage = false; InVanish = false; - if (me->GetHealth()) + if (me->IsAlive()) SpawnAdds(); if (instance) @@ -183,39 +181,34 @@ public: void SpawnAdds() { DeSpawnAdds(); + if (isAddlistEmpty()) { - Creature* creature = NULL; - std::vector<uint32> AddList; + std::list<uint32> AddList; for (uint8 i = 0; i < 6; ++i) AddList.push_back(Adds[i]); - while (AddList.size() > 4) - AddList.erase((AddList.begin())+(rand()%AddList.size())); + Trinity::Containers::RandomResizeList(AddList, 4); uint8 i = 0; - for (std::vector<uint32>::const_iterator itr = AddList.begin(); itr != AddList.end(); ++itr) + for (std::list<uint32>::const_iterator itr = AddList.begin(); itr != AddList.end() && i < 4; ++itr, ++i) { uint32 entry = *itr; - creature = me->SummonCreature(entry, Locations[i][0], Locations[i][1], POS_Z, Locations[i][2], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000); - if (creature) + if (Creature* creature = me->SummonCreature(entry, Locations[i], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000)) { AddGUID[i] = creature->GetGUID(); AddId[i] = entry; } - ++i; } - }else + } + else { for (uint8 i = 0; i < 4; ++i) { - Creature* creature = me->SummonCreature(AddId[i], Locations[i][0], Locations[i][1], POS_Z, Locations[i][2], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000); - if (creature) - { + if (Creature* creature = me->SummonCreature(AddId[i], Locations[i], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000)) AddGUID[i] = creature->GetGUID(); - } } } } @@ -235,9 +228,8 @@ public: { if (AddGUID[i]) { - Creature* temp = Creature::GetCreature((*me), AddGUID[i]); - if (temp && temp->IsAlive()) - temp->DisappearAndDie(); + if (Creature* temp = ObjectAccessor::GetCreature(*me, AddGUID[i])) + temp->DespawnOrUnsummon(); } } } diff --git a/src/server/scripts/EasternKingdoms/Karazhan/boss_prince_malchezaar.cpp b/src/server/scripts/EasternKingdoms/Karazhan/boss_prince_malchezaar.cpp index 2abfcead826..8f292f2d008 100644 --- a/src/server/scripts/EasternKingdoms/Karazhan/boss_prince_malchezaar.cpp +++ b/src/server/scripts/EasternKingdoms/Karazhan/boss_prince_malchezaar.cpp @@ -364,24 +364,22 @@ public: me->GetRandomNearPosition(pos, 60); else { - std::vector<InfernalPoint*>::iterator itr = positions.begin()+rand()%positions.size(); - point = *itr; - positions.erase(itr); - pos.Relocate(point->x, point->y, INFERNAL_Z); + point = Trinity::Containers::SelectRandomContainerElement(positions); + pos.Relocate(point->x, point->y, INFERNAL_Z, frand(0.0f, float(M_PI * 2))); } - Creature* Infernal = me->SummonCreature(NETHERSPITE_INFERNAL, pos, TEMPSUMMON_TIMED_DESPAWN, 180000); + Creature* infernal = me->SummonCreature(NETHERSPITE_INFERNAL, pos, TEMPSUMMON_TIMED_DESPAWN, 180000); - if (Infernal) + if (infernal) { - Infernal->SetDisplayId(INFERNAL_MODEL_INVISIBLE); - Infernal->setFaction(me->getFaction()); + infernal->SetDisplayId(INFERNAL_MODEL_INVISIBLE); + infernal->setFaction(me->getFaction()); if (point) - CAST_AI(netherspite_infernal::netherspite_infernalAI, Infernal->AI())->point=point; - CAST_AI(netherspite_infernal::netherspite_infernalAI, Infernal->AI())->malchezaar=me->GetGUID(); + CAST_AI(netherspite_infernal::netherspite_infernalAI, infernal->AI())->point=point; + CAST_AI(netherspite_infernal::netherspite_infernalAI, infernal->AI())->malchezaar=me->GetGUID(); - infernals.push_back(Infernal->GetGUID()); - DoCast(Infernal, SPELL_INFERNAL_RELAY); + infernals.push_back(infernal->GetGUID()); + DoCast(infernal, SPELL_INFERNAL_RELAY); } Talk(SAY_SUMMON); diff --git a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp index f49432853fb..3cdefb70617 100644 --- a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp +++ b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp @@ -143,7 +143,7 @@ public: wait_timer = 5000; me->CastSpell(me, SPELL_DK_INITIATE_VISUAL, true); - if (Player* starter = Unit::GetPlayer(*me, playerGUID)) + if (Player* starter = ObjectAccessor::GetPlayer(*me, playerGUID)) sCreatureTextMgr->SendChat(me, SAY_EVENT_ATTACK, 0, CHAT_MSG_ADDON, LANG_ADDON, TEXT_RANGE_NORMAL, 0, TEAM_OTHER, false, starter); phase = PHASE_TO_ATTACK; @@ -228,8 +228,8 @@ public: me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); phase = PHASE_ATTACKING; - if (Player* target = Unit::GetPlayer(*me, playerGUID)) - me->AI()->AttackStart(target); + if (Player* target = ObjectAccessor::GetPlayer(*me, playerGUID)) + AttackStart(target); wait_timer = 0; } } @@ -505,93 +505,89 @@ public: ## npc_dark_rider_of_acherus ######*/ -enum Spells_DR +enum DarkRiderOfAcherus { + SAY_DARK_RIDER = 0, SPELL_DESPAWN_HORSE = 51918 }; -enum Says_DR -{ - SAY_DARK_RIDER = 0 -}; - class npc_dark_rider_of_acherus : public CreatureScript { -public: - npc_dark_rider_of_acherus() : CreatureScript("npc_dark_rider_of_acherus") { } - - CreatureAI* GetAI(Creature* creature) const OVERRIDE - { - return new npc_dark_rider_of_acherusAI(creature); - } - - struct npc_dark_rider_of_acherusAI : public ScriptedAI - { - npc_dark_rider_of_acherusAI(Creature* creature) : ScriptedAI(creature) {} - - uint32 PhaseTimer; - uint32 Phase; - bool Intro; - uint64 TargetGUID; + public: + npc_dark_rider_of_acherus() : CreatureScript("npc_dark_rider_of_acherus") { } - void Reset() OVERRIDE + struct npc_dark_rider_of_acherusAI : public ScriptedAI { - PhaseTimer = 4000; - Phase = 0; - Intro = false; - TargetGUID = 0; - } + npc_dark_rider_of_acherusAI(Creature* creature) : ScriptedAI(creature) { } - void UpdateAI(uint32 diff) OVERRIDE - { - if (!Intro || !TargetGUID) - return; + void Reset() OVERRIDE + { + PhaseTimer = 4000; + Phase = 0; + Intro = false; + TargetGUID = 0; + } - if (PhaseTimer <= diff) + void UpdateAI(uint32 diff) OVERRIDE { - switch (Phase) + if (!Intro || !TargetGUID) + return; + + if (PhaseTimer <= diff) { - case 0: - me->MonsterSay(SAY_DARK_RIDER, LANG_UNIVERSAL, 0); - PhaseTimer = 5000; - Phase = 1; - break; - case 1: - if (Unit* target = Unit::GetUnit(*me, TargetGUID)) - DoCast(target, SPELL_DESPAWN_HORSE, true); - PhaseTimer = 3000; - Phase = 2; - break; - case 2: - me->SetVisible(false); - PhaseTimer = 2000; - Phase = 3; - break; - case 3: - me->DespawnOrUnsummon(); - break; - default: - break; + switch (Phase) + { + case 0: + Talk(SAY_DARK_RIDER); + PhaseTimer = 5000; + Phase = 1; + break; + case 1: + if (Unit* target = ObjectAccessor::GetUnit(*me, TargetGUID)) + DoCast(target, SPELL_DESPAWN_HORSE, true); + PhaseTimer = 3000; + Phase = 2; + break; + case 2: + me->SetVisible(false); + PhaseTimer = 2000; + Phase = 3; + break; + case 3: + me->DespawnOrUnsummon(); + break; + default: + break; + } } - } else PhaseTimer -= diff; - - } + else + PhaseTimer -= diff; + } - void InitDespawnHorse(Unit* who) - { - if (!who) - return; + void InitDespawnHorse(Unit* who) + { + if (!who) + return; - TargetGUID = who->GetGUID(); - me->SetWalk(true); - me->SetSpeed(MOVE_RUN, 0.4f); - me->GetMotionMaster()->MoveChase(who); - me->SetTarget(TargetGUID); - Intro = true; - } + TargetGUID = who->GetGUID(); + me->SetWalk(true); + me->SetSpeed(MOVE_RUN, 0.4f); + me->GetMotionMaster()->MoveChase(who); + me->SetTarget(TargetGUID); + Intro = true; + } - }; + private: + uint32 PhaseTimer; + uint32 Phase; + bool Intro; + uint64 TargetGUID; + }; + CreatureAI* GetAI(Creature* creature) const OVERRIDE + { + return new npc_dark_rider_of_acherusAI(creature); + } }; /*###### @@ -644,7 +640,6 @@ public: } void MoveInLineOfSight(Unit* who) OVERRIDE - { ScriptedAI::MoveInLineOfSight(who); diff --git a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter2.cpp b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter2.cpp index 44eef7602c8..ba6f0f23656 100644 --- a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter2.cpp +++ b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter2.cpp @@ -96,7 +96,7 @@ public: { if (speechTimer <= diff) { - Player* player = Unit::GetPlayer(*me, playerGUID); + Player* player = ObjectAccessor::GetPlayer(*me, playerGUID); if (!player) { EnterEvadeMode(); @@ -683,7 +683,7 @@ public: { if (ExecuteSpeech_Timer <= diff) { - Player* player = Unit::GetPlayer(*me, PlayerGUID); + Player* player = ObjectAccessor::GetPlayer(*me, PlayerGUID); if (!player) { diff --git a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter5.cpp b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter5.cpp index 382a0002065..ab1367ed684 100644 --- a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter5.cpp +++ b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter5.cpp @@ -311,6 +311,23 @@ public: { npc_highlord_darion_mograineAI(Creature* creature) : npc_escortAI(creature) { + uiTirionGUID = 0; + uiKorfaxGUID = 0; + uiMaxwellGUID = 0; + uiEligorGUID = 0; + uiRayneGUID = 0; + uiKoltiraGUID = 0; + uiOrbazGUID = 0; + uiThassarianGUID = 0; + uiLichKingGUID = 0; + + memset(uiDefenderGUID, 0, sizeof(uiDefenderGUID)); + memset(uiEarthshatterGUID, 0, sizeof(uiEarthshatterGUID)); + memset(uiAbominationGUID, 0, sizeof(uiAbominationGUID)); + memset(uiBehemothGUID, 0, sizeof(uiBehemothGUID)); + memset(uiGhoulGUID, 0, sizeof(uiGhoulGUID)); + memset(uiWarriorGUID, 0, sizeof(uiWarriorGUID)); + Reset(); } diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_eredar_twins.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_eredar_twins.cpp index 0e58cb85c4b..d402eccedd4 100644 --- a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_eredar_twins.cpp +++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_eredar_twins.cpp @@ -473,6 +473,7 @@ public: { case SPELL_BLAZE: target->CastSpell(target, SPELL_BLAZE_SUMMON, true); + break; case SPELL_CONFLAGRATION: case SPELL_FLAME_SEAR: HandleTouchedSpells(target, SPELL_FLAME_TOUCHED); diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_muru.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_muru.cpp index aa53790ee5f..c3d00ddba53 100644 --- a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_muru.cpp +++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_muru.cpp @@ -410,7 +410,7 @@ public: void JustSummoned(Creature* summoned) OVERRIDE { if (instance) - if (Player* Target = Unit::GetPlayer(*me, instance->GetData64(DATA_PLAYER_GUID))) + if (Player* Target = ObjectAccessor::GetPlayer(*me, instance->GetData64(DATA_PLAYER_GUID))) summoned->AI()->AttackStart(Target); Summons.Summon(summoned); diff --git a/src/server/scripts/EasternKingdoms/TheStockade/instance_the_stockade.cpp b/src/server/scripts/EasternKingdoms/TheStockade/instance_the_stockade.cpp new file mode 100644 index 00000000000..9550ac13208 --- /dev/null +++ b/src/server/scripts/EasternKingdoms/TheStockade/instance_the_stockade.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2008-2013 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/>. + */ + +/* +This placeholder for the instance is needed for dungeon finding to be able +to give credit after the boss defined in lastEncounterDungeon is killed. +Without it, the party doing random dungeon won't get satchel of spoils and +gets instead the deserter debuff. +*/ + +#include "ScriptMgr.h" +#include "InstanceScript.h" + +class instance_the_stockade : public InstanceMapScript +{ +public: + instance_the_stockade() : InstanceMapScript("instance_the_stockade", 34) { } + + InstanceScript* GetInstanceScript(InstanceMap* map) const OVERRIDE + { + return new instance_the_stockade_InstanceMapScript(map); + } + + struct instance_the_stockade_InstanceMapScript : public InstanceScript + { + instance_the_stockade_InstanceMapScript(Map* map) : InstanceScript(map) {} + }; +}; + +void AddSC_instance_the_stockade() +{ + new instance_the_stockade(); +} diff --git a/src/server/scripts/EasternKingdoms/zone_eversong_woods.cpp b/src/server/scripts/EasternKingdoms/zone_eversong_woods.cpp index d8750a82bc4..5381b19ebf3 100644 --- a/src/server/scripts/EasternKingdoms/zone_eversong_woods.cpp +++ b/src/server/scripts/EasternKingdoms/zone_eversong_woods.cpp @@ -98,14 +98,14 @@ public: void JustDied(Unit* /*killer*/) OVERRIDE { if (PlayerGUID) - if (Player* player = Unit::GetPlayer(*me, PlayerGUID)) + if (Player* player = ObjectAccessor::GetPlayer(*me, PlayerGUID)) player->FailQuest(QUEST_UNEXPECTED_RESULT); } void UpdateAI(uint32 /*diff*/) OVERRIDE { if (KillCount >= 3 && PlayerGUID) - if (Player* player = Unit::GetPlayer(*me, PlayerGUID)) + if (Player* player = ObjectAccessor::GetPlayer(*me, PlayerGUID)) player->CompleteQuest(QUEST_UNEXPECTED_RESULT); if (Summon) @@ -207,7 +207,7 @@ public: void JustDied(Unit* /*killer*/) OVERRIDE { if (PlayerGUID && !Completed) - if (Player* player = Unit::GetPlayer(*me, PlayerGUID)) + if (Player* player = ObjectAccessor::GetPlayer(*me, PlayerGUID)) player->FailQuest(QUEST_POWERING_OUR_DEFENSES); } @@ -218,7 +218,7 @@ public: Talk(EMOTE); Completed = true; if (PlayerGUID) - if (Player* player = Unit::GetPlayer(*me, PlayerGUID)) + if (Player* player = ObjectAccessor::GetPlayer(*me, PlayerGUID)) player->CompleteQuest(QUEST_POWERING_OUR_DEFENSES); me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); diff --git a/src/server/scripts/EasternKingdoms/zone_isle_of_queldanas.cpp b/src/server/scripts/EasternKingdoms/zone_isle_of_queldanas.cpp index c5272ba01f6..8cfd3c45338 100644 --- a/src/server/scripts/EasternKingdoms/zone_isle_of_queldanas.cpp +++ b/src/server/scripts/EasternKingdoms/zone_isle_of_queldanas.cpp @@ -112,32 +112,22 @@ public: { npc_greengill_slaveAI(Creature* creature) : ScriptedAI(creature) {} - uint64 PlayerGUID; + void EnterCombat(Unit* /*who*/) OVERRIDE { } - void EnterCombat(Unit* /*who*/)OVERRIDE {} - - void Reset() OVERRIDE - { - PlayerGUID = 0; - } - - void SpellHit(Unit* caster, const SpellInfo* spell) OVERRIDE + void SpellHit(Unit* caster, SpellInfo const* spellInfo) OVERRIDE { - if (!caster) + Player* player = caster->ToPlayer(); + if (!player) return; - if (caster->GetTypeId() == TYPEID_PLAYER && spell->Id == ORB && !me->HasAura(ENRAGE)) + if (spellInfo->Id == ORB && !me->HasAura(ENRAGE)) { - PlayerGUID = caster->GetGUID(); - if (PlayerGUID) - { - Player* player = Unit::GetPlayer(*me, PlayerGUID); - if (player && player->GetQuestStatus(QUESTG) == QUEST_STATUS_INCOMPLETE) - DoCast(player, 45110, true); - } + if (player->GetQuestStatus(QUESTG) == QUEST_STATUS_INCOMPLETE) + DoCast(player, 45110, true); + DoCast(me, ENRAGE); - Unit* Myrmidon = me->FindNearestCreature(DM, 70); - if (Myrmidon) + + if (Creature* Myrmidon = me->FindNearestCreature(DM, 70)) { me->AddThreat(Myrmidon, 100000.0f); AttackStart(Myrmidon); diff --git a/src/server/scripts/EasternKingdoms/zone_tirisfal_glades.cpp b/src/server/scripts/EasternKingdoms/zone_tirisfal_glades.cpp index 903c88ad89a..f07f12710d6 100644 --- a/src/server/scripts/EasternKingdoms/zone_tirisfal_glades.cpp +++ b/src/server/scripts/EasternKingdoms/zone_tirisfal_glades.cpp @@ -1,6 +1,5 @@ /* * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/> * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the diff --git a/src/server/scripts/EasternKingdoms/zone_western_plaguelands.cpp b/src/server/scripts/EasternKingdoms/zone_western_plaguelands.cpp index 4057f4070b1..8937e896faf 100644 --- a/src/server/scripts/EasternKingdoms/zone_western_plaguelands.cpp +++ b/src/server/scripts/EasternKingdoms/zone_western_plaguelands.cpp @@ -361,13 +361,12 @@ public: break; case 15: Talk(SAY_WP_2); + break; case 21: Theldanis = GetClosestCreatureWithEntry(me, NPC_THEL_DANIS, 150); if (Theldanis) Theldanis->AI()->Talk(SAY_WP_3); break; - case 22: - break; case 23: Ughost = me->SummonCreature(NPC_GHOST_UTHER, 971.86f, -1825.42f, 81.99f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); if (Ughost) diff --git a/src/server/scripts/Events/childrens_week.cpp b/src/server/scripts/Events/childrens_week.cpp index 25bc683edcf..a72e8cc6812 100644 --- a/src/server/scripts/Events/childrens_week.cpp +++ b/src/server/scripts/Events/childrens_week.cpp @@ -181,8 +181,8 @@ class npc_winterfin_playmate : public CreatureScript if (timer <= diff) { - Player* player = Player::GetPlayer(*me, playerGUID); - Creature* orphan = Creature::GetCreature(*me, orphanGUID); + Player* player = ObjectAccessor::GetPlayer(*me, playerGUID); + Creature* orphan = ObjectAccessor::GetCreature(*me, orphanGUID); if (!orphan || !player) { @@ -280,8 +280,8 @@ class npc_snowfall_glade_playmate : public CreatureScript if (timer <= diff) { - Player* player = Player::GetPlayer(*me, playerGUID); - Creature* orphan = Creature::GetCreature(*me, orphanGUID); + Player* player = ObjectAccessor::GetPlayer(*me, playerGUID); + Creature* orphan = ObjectAccessor::GetCreature(*me, orphanGUID); if (!orphan || !player) { @@ -381,8 +381,8 @@ class npc_the_biggest_tree : public CreatureScript if (timer <= diff) { - Player* player = Player::GetPlayer(*me, playerGUID); - Creature* orphan = Creature::GetCreature(*me, orphanGUID); + Player* player = ObjectAccessor::GetPlayer(*me, playerGUID); + Creature* orphan = ObjectAccessor::GetCreature(*me, orphanGUID); if (!orphan || !player) { @@ -468,8 +468,8 @@ class npc_high_oracle_soo_roo : public CreatureScript if (timer <= diff) { - Player* player = Player::GetPlayer(*me, playerGUID); - Creature* orphan = Creature::GetCreature(*me, orphanGUID); + Player* player = ObjectAccessor::GetPlayer(*me, playerGUID); + Creature* orphan = ObjectAccessor::GetCreature(*me, orphanGUID); if (!orphan || !player) { @@ -557,8 +557,8 @@ class npc_elder_kekek : public CreatureScript if (timer <= diff) { - Player* player = Player::GetPlayer(*me, playerGUID); - Creature* orphan = Creature::GetCreature(*me, orphanGUID); + Player* player = ObjectAccessor::GetPlayer(*me, playerGUID); + Creature* orphan = ObjectAccessor::GetCreature(*me, orphanGUID); if (!player || !orphan) { @@ -646,8 +646,8 @@ class npc_the_etymidian : public CreatureScript if (timer <= diff) { - Player* player = Player::GetPlayer(*me, playerGUID); - Creature* orphan = Creature::GetCreature(*me, orphanGUID); + Player* player = ObjectAccessor::GetPlayer(*me, playerGUID); + Creature* orphan = ObjectAccessor::GetCreature(*me, orphanGUID); if (!orphan || !player) { @@ -768,8 +768,8 @@ class npc_alexstraza_the_lifebinder : public CreatureScript if (timer <= diff) { - Player* player = Player::GetPlayer(*me, playerGUID); - Creature* orphan = Creature::GetCreature(*me, orphanGUID); + Player* player = ObjectAccessor::GetPlayer(*me, playerGUID); + Creature* orphan = ObjectAccessor::GetCreature(*me, orphanGUID); if (!orphan || !player) { diff --git a/src/server/scripts/Kalimdor/CMakeLists.txt b/src/server/scripts/Kalimdor/CMakeLists.txt index 67082631c4e..b21c20d3d5a 100644 --- a/src/server/scripts/Kalimdor/CMakeLists.txt +++ b/src/server/scripts/Kalimdor/CMakeLists.txt @@ -67,6 +67,7 @@ set(scripts_STAT_SRCS Kalimdor/Maraudon/boss_landslide.cpp Kalimdor/Maraudon/boss_celebras_the_cursed.cpp Kalimdor/Maraudon/boss_noxxion.cpp + Kalimdor/Maraudon/instance_maraudon.cpp Kalimdor/TempleOfAhnQiraj/boss_fankriss.cpp Kalimdor/TempleOfAhnQiraj/boss_huhuran.cpp Kalimdor/TempleOfAhnQiraj/instance_temple_of_ahnqiraj.cpp @@ -112,6 +113,8 @@ set(scripts_STAT_SRCS Kalimdor/OnyxiasLair/boss_onyxia.cpp Kalimdor/OnyxiasLair/onyxias_lair.h Kalimdor/OnyxiasLair/instance_onyxias_lair.cpp + Kalimdor/RagefireChasm/instance_ragefire_chasm.cpp + Kalimdor/DireMaul/instance_dire_maul.cpp Kalimdor/HallsOfOrigination/halls_of_origination.h Kalimdor/HallsOfOrigination/instance_halls_of_origination.cpp Kalimdor/HallsOfOrigination/boss_temple_guardian_anhuur.cpp diff --git a/src/server/scripts/Kalimdor/DireMaul/instance_dire_maul.cpp b/src/server/scripts/Kalimdor/DireMaul/instance_dire_maul.cpp new file mode 100644 index 00000000000..a478d7aea25 --- /dev/null +++ b/src/server/scripts/Kalimdor/DireMaul/instance_dire_maul.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2008-2013 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/>. + */ + +/* +This placeholder for the instance is needed for dungeon finding to be able +to give credit after the boss defined in lastEncounterDungeon is killed. +Without it, the party doing random dungeon won't get satchel of spoils and +gets instead the deserter debuff. +*/ + +#include "ScriptMgr.h" +#include "InstanceScript.h" + +class instance_dire_maul : public InstanceMapScript +{ +public: + instance_dire_maul() : InstanceMapScript("instance_dire_maul", 429) { } + + InstanceScript* GetInstanceScript(InstanceMap* map) const OVERRIDE + { + return new instance_dire_maul_InstanceMapScript(map); + } + + struct instance_dire_maul_InstanceMapScript : public InstanceScript + { + instance_dire_maul_InstanceMapScript(Map* map) : InstanceScript(map) {} + }; +}; + +void AddSC_instance_dire_maul() +{ + new instance_dire_maul(); +} diff --git a/src/server/scripts/Kalimdor/Maraudon/instance_maraudon.cpp b/src/server/scripts/Kalimdor/Maraudon/instance_maraudon.cpp new file mode 100644 index 00000000000..a44f4078a9b --- /dev/null +++ b/src/server/scripts/Kalimdor/Maraudon/instance_maraudon.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2008-2013 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/>. + */ + +/* +This placeholder for the instance is needed for dungeon finding to be able +to give credit after the boss defined in lastEncounterDungeon is killed. +Without it, the party doing random dungeon won't get satchel of spoils and +gets instead the deserter debuff. +*/ + +#include "ScriptMgr.h" +#include "InstanceScript.h" + +class instance_maraudon : public InstanceMapScript +{ +public: + instance_maraudon() : InstanceMapScript("instance_maraudon", 349) { } + + InstanceScript* GetInstanceScript(InstanceMap* map) const OVERRIDE + { + return new instance_maraudon_InstanceMapScript(map); + } + + struct instance_maraudon_InstanceMapScript : public InstanceScript + { + instance_maraudon_InstanceMapScript(Map* map) : InstanceScript(map) {} + }; +}; + +void AddSC_instance_maraudon() +{ + new instance_maraudon(); +} diff --git a/src/server/scripts/Kalimdor/RagefireChasm/instance_ragefire_chasm.cpp b/src/server/scripts/Kalimdor/RagefireChasm/instance_ragefire_chasm.cpp new file mode 100644 index 00000000000..6b13fecb26a --- /dev/null +++ b/src/server/scripts/Kalimdor/RagefireChasm/instance_ragefire_chasm.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2008-2013 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/>. + */ + +/* +This placeholder for the instance is needed for dungeon finding to be able +to give credit after the boss defined in lastEncounterDungeon is killed. +Without it, the party doing random dungeon won't get satchel of spoils and +gets instead the deserter debuff. +*/ + +#include "ScriptMgr.h" +#include "InstanceScript.h" + +class instance_ragefire_chasm : public InstanceMapScript +{ +public: + instance_ragefire_chasm() : InstanceMapScript("instance_ragefire_chasm", 389) { } + + InstanceScript* GetInstanceScript(InstanceMap* map) const OVERRIDE + { + return new instance_ragefire_chasm_InstanceMapScript(map); + } + + struct instance_ragefire_chasm_InstanceMapScript : public InstanceScript + { + instance_ragefire_chasm_InstanceMapScript(Map* map) : InstanceScript(map) {} + }; +}; + +void AddSC_instance_ragefire_chasm() +{ + new instance_ragefire_chasm(); +} diff --git a/src/server/scripts/Kalimdor/ZulFarrak/zulfarrak.cpp b/src/server/scripts/Kalimdor/ZulFarrak/zulfarrak.cpp index c8d83a54e1e..a2f98b21589 100644 --- a/src/server/scripts/Kalimdor/ZulFarrak/zulfarrak.cpp +++ b/src/server/scripts/Kalimdor/ZulFarrak/zulfarrak.cpp @@ -145,7 +145,7 @@ public: break; case 3: me->setFaction(FACTION_HOSTILE); - if (Player* target = Player::GetPlayer(*me, PlayerGUID)) + if (Player* target = ObjectAccessor::GetPlayer(*me, PlayerGUID)) AttackStart(target); if (instance) diff --git a/src/server/scripts/Kalimdor/zone_azshara.cpp b/src/server/scripts/Kalimdor/zone_azshara.cpp index a44568e0472..9896807776e 100644 --- a/src/server/scripts/Kalimdor/zone_azshara.cpp +++ b/src/server/scripts/Kalimdor/zone_azshara.cpp @@ -1,6 +1,5 @@ /* * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/> * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the diff --git a/src/server/scripts/Kalimdor/zone_azuremyst_isle.cpp b/src/server/scripts/Kalimdor/zone_azuremyst_isle.cpp index cb3b8d6d01a..79e0755a40a 100644 --- a/src/server/scripts/Kalimdor/zone_azuremyst_isle.cpp +++ b/src/server/scripts/Kalimdor/zone_azuremyst_isle.cpp @@ -133,7 +133,7 @@ public: { me->RemoveAurasDueToSpell(SPELL_IRRIDATION); - if (Player* player = Unit::GetPlayer(*me, pCaster)) + if (Player* player = ObjectAccessor::GetPlayer(*me, pCaster)) { Talk(SAY_HEAL, player->GetGUID()); diff --git a/src/server/scripts/Kalimdor/zone_bloodmyst_isle.cpp b/src/server/scripts/Kalimdor/zone_bloodmyst_isle.cpp index ab74a76a440..8ee1de1c8d5 100644 --- a/src/server/scripts/Kalimdor/zone_bloodmyst_isle.cpp +++ b/src/server/scripts/Kalimdor/zone_bloodmyst_isle.cpp @@ -172,7 +172,7 @@ public: if (Creature* stillpine = go->FindNearestCreature(NPC_PRINCESS_STILLPINE, 25, true)) { stillpine->GetMotionMaster()->MovePoint(1, go->GetPositionX(), go->GetPositionY()-15, go->GetPositionZ()); - player->CastedCreatureOrGO(NPC_PRINCESS_STILLPINE, 0, SPELL_OPENING_PRINCESS_STILLPINE_CREDIT); + player->KilledMonsterCredit(NPC_PRINCESS_STILLPINE, stillpine->GetGUID()); } return true; } diff --git a/src/server/scripts/Kalimdor/zone_mulgore.cpp b/src/server/scripts/Kalimdor/zone_mulgore.cpp index 217c8e43382..75bb2e9dbab 100644 --- a/src/server/scripts/Kalimdor/zone_mulgore.cpp +++ b/src/server/scripts/Kalimdor/zone_mulgore.cpp @@ -161,7 +161,7 @@ public: switch (EventPhase) { case 1: - if (Unit* unit = Unit::GetUnit(*me, PlayerGUID)) + if (Unit* unit = ObjectAccessor::GetUnit(*me, PlayerGUID)) { if (GameObject* go = unit->GetGameObject(SPELL_LUNCH)) { @@ -175,7 +175,7 @@ public: me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_USE_STANDING); break; case 3: - if (Player* unit = Unit::GetPlayer(*me, PlayerGUID)) + if (Player* unit = ObjectAccessor::GetPlayer(*me, PlayerGUID)) unit->TalkedToCreature(me->GetEntry(), me->GetGUID()); me->UpdateEntry(NPC_KYLE_FRIENDLY); diff --git a/src/server/scripts/Kalimdor/zone_orgrimmar.cpp b/src/server/scripts/Kalimdor/zone_orgrimmar.cpp index ccc8bdc257a..8cf84de20ec 100644 --- a/src/server/scripts/Kalimdor/zone_orgrimmar.cpp +++ b/src/server/scripts/Kalimdor/zone_orgrimmar.cpp @@ -1,6 +1,5 @@ /* * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/> * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -16,16 +15,6 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -/* ScriptData -SDName: Orgrimmar -SD%Complete: 0 -SDComment: Quest support: -SDCategory: Orgrimmar -EndScriptData */ - -/* ContentData -EndContentData */ - #include "ScriptMgr.h" #include "ScriptedCreature.h" #include "ScriptedGossip.h" diff --git a/src/server/scripts/Kalimdor/zone_silithus.cpp b/src/server/scripts/Kalimdor/zone_silithus.cpp index 8120686a0aa..80ca6975316 100644 --- a/src/server/scripts/Kalimdor/zone_silithus.cpp +++ b/src/server/scripts/Kalimdor/zone_silithus.cpp @@ -526,7 +526,7 @@ public: void HandleAnimation() { - Player* player = Unit::GetPlayer(*me, PlayerGUID); + Player* player = ObjectAccessor::GetPlayer(*me, PlayerGUID); if (!player) return; @@ -1002,14 +1002,13 @@ public: void CheckEventFail() { - Player* player = Unit::GetPlayer(*me, PlayerGUID); - + Player* player = ObjectAccessor::GetPlayer(*me, PlayerGUID); if (!player) return; if (Group* EventGroup = player->GetGroup()) { - Player* groupMember; + Player* groupMember = NULL; uint8 GroupMemberCount = 0; uint8 DeadMemberCount = 0; @@ -1019,7 +1018,7 @@ public: for (Group::member_citerator itr = members.begin(); itr!= members.end(); ++itr) { - groupMember = (Unit::GetPlayer(*me, itr->guid)); + groupMember = ObjectAccessor::GetPlayer(*me, itr->guid); if (!groupMember) continue; if (!groupMember->IsWithinDistInMap(me, EVENT_AREA_RADIUS) && groupMember->GetQuestStatus(QUEST_A_PAWN_ON_THE_ETERNAL_BOARD) == QUEST_STATUS_INCOMPLETE) diff --git a/src/server/scripts/Kalimdor/zone_the_barrens.cpp b/src/server/scripts/Kalimdor/zone_the_barrens.cpp index 79299d1b03c..c991f760605 100644 --- a/src/server/scripts/Kalimdor/zone_the_barrens.cpp +++ b/src/server/scripts/Kalimdor/zone_the_barrens.cpp @@ -361,18 +361,20 @@ public: void UpdateAI(uint32 diff) OVERRIDE { - if (EventInProgress) { - Player* pWarrior = NULL; + if (EventInProgress) + { + Player* warrior = NULL; if (PlayerGUID) - pWarrior = Unit::GetPlayer(*me, PlayerGUID); + warrior = ObjectAccessor::GetPlayer(*me, PlayerGUID); - if (!pWarrior) + if (!warrior) return; - if (!pWarrior->IsAlive() && pWarrior->GetQuestStatus(1719) == QUEST_STATUS_INCOMPLETE) { + if (!warrior->IsAlive() && warrior->GetQuestStatus(1719) == QUEST_STATUS_INCOMPLETE) + { Talk(SAY_TWIGGY_FLATHEAD_DOWN); - pWarrior->FailQuest(1719); + warrior->FailQuest(1719); for (uint8 i = 0; i < 6; ++i) // unsummon challengers { @@ -396,11 +398,12 @@ public: if (!EventGrate && EventInProgress) { float x, y, z; - pWarrior->GetPosition(x, y, z); + warrior->GetPosition(x, y, z); - if (x >= -1684 && x <= -1674 && y >= -4334 && y <= -4324) { - pWarrior->AreaExploredOrEventHappens(1719); - Talk(SAY_TWIGGY_FLATHEAD_BEGIN, pWarrior->GetGUID()); + if (x >= -1684 && x <= -1674 && y >= -4334 && y <= -4324) + { + warrior->AreaExploredOrEventHappens(1719); + Talk(SAY_TWIGGY_FLATHEAD_BEGIN, warrior->GetGUID()); for (uint8 i = 0; i < 6; ++i) { @@ -442,19 +445,20 @@ public: if (Wave < 6 && AffrayChallenger[Wave] && !EventBigWill) { Talk(SAY_TWIGGY_FLATHEAD_FRAY); - Creature* creature = Unit::GetCreature((*me), AffrayChallenger[Wave]); + Creature* creature = ObjectAccessor::GetCreature(*me, AffrayChallenger[Wave]); if (creature && (creature->IsAlive())) { creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); creature->HandleEmoteCommand(EMOTE_ONESHOT_ROAR); creature->setFaction(14); - creature->AI()->AttackStart(pWarrior); + creature->AI()->AttackStart(warrior); ++Wave; WaveTimer = 20000; } } - else if (Wave >= 6 && !EventBigWill) { + else if (Wave >= 6 && !EventBigWill) + { if (Creature* creature = me->SummonCreature(NPC_BIG_WILL, -1722, -4341, 6.12f, 6.26f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 480000)) { BigWill = creature->GetGUID(); @@ -468,7 +472,7 @@ public: } else if (Wave >= 6 && EventBigWill && BigWill) { - Creature* creature = Unit::GetCreature((*me), BigWill); + Creature* creature = ObjectAccessor::GetCreature(*me, BigWill); if (!creature || !creature->IsAlive()) { Talk(SAY_TWIGGY_FLATHEAD_OVER); diff --git a/src/server/scripts/Kalimdor/zone_winterspring.cpp b/src/server/scripts/Kalimdor/zone_winterspring.cpp index e517afe6b46..92d15322f4c 100644 --- a/src/server/scripts/Kalimdor/zone_winterspring.cpp +++ b/src/server/scripts/Kalimdor/zone_winterspring.cpp @@ -158,8 +158,7 @@ public: DialogueHelper(DialogueEntry const* dialogueArray) : _dialogueArray(dialogueArray), _currentEntry(NULL), - _actionTimer(0), - _isFirstSide(true) + _actionTimer(0) {} // The array MUST be terminated by {0, 0, 0, 0, 0} @@ -237,7 +236,6 @@ private: DialogueEntry const* _currentEntry; uint32 _actionTimer; - bool _isFirstSide; }; const DialogueEntry introDialogue[] = diff --git a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/ahnkahet.h b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/ahnkahet.h index 8473ee1d39d..5b8cf0a4d44 100644 --- a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/ahnkahet.h +++ b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/ahnkahet.h @@ -18,33 +18,71 @@ #ifndef AHNKAHET_H_ #define AHNKAHET_H_ -enum Data64 +#define AhnKahetScriptName "instance_ahnkahet" + +uint32 const EncounterCount = 5; + +enum DataTypes +{ + // Encounter States/Boss GUIDs + DATA_ELDER_NADOX = 0, + DATA_PRINCE_TALDARAM = 1, + DATA_JEDOGA_SHADOWSEEKER = 2, + DATA_AMANITAR = 3, + DATA_HERALD_VOLAZJ = 4, + + // Additional Data + DATA_SPHERE_1 = 5, + DATA_SPHERE_2 = 6, + DATA_PRINCE_TALDARAM_PLATFORM = 7, + DATA_PL_JEDOGA_TARGET = 8, + DATA_ADD_JEDOGA_OPFER = 9, + DATA_ADD_JEDOGA_INITIAND = 10, + DATA_JEDOGA_TRIGGER_SWITCH = 11, + DATA_JEDOGA_RESET_INITIANDS = 12, + DATA_ALL_INITIAND_DEAD = 13 +}; + +enum CreatureIds { - DATA_ELDER_NADOX, - DATA_PRINCE_TALDARAM, - DATA_JEDOGA_SHADOWSEEKER, - DATA_HERALD_VOLAZJ, - DATA_AMANITAR, - DATA_SPHERE1, - DATA_SPHERE2, - DATA_PRINCE_TALDARAM_PLATFORM, - DATA_PL_JEDOGA_TARGET, - DATA_ADD_JEDOGA_OPFER, - DATA_ADD_JEDOGA_INITIAND + NPC_ELDER_NADOX = 29309, + NPC_PRINCE_TALDARAM = 29308, + NPC_JEDOGA_SHADOWSEEKER = 29310, + NPC_AMANITAR = 30258, + NPC_HERALD_VOLAZJ = 29311, + + // Elder Nadox + NPC_AHNKAHAR_GUARDIAN = 30176, + NPC_AHNKAHAR_SWARMER = 30178, + + // Jedoga Shadowseeker + NPC_INITIAND = 30114, + NPC_JEDOGA_CONTROLLER = 30181, + + // Amanitar + NPC_HEALTHY_MUSHROOM = 30391, + NPC_POISONOUS_MUSHROOM = 30435, + + // Herald Volazj + //NPC_TWISTED_VISAGE_1 = 30621, + //NPC_TWISTED_VISAGE_2 = 30622, + //NPC_TWISTED_VISAGE_3 = 30623, + //NPC_TWISTED_VISAGE_4 = 30624, + NPC_TWISTED_VISAGE = 30625 }; -enum Data +enum GameObjectIds { - DATA_ELDER_NADOX_EVENT, - DATA_PRINCE_TALDARAM_EVENT, - DATA_JEDOGA_SHADOWSEEKER_EVENT, - DATA_HERALD_VOLAZJ_EVENT, - DATA_AMANITAR_EVENT, - DATA_SPHERE1_EVENT, - DATA_SPHERE2_EVENT, - DATA_JEDOGA_TRIGGER_SWITCH, - DATA_JEDOGA_RESET_INITIANDS, - DATA_ALL_INITIAND_DEAD + GO_PRINCE_TALDARAM_GATE = 192236, + GO_PRINCE_TALDARAM_PLATFORM = 193564, + GO_SPHERE_1 = 193093, + GO_SPHERE_2 = 193094 }; +template<class AI> +AI* GetAhnKahetAI(Creature* creature) +{ + return GetInstanceAI<AI>(creature, AhnKahetScriptName); +} + #endif // AHNKAHET_H_ diff --git a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_amanitar.cpp b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_amanitar.cpp index 7a20d1f581c..7132ba825f1 100644 --- a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_amanitar.cpp +++ b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_amanitar.cpp @@ -35,8 +35,6 @@ enum Spells enum Creatures { - NPC_HEALTHY_MUSHROOM = 30391, - NPC_POISONOUS_MUSHROOM = 30435, NPC_TRIGGER = 19656 }; @@ -52,129 +50,112 @@ enum Events class boss_amanitar : public CreatureScript { -public: - boss_amanitar() : CreatureScript("boss_amanitar") { } - - struct boss_amanitarAI : public BossAI - { - boss_amanitarAI(Creature* creature) : BossAI(creature, DATA_AMANITAR) { } + public: + boss_amanitar() : CreatureScript("boss_amanitar") { } - void Reset() OVERRIDE + struct boss_amanitarAI : public BossAI { - _Reset(); + boss_amanitarAI(Creature* creature) : BossAI(creature, DATA_AMANITAR) { } - me->SetMeleeDamageSchool(SPELL_SCHOOL_NATURE); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, true); - summons.DespawnAll(); + void Reset() OVERRIDE + { + _Reset(); + me->SetMeleeDamageSchool(SPELL_SCHOOL_NATURE); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, true); + } - if (instance) + void EnterCombat(Unit* /*who*/) OVERRIDE { - instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_MINI); - instance->SetData(DATA_AMANITAR_EVENT, NOT_STARTED); + _EnterCombat(); + + events.ScheduleEvent(EVENT_ROOT, urand(5, 9) * IN_MILLISECONDS); + events.ScheduleEvent(EVENT_BASH, urand(10, 14) * IN_MILLISECONDS); + events.ScheduleEvent(EVENT_BOLT, urand(15, 20) * IN_MILLISECONDS); + events.ScheduleEvent(EVENT_MINI, urand(12, 18) * IN_MILLISECONDS); + events.ScheduleEvent(EVENT_SPAWN, 5 * IN_MILLISECONDS); } - } - void JustDied(Unit* /*Killer*/) OVERRIDE - { - if (instance) + void JustDied(Unit* /*killer*/) OVERRIDE { _JustDied(); - instance->SetData(DATA_AMANITAR_EVENT, DONE); instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_MINI); - summons.DespawnAll(); } - } - - void EnterCombat(Unit* /*who*/) OVERRIDE - { - _EnterCombat(); - - events.ScheduleEvent(EVENT_ROOT, urand(5, 9) * IN_MILLISECONDS); - events.ScheduleEvent(EVENT_BASH, urand(10, 14) * IN_MILLISECONDS); - events.ScheduleEvent(EVENT_BOLT, urand(15, 20) * IN_MILLISECONDS); - events.ScheduleEvent(EVENT_MINI, urand(12, 18) * IN_MILLISECONDS); - events.ScheduleEvent(EVENT_SPAWN, 5 * IN_MILLISECONDS); - me->SetInCombatWithZone(); - if (instance) - instance->SetData(DATA_AMANITAR_EVENT, IN_PROGRESS); - } - - void SpawnAdds() - { - uint8 u = 0; - - for (uint8 i = 0; i < 30; ++i) + void SpawnAdds() { - Position pos; - me->GetPosition(&pos); - me->GetRandomNearPosition(pos, 30.0f); - pos.m_positionZ = me->GetMap()->GetHeight(pos.GetPositionX(), pos.GetPositionY(), MAX_HEIGHT) + 2.0f; + uint8 u = 0; - if (Creature* trigger = me->SummonCreature(NPC_TRIGGER, pos)) + for (uint8 i = 0; i < 30; ++i) { - Creature* temp1 = trigger->FindNearestCreature(NPC_HEALTHY_MUSHROOM, 4.0f, true); - Creature* temp2 = trigger->FindNearestCreature(NPC_POISONOUS_MUSHROOM, 4.0f, true); - if (temp1 || temp2) - { - trigger->DisappearAndDie(); - } - else + Position pos; + me->GetPosition(&pos); + me->GetRandomNearPosition(pos, 30.0f); + pos.m_positionZ = me->GetMap()->GetHeight(pos.GetPositionX(), pos.GetPositionY(), MAX_HEIGHT) + 2.0f; + + if (Creature* trigger = me->SummonCreature(NPC_TRIGGER, pos)) { - u = 1 - u; - trigger->DisappearAndDie(); - me->SummonCreature(u > 0 ? NPC_POISONOUS_MUSHROOM : NPC_HEALTHY_MUSHROOM, pos, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60 * IN_MILLISECONDS); + Creature* temp1 = trigger->FindNearestCreature(NPC_HEALTHY_MUSHROOM, 4.0f, true); + Creature* temp2 = trigger->FindNearestCreature(NPC_POISONOUS_MUSHROOM, 4.0f, true); + if (temp1 || temp2) + { + trigger->DisappearAndDie(); + } + else + { + u = 1 - u; + trigger->DisappearAndDie(); + me->SummonCreature(u > 0 ? NPC_POISONOUS_MUSHROOM : NPC_HEALTHY_MUSHROOM, pos, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60 * IN_MILLISECONDS); + } } } } - } - void UpdateAI(uint32 diff) OVERRIDE - { - if (!UpdateVictim()) - return; + void UpdateAI(uint32 diff) OVERRIDE + { + if (!UpdateVictim()) + return; - events.Update(diff); + events.Update(diff); - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; - while (uint32 eventId = events.ExecuteEvent()) - { - switch (eventId) + while (uint32 eventId = events.ExecuteEvent()) { - case EVENT_SPAWN: - SpawnAdds(); - events.ScheduleEvent(EVENT_SPAWN, 20 * IN_MILLISECONDS); - break; - case EVENT_MINI: - DoCast(SPELL_MINI); - events.ScheduleEvent(EVENT_MINI, urand(25, 30) * IN_MILLISECONDS); - break; - case EVENT_ROOT: - DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true), SPELL_ENTANGLING_ROOTS, true); - events.ScheduleEvent(EVENT_ROOT, urand(10, 15) * IN_MILLISECONDS); - break; - case EVENT_BASH: - DoCastVictim(SPELL_BASH); - events.ScheduleEvent(EVENT_BASH, urand(7, 12) * IN_MILLISECONDS); - break; - case EVENT_BOLT: - DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true), SPELL_VENOM_BOLT_VOLLEY, true); - events.ScheduleEvent(EVENT_BOLT, urand(18, 22) * IN_MILLISECONDS); - break; - default: - break; + switch (eventId) + { + case EVENT_SPAWN: + SpawnAdds(); + events.ScheduleEvent(EVENT_SPAWN, 20 * IN_MILLISECONDS); + break; + case EVENT_MINI: + DoCast(SPELL_MINI); + events.ScheduleEvent(EVENT_MINI, urand(25, 30) * IN_MILLISECONDS); + break; + case EVENT_ROOT: + DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true), SPELL_ENTANGLING_ROOTS, true); + events.ScheduleEvent(EVENT_ROOT, urand(10, 15) * IN_MILLISECONDS); + break; + case EVENT_BASH: + DoCastVictim(SPELL_BASH); + events.ScheduleEvent(EVENT_BASH, urand(7, 12) * IN_MILLISECONDS); + break; + case EVENT_BOLT: + DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true), SPELL_VENOM_BOLT_VOLLEY, true); + events.ScheduleEvent(EVENT_BOLT, urand(18, 22) * IN_MILLISECONDS); + break; + default: + break; + } } + DoMeleeAttackIfReady(); } - DoMeleeAttackIfReady(); - } - }; + }; - CreatureAI* GetAI(Creature* creature) const OVERRIDE - { - return new boss_amanitarAI(creature); - } + CreatureAI* GetAI(Creature* creature) const OVERRIDE + { + return GetAhnKahetAI<boss_amanitarAI>(creature); + } }; class npc_amanitar_mushrooms : public CreatureScript diff --git a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_elder_nadox.cpp b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_elder_nadox.cpp index 482617cbfd5..4fa150511b5 100644 --- a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_elder_nadox.cpp +++ b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_elder_nadox.cpp @@ -41,12 +41,6 @@ enum Spells SPELL_GUARDIAN_AURA = 56151 }; -enum Creatures -{ - NPC_AHNKAHAR_SWARMER = 30178, - NPC_AHNKAHAR_GUARDIAN = 30176 -}; - enum Events { EVENT_PLAGUE = 1, @@ -62,38 +56,22 @@ class boss_elder_nadox : public CreatureScript public: boss_elder_nadox() : CreatureScript("boss_elder_nadox") { } - struct boss_elder_nadoxAI : public ScriptedAI + struct boss_elder_nadoxAI : public BossAI { - boss_elder_nadoxAI(Creature* creature) : ScriptedAI(creature), summons(me) - { - instance = creature->GetInstanceScript(); - } - - bool GuardianDied; - uint8 AmountHealthModifier; - InstanceScript* instance; - SummonList summons; - EventMap events; + boss_elder_nadoxAI(Creature* creature) : BossAI(creature, DATA_ELDER_NADOX) { } void Reset() OVERRIDE { - events.Reset(); - summons.DespawnAll(); - + _Reset(); AmountHealthModifier = 1; GuardianDied = false; - - if (instance) - instance->SetData(DATA_ELDER_NADOX_EVENT, NOT_STARTED); } void EnterCombat(Unit* /*who*/) OVERRIDE { + _EnterCombat(); Talk(SAY_AGGRO); - if (instance) - instance->SetData(DATA_ELDER_NADOX_EVENT, IN_PROGRESS); - events.ScheduleEvent(EVENT_PLAGUE, 13 * IN_MILLISECONDS); events.ScheduleEvent(EVENT_SUMMON_SWARMER, 10 * IN_MILLISECONDS); @@ -104,12 +82,6 @@ class boss_elder_nadox : public CreatureScript } } - void JustSummoned(Creature* summon) OVERRIDE - { - summons.Summon(summon); - summon->AI()->DoZoneInCombat(); - } - void SummonedCreatureDies(Creature* summon, Unit* /*killer*/) OVERRIDE { if (summon->GetEntry() == NPC_AHNKAHAR_GUARDIAN) @@ -124,19 +96,16 @@ class boss_elder_nadox : public CreatureScript return 0; } - void KilledUnit(Unit* /*victim*/) OVERRIDE + void KilledUnit(Unit* who) OVERRIDE { - Talk(SAY_SLAY); + if (who->GetTypeId() == TYPEID_PLAYER) + Talk(SAY_SLAY); } void JustDied(Unit* /*killer*/) OVERRIDE { + _JustDied(); Talk(SAY_DEATH); - - summons.DespawnAll(); - - if (instance) - instance->SetData(DATA_ELDER_NADOX_EVENT, DONE); } void UpdateAI(uint32 diff) OVERRIDE @@ -185,11 +154,15 @@ class boss_elder_nadox : public CreatureScript DoMeleeAttackIfReady(); } + + private: + bool GuardianDied; + uint8 AmountHealthModifier; }; CreatureAI* GetAI(Creature* creature) const OVERRIDE { - return new boss_elder_nadoxAI(creature); + return GetAhnKahetAI<boss_elder_nadoxAI>(creature); } }; diff --git a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_herald_volazj.cpp b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_herald_volazj.cpp index 481df79c890..5bb68a4c886 100644 --- a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_herald_volazj.cpp +++ b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_herald_volazj.cpp @@ -41,12 +41,6 @@ enum Spells SPELL_INSANITY_PHASING_5 = 57512 }; -enum Creatures -{ - NPC_TWISTED_VISAGE = 30625 -}; - - enum Yells { SAY_AGGRO = 0, @@ -157,7 +151,7 @@ public: if (instance) { - instance->SetData(DATA_HERALD_VOLAZJ, NOT_STARTED); + instance->SetBossState(DATA_HERALD_VOLAZJ, NOT_STARTED); instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_QUICK_DEMISE_START_EVENT); } @@ -180,7 +174,7 @@ public: if (instance) { - instance->SetData(DATA_HERALD_VOLAZJ, IN_PROGRESS); + instance->SetBossState(DATA_HERALD_VOLAZJ, IN_PROGRESS); instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_QUICK_DEMISE_START_EVENT); } } @@ -302,7 +296,7 @@ public: Talk(SAY_DEATH); if (instance) - instance->SetData(DATA_HERALD_VOLAZJ, DONE); + instance->SetBossState(DATA_HERALD_VOLAZJ, DONE); Summons.DespawnAll(); ResetPlayersPhaseMask(); diff --git a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_jedoga_shadowseeker.cpp b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_jedoga_shadowseeker.cpp index 5095f590fdb..78513fec486 100644 --- a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_jedoga_shadowseeker.cpp +++ b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_jedoga_shadowseeker.cpp @@ -46,11 +46,6 @@ enum Spells SPELL_THUNDERSHOCK_H = 60029 // 30Y }; -enum Creatures -{ - NPC_JEDOGA_CONTROLLER = 30181 -}; - const Position JedogaPosition[2] = { {372.330994f, -705.278015f, -0.624178f, 5.427970f}, @@ -109,7 +104,7 @@ public: if (instance) { if (!bFirstTime) - instance->SetData(DATA_JEDOGA_SHADOWSEEKER_EVENT, FAIL); + instance->SetBossState(DATA_JEDOGA_SHADOWSEEKER, FAIL); instance->SetData64(DATA_PL_JEDOGA_TARGET, 0); instance->SetData64(DATA_ADD_JEDOGA_OPFER, 0); @@ -127,7 +122,7 @@ public: Talk(TEXT_AGGRO); me->SetInCombatWithZone(); - instance->SetData(DATA_JEDOGA_SHADOWSEEKER_EVENT, IN_PROGRESS); + instance->SetBossState(DATA_JEDOGA_SHADOWSEEKER, IN_PROGRESS); } void AttackStart(Unit* who) OVERRIDE @@ -150,7 +145,7 @@ public: { Talk(TEXT_DEATH); if (instance) - instance->SetData(DATA_JEDOGA_SHADOWSEEKER_EVENT, DONE); + instance->SetBossState(DATA_JEDOGA_SHADOWSEEKER, DONE); } void DoAction(int32 action) OVERRIDE @@ -168,7 +163,6 @@ public: } void MoveInLineOfSight(Unit* who) OVERRIDE - { if (!instance || !who || (who->GetTypeId() == TYPEID_UNIT && who->GetEntry() == NPC_JEDOGA_CONTROLLER)) return; @@ -179,7 +173,7 @@ public: bPreDone = true; } - if (instance->GetData(DATA_JEDOGA_SHADOWSEEKER_EVENT) != IN_PROGRESS || !bOnGround) + if (instance->GetBossState(DATA_JEDOGA_SHADOWSEEKER) != IN_PROGRESS || !bOnGround) return; if (!me->GetVictim() && me->CanCreatureAttack(who)) @@ -229,7 +223,7 @@ public: { AttackStart(target); instance->SetData(DATA_JEDOGA_RESET_INITIANDS, 0); - if (instance->GetData(DATA_JEDOGA_SHADOWSEEKER_EVENT) != IN_PROGRESS) + if (instance->GetBossState(DATA_JEDOGA_SHADOWSEEKER) != IN_PROGRESS) EnterCombat(target); } else if (!me->IsInCombat()) @@ -252,7 +246,8 @@ public: me->GetMotionMaster()->MovePoint(0, JedogaPosition[0]); instance->SetData(DATA_JEDOGA_TRIGGER_SWITCH, 1); - if (instance->GetData(DATA_JEDOGA_SHADOWSEEKER_EVENT) == IN_PROGRESS) OpferRufen(); + if (instance->GetBossState(DATA_JEDOGA_SHADOWSEEKER) == IN_PROGRESS) + OpferRufen(); bOnGround = false; uiOpFerTimer = urand(15*IN_MILLISECONDS, 30*IN_MILLISECONDS); @@ -289,7 +284,7 @@ public: if (!instance) return; - if (instance->GetData(DATA_JEDOGA_SHADOWSEEKER_EVENT) != IN_PROGRESS && instance->GetData(DATA_ALL_INITIAND_DEAD)) + if (instance->GetBossState(DATA_JEDOGA_SHADOWSEEKER) != IN_PROGRESS && instance->GetData(DATA_ALL_INITIAND_DEAD)) MoveDown(); if (bOpFerok && !bOnGround && !bCanDown) Opfern(); @@ -372,7 +367,7 @@ public: bWalking = false; bCheckTimer = 2*IN_MILLISECONDS; - if (instance->GetData(DATA_JEDOGA_SHADOWSEEKER_EVENT) != IN_PROGRESS) + if (instance->GetBossState(DATA_JEDOGA_SHADOWSEEKER) != IN_PROGRESS) { me->RemoveAurasDueToSpell(SPELL_SPHERE_VISUAL); me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, false); @@ -412,15 +407,13 @@ public: instance->SetData64(DATA_PL_JEDOGA_TARGET, killer->GetGUID()); } - void EnterCombat(Unit* who) OVERRIDE + void EnterCombat(Unit* /*who*/) OVERRIDE { - if ((instance && instance->GetData(DATA_JEDOGA_SHADOWSEEKER_EVENT) == IN_PROGRESS) || !who) - return; } void AttackStart(Unit* victim) OVERRIDE { - if ((instance && instance->GetData(DATA_JEDOGA_SHADOWSEEKER_EVENT) == IN_PROGRESS) || !victim) + if ((instance && instance->GetBossState(DATA_JEDOGA_SHADOWSEEKER) == IN_PROGRESS) || !victim) return; ScriptedAI::AttackStart(victim); @@ -429,7 +422,7 @@ public: void MoveInLineOfSight(Unit* who) OVERRIDE { - if ((instance && instance->GetData(DATA_JEDOGA_SHADOWSEEKER_EVENT) == IN_PROGRESS) || !who) + if ((instance && instance->GetBossState(DATA_JEDOGA_SHADOWSEEKER) == IN_PROGRESS) || !who) return; ScriptedAI::MoveInLineOfSight(who); @@ -482,14 +475,14 @@ public: } if (!bWalking) { - if (instance->GetData(DATA_JEDOGA_SHADOWSEEKER_EVENT) != IN_PROGRESS && me->HasAura(SPELL_SPHERE_VISUAL)) + if (instance->GetBossState(DATA_JEDOGA_SHADOWSEEKER) != IN_PROGRESS && me->HasAura(SPELL_SPHERE_VISUAL)) { me->RemoveAurasDueToSpell(SPELL_SPHERE_VISUAL); me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, false); me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_MAGIC, false); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE + UNIT_FLAG_NON_ATTACKABLE); } - if (instance->GetData(DATA_JEDOGA_SHADOWSEEKER_EVENT) == IN_PROGRESS && !me->HasAura(SPELL_SPHERE_VISUAL)) + if (instance->GetBossState(DATA_JEDOGA_SHADOWSEEKER) == IN_PROGRESS && !me->HasAura(SPELL_SPHERE_VISUAL)) { DoCast(me, SPELL_SPHERE_VISUAL, false); me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, true); @@ -561,7 +554,7 @@ public: if (!bRemoved && me->GetPositionX() > 440.0f) { - if (instance->GetData(DATA_PRINCE_TALDARAM_EVENT) == DONE) + if (instance->GetBossState(DATA_PRINCE_TALDARAM) == DONE) { me->InterruptNonMeleeSpells(true); bRemoved = true; @@ -585,7 +578,7 @@ public: me->InterruptNonMeleeSpells(true); bCasted2 = false; } - if (!bRemoved2 && instance->GetData(DATA_JEDOGA_SHADOWSEEKER_EVENT) == DONE) + if (!bRemoved2 && instance->GetBossState(DATA_JEDOGA_SHADOWSEEKER) == DONE) { me->InterruptNonMeleeSpells(true); bRemoved2 = true; diff --git a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_prince_taldaram.cpp b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_prince_taldaram.cpp index 2cfc714c1f7..2f01cc734e6 100644 --- a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_prince_taldaram.cpp +++ b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_prince_taldaram.cpp @@ -69,11 +69,6 @@ enum CombatPhase VANISHED, FEEDING }; -enum GameObjects -{ - GO_SPHERE1 = 193093, - GO_SPHERE2 = 193094 -}; class boss_taldaram : public CreatureScript { @@ -113,13 +108,13 @@ public: uiPhaseTimer = 0; uiEmbraceTarget = 0; if (instance) - instance->SetData(DATA_PRINCE_TALDARAM_EVENT, NOT_STARTED); + instance->SetBossState(DATA_PRINCE_TALDARAM, NOT_STARTED); } void EnterCombat(Unit* /*who*/) OVERRIDE { if (instance) - instance->SetData(DATA_PRINCE_TALDARAM_EVENT, IN_PROGRESS); + instance->SetBossState(DATA_PRINCE_TALDARAM, IN_PROGRESS); Talk(SAY_AGGRO); } @@ -267,7 +262,7 @@ public: Talk(SAY_DEATH); if (instance) - instance->SetData(DATA_PRINCE_TALDARAM_EVENT, DONE); + instance->SetBossState(DATA_PRINCE_TALDARAM, DONE); } void KilledUnit(Unit* victim) OVERRIDE @@ -287,21 +282,10 @@ public: bool CheckSpheres() { - if (!instance) - return false; - - uint64 uiSphereGuids[2]; - uiSphereGuids[0] = instance->GetData64(DATA_SPHERE1); - uiSphereGuids[1] = instance->GetData64(DATA_SPHERE2); - - for (uint8 i=0; i < 2; ++i) - { - GameObject* pSpheres = instance->instance->GetGameObject(uiSphereGuids[i]); - if (!pSpheres) + for (uint8 i = 0; i < 2; ++i) + if (!instance->GetData(DATA_SPHERE_1 + i)) return false; - if (pSpheres->GetGoState() != GO_STATE_ACTIVE) - return false; - } + RemovePrison(); return true; } @@ -332,7 +316,7 @@ public: CreatureAI* GetAI(Creature* creature) const OVERRIDE { - return new boss_taldaramAI(creature); + return GetAhnKahetAI<boss_taldaramAI>(creature); } }; @@ -390,39 +374,38 @@ public: class prince_taldaram_sphere : public GameObjectScript { -public: - prince_taldaram_sphere() : GameObjectScript("prince_taldaram_sphere") { } - - bool OnGossipHello(Player* /*player*/, GameObject* go) OVERRIDE - { - InstanceScript* instance = go->GetInstanceScript(); - if (!instance) - return true; + public: + prince_taldaram_sphere() : GameObjectScript("prince_taldaram_sphere") { } - Creature* pPrinceTaldaram = Unit::GetCreature(*go, instance->GetData64(DATA_PRINCE_TALDARAM)); - if (pPrinceTaldaram && pPrinceTaldaram->IsAlive()) + bool OnGossipHello(Player* /*player*/, GameObject* go) { - // maybe these are hacks :( - go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); - go->SetGoState(GO_STATE_ACTIVE); + InstanceScript* instance = go->GetInstanceScript(); + if (!instance) + return false; - switch (go->GetEntry()) + Creature* PrinceTaldaram = ObjectAccessor::GetCreature(*go, instance->GetData64(DATA_PRINCE_TALDARAM)); + if (PrinceTaldaram && PrinceTaldaram->IsAlive()) { - case GO_SPHERE1: - instance->SetData(DATA_SPHERE1_EVENT, IN_PROGRESS); - pPrinceTaldaram->AI()->Talk(SAY_1); - break; + // maybe these are hacks :( + go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); + go->SetGoState(GO_STATE_ACTIVE); - case GO_SPHERE2: - instance->SetData(DATA_SPHERE2_EVENT, IN_PROGRESS); - pPrinceTaldaram->AI()->Talk(SAY_1); - break; - } + switch (go->GetEntry()) + { + case GO_SPHERE_1: + instance->SetData(DATA_SPHERE_1, IN_PROGRESS); + PrinceTaldaram->AI()->Talk(SAY_1); + break; + case GO_SPHERE_2: + instance->SetData(DATA_SPHERE_2, IN_PROGRESS); + PrinceTaldaram->AI()->Talk(SAY_1); + break; + } - CAST_AI(boss_taldaram::boss_taldaramAI, pPrinceTaldaram->AI())->CheckSpheres(); + CAST_AI(boss_taldaram::boss_taldaramAI, PrinceTaldaram->AI())->CheckSpheres(); + } + return true; } - return true; - } }; void AddSC_boss_taldaram() diff --git a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/instance_ahnkahet.cpp b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/instance_ahnkahet.cpp index a7b82583d08..7207bbd3aab 100644 --- a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/instance_ahnkahet.cpp +++ b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/instance_ahnkahet.cpp @@ -20,321 +20,314 @@ #include "InstanceScript.h" #include "ahnkahet.h" -/* Ahn'kahet encounters: -0 - Elder Nadox -1 - Prince Taldaram -2 - Jedoga Shadowseeker -3 - Herald Volazj -4 - Amanitar (Heroic only) -*/ - -#define MAX_ENCOUNTER 5 - -enum Achievements +DoorData const doorData[] = { - ACHIEV_VOLUNTEER_WORK = 2056 + { GO_PRINCE_TALDARAM_GATE, DATA_PRINCE_TALDARAM, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, + { 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE } // END }; class instance_ahnkahet : public InstanceMapScript { -public: - instance_ahnkahet() : InstanceMapScript("instance_ahnkahet", 619) { } - - struct instance_ahnkahet_InstanceScript : public InstanceScript - { - instance_ahnkahet_InstanceScript(Map* map) : InstanceScript(map) {} - - uint64 Elder_Nadox; - uint64 Prince_Taldaram; - uint64 Jedoga_Shadowseeker; - uint64 Herald_Volazj; - uint64 Amanitar; - - uint64 Prince_TaldaramSpheres[2]; - uint64 Prince_TaldaramPlatform; - uint64 Prince_TaldaramGate; - - std::set<uint64> InitiandGUIDs; - uint64 JedogaSacrifices; - uint64 JedogaTarget; + public: + instance_ahnkahet() : InstanceMapScript(AhnKahetScriptName, 619) { } - uint32 m_auiEncounter[MAX_ENCOUNTER]; - uint32 spheres[2]; + struct instance_ahnkahet_InstanceScript : public InstanceScript + { + instance_ahnkahet_InstanceScript(Map* map) : InstanceScript(map) + { + SetBossNumber(EncounterCount); + LoadDoorData(doorData); - uint8 InitiandCnt; - uint8 switchtrigger; + ElderNadoxGUID = 0; + PrinceTaldaramGUID = 0; + JedogaShadowseekerGUID = 0; + AmanitarGUID = 0; + HeraldVolazjGUID = 0; - std::string str_data; + PrinceTaldaramPlatformGUID = 0; + JedogaSacrifices = 0; + JedogaTarget = 0; + SwitchTrigger = 0; - void Initialize() OVERRIDE - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - InitiandGUIDs.clear(); - - Elder_Nadox =0; - Prince_Taldaram =0; - Jedoga_Shadowseeker =0; - Herald_Volazj =0; - Amanitar =0; - - spheres[0] = NOT_STARTED; - spheres[1] = NOT_STARTED; - - InitiandCnt = 0; - switchtrigger = 0; - JedogaSacrifices = 0; - JedogaTarget = 0; - } + SpheresState[0] = 0; + SpheresState[1] = 0; - bool IsEncounterInProgress() const OVERRIDE - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - return true; + InitiandGUIDs.clear(); + } - return false; - } + void OnCreatureCreate(Creature* creature) OVERRIDE + { + switch (creature->GetEntry()) + { + case NPC_ELDER_NADOX: + ElderNadoxGUID = creature->GetGUID(); + break; + case NPC_PRINCE_TALDARAM: + PrinceTaldaramGUID = creature->GetGUID(); + break; + case NPC_JEDOGA_SHADOWSEEKER: + JedogaShadowseekerGUID = creature->GetGUID(); + break; + case NPC_AMANITAR: + AmanitarGUID = creature->GetGUID(); + break; + case NPC_HERALD_VOLAZJ: + HeraldVolazjGUID = creature->GetGUID(); + break; + case NPC_INITIAND: + InitiandGUIDs.insert(creature->GetGUID()); + break; + default: + break; + } + } - void OnCreatureCreate(Creature* creature) OVERRIDE - { - switch (creature->GetEntry()) + void OnGameObjectCreate(GameObject* go) OVERRIDE { - case 29309: Elder_Nadox = creature->GetGUID(); break; - case 29308: Prince_Taldaram = creature->GetGUID(); break; - case 29310: Jedoga_Shadowseeker = creature->GetGUID(); break; - case 29311: Herald_Volazj = creature->GetGUID(); break; - case 30258: Amanitar = creature->GetGUID(); break; - case 30114: InitiandGUIDs.insert(creature->GetGUID()); break; + switch (go->GetEntry()) + { + case GO_PRINCE_TALDARAM_PLATFORM: + PrinceTaldaramPlatformGUID = go->GetGUID(); + if (GetBossState(DATA_PRINCE_TALDARAM) == DONE) + HandleGameObject(0, true, go); + break; + case GO_SPHERE_1: + if (SpheresState[0]) + { + go->SetGoState(GO_STATE_ACTIVE); + go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); + } + else + go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); + break; + case GO_SPHERE_2: + if (SpheresState[1]) + { + go->SetGoState(GO_STATE_ACTIVE); + go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); + } + else + go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); + break; + case GO_PRINCE_TALDARAM_GATE: + AddDoor(go, true); + break; + default: + break; + } } - } - void OnGameObjectCreate(GameObject* go) OVERRIDE - { - switch (go->GetEntry()) + void OnGameObjectRemove(GameObject* go) OVERRIDE { - case 193564: - Prince_TaldaramPlatform = go->GetGUID(); - if (m_auiEncounter[1] == DONE) - HandleGameObject(0, true, go); - break; - - case 193093: - Prince_TaldaramSpheres[0] = go->GetGUID(); - if (spheres[0] == IN_PROGRESS) - { - go->SetGoState(GO_STATE_ACTIVE); - go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); - } - else - go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); - break; - case 193094: - Prince_TaldaramSpheres[1] = go->GetGUID(); - if (spheres[1] == IN_PROGRESS) - { - go->SetGoState(GO_STATE_ACTIVE); - go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); - } - else - go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); - break; - case 192236: - Prince_TaldaramGate = go->GetGUID(); // Web gate past Prince Taldaram - if (m_auiEncounter[1] == DONE) - HandleGameObject(0, true, go); - break; + switch (go->GetEntry()) + { + case GO_PRINCE_TALDARAM_GATE: + AddDoor(go, false); + break; + default: + break; + } } - } - void SetData64(uint32 idx, uint64 guid) OVERRIDE - { - switch (idx) + void SetData(uint32 type, uint32 data) OVERRIDE { - case DATA_ADD_JEDOGA_OPFER: - JedogaSacrifices = guid; - break; + switch (type) + { + case DATA_SPHERE_1: + case DATA_SPHERE_2: + SpheresState[type - DATA_SPHERE_1] = data; + break; + case DATA_JEDOGA_TRIGGER_SWITCH: + SwitchTrigger = data; + break; + case DATA_JEDOGA_RESET_INITIANDS: + for (std::set<uint64>::const_iterator itr = InitiandGUIDs.begin(); itr != InitiandGUIDs.end(); ++itr) + { + if (Creature* creature = instance->GetCreature(*itr)) + { + creature->Respawn(); + if (!creature->IsInEvadeMode()) + creature->AI()->EnterEvadeMode(); + } + } + break; + default: + break; + } + } - case DATA_PL_JEDOGA_TARGET: - JedogaTarget = guid; - break; + uint32 GetData(uint32 type) const OVERRIDE + { + switch (type) + { + case DATA_SPHERE_1: + case DATA_SPHERE_2: + return SpheresState[type - DATA_SPHERE_1]; + case DATA_ALL_INITIAND_DEAD: + for (std::set<uint64>::const_iterator itr = InitiandGUIDs.begin(); itr != InitiandGUIDs.end(); ++itr) + { + Creature* cr = instance->GetCreature(*itr); + if (!cr || cr->IsAlive()) + return 0; + } + return 1; + case DATA_JEDOGA_TRIGGER_SWITCH: + return SwitchTrigger; + default: + break; + } + return 0; } - } - uint64 GetData64(uint32 identifier) const OVERRIDE - { - switch (identifier) + void SetData64(uint32 type, uint64 data) OVERRIDE { - case DATA_ELDER_NADOX: return Elder_Nadox; - case DATA_PRINCE_TALDARAM: return Prince_Taldaram; - case DATA_JEDOGA_SHADOWSEEKER: return Jedoga_Shadowseeker; - case DATA_HERALD_VOLAZJ: return Herald_Volazj; - case DATA_AMANITAR: return Amanitar; - case DATA_SPHERE1: return Prince_TaldaramSpheres[0]; - case DATA_SPHERE2: return Prince_TaldaramSpheres[1]; - case DATA_PRINCE_TALDARAM_PLATFORM: return Prince_TaldaramPlatform; - case DATA_ADD_JEDOGA_INITIAND: + switch (type) { - std::vector<uint64> vInitiands; - vInitiands.clear(); - for (std::set<uint64>::const_iterator itr = InitiandGUIDs.begin(); itr != InitiandGUIDs.end(); ++itr) - { - Creature* cr = instance->GetCreature(*itr); - if (cr && cr->IsAlive()) - vInitiands.push_back(*itr); - } - if (vInitiands.empty()) - return 0; - uint8 j = urand(0, vInitiands.size() -1); - return vInitiands[j]; + case DATA_ADD_JEDOGA_OPFER: + JedogaSacrifices = data; + break; + case DATA_PL_JEDOGA_TARGET: + JedogaTarget = data; + break; + default: + break; } - case DATA_ADD_JEDOGA_OPFER: return JedogaSacrifices; - case DATA_PL_JEDOGA_TARGET: return JedogaTarget; } - return 0; - } - void SetData(uint32 type, uint32 data) OVERRIDE - { - switch (type) + uint64 GetData64(uint32 type) const OVERRIDE { - case DATA_ELDER_NADOX_EVENT: - m_auiEncounter[0] = data; - break; - case DATA_PRINCE_TALDARAM_EVENT: - if (data == DONE) - HandleGameObject(Prince_TaldaramGate, true); - m_auiEncounter[1] = data; - break; - case DATA_JEDOGA_SHADOWSEEKER_EVENT: - m_auiEncounter[2] = data; - if (data == DONE) + switch (type) + { + case DATA_ELDER_NADOX: + return ElderNadoxGUID; + case DATA_PRINCE_TALDARAM: + return PrinceTaldaramGUID; + case DATA_JEDOGA_SHADOWSEEKER: + return JedogaShadowseekerGUID; + case DATA_AMANITAR: + return AmanitarGUID; + case DATA_HERALD_VOLAZJ: + return HeraldVolazjGUID; + case DATA_PRINCE_TALDARAM_PLATFORM: + return PrinceTaldaramPlatformGUID; + case DATA_ADD_JEDOGA_INITIAND: { + std::vector<uint64> vInitiands; + vInitiands.clear(); for (std::set<uint64>::const_iterator itr = InitiandGUIDs.begin(); itr != InitiandGUIDs.end(); ++itr) { Creature* cr = instance->GetCreature(*itr); if (cr && cr->IsAlive()) - { - cr->SetVisible(false); - cr->setDeathState(JUST_DIED); - cr->RemoveCorpse(); - } + vInitiands.push_back(*itr); } + if (vInitiands.empty()) + return 0; + + return Trinity::Containers::SelectRandomContainerElement(vInitiands); } - break; - case DATA_HERALD_VOLAZJ_EVENT: - m_auiEncounter[3] = data; - break; - case DATA_AMANITAR_EVENT: - m_auiEncounter[4] = data; - break; - case DATA_SPHERE1_EVENT: - spheres[0] = data; - break; - case DATA_SPHERE2_EVENT: - spheres[1] = data; - break; - case DATA_JEDOGA_TRIGGER_SWITCH: - switchtrigger = data; - break; - case DATA_JEDOGA_RESET_INITIANDS: - for (std::set<uint64>::const_iterator itr = InitiandGUIDs.begin(); itr != InitiandGUIDs.end(); ++itr) - { - Creature* cr = instance->GetCreature(*itr); - if (cr) + case DATA_ADD_JEDOGA_OPFER: + return JedogaSacrifices; + case DATA_PL_JEDOGA_TARGET: + return JedogaTarget; + default: + break; + } + return 0; + } + + bool SetBossState(uint32 type, EncounterState state) OVERRIDE + { + if (!InstanceScript::SetBossState(type, state)) + return false; + + switch (type) + { + case DATA_JEDOGA_SHADOWSEEKER: + if (state == DONE) { - cr->Respawn(); - if (!cr->IsInEvadeMode()) cr->AI()->EnterEvadeMode(); + for (std::set<uint64>::const_iterator itr = InitiandGUIDs.begin(); itr != InitiandGUIDs.end(); ++itr) + { + if (Creature* cr = instance->GetCreature(*itr)) + cr->DespawnOrUnsummon(); + } } - } - break; + break; + default: + break; + } + return true; } - if (data == DONE) - SaveToDB(); - } - uint32 GetData(uint32 type) const OVERRIDE - { - switch (type) + std::string GetSaveData() OVERRIDE { - case DATA_ELDER_NADOX_EVENT: return m_auiEncounter[0]; - case DATA_PRINCE_TALDARAM_EVENT: return m_auiEncounter[1]; - case DATA_JEDOGA_SHADOWSEEKER_EVENT: return m_auiEncounter[2]; - case DATA_HERALD_VOLAZJ: return m_auiEncounter[3]; - case DATA_AMANITAR_EVENT: return m_auiEncounter[4]; - case DATA_SPHERE1_EVENT: return spheres[0]; - case DATA_SPHERE2_EVENT: return spheres[1]; - case DATA_ALL_INITIAND_DEAD: - for (std::set<uint64>::const_iterator itr = InitiandGUIDs.begin(); itr != InitiandGUIDs.end(); ++itr) - { - Creature* cr = instance->GetCreature(*itr); - if (!cr || (cr && cr->IsAlive())) - return 0; - } - return 1; - case DATA_JEDOGA_TRIGGER_SWITCH: return switchtrigger; - } - return 0; - } + OUT_SAVE_INST_DATA; - std::string GetSaveData() OVERRIDE - { - OUT_SAVE_INST_DATA; + std::ostringstream saveStream; + saveStream << "A K " << GetBossSaveData() << SpheresState[0] << ' ' << SpheresState[1]; - std::ostringstream saveStream; - saveStream << "A K " << m_auiEncounter[0] << ' ' << m_auiEncounter[1] << ' ' - << m_auiEncounter[2] << ' ' << m_auiEncounter[3] << ' ' << m_auiEncounter[4] << ' ' - << spheres[0] << ' ' << spheres[1]; + OUT_SAVE_INST_DATA_COMPLETE; + return saveStream.str(); + } - str_data = saveStream.str(); + void Load(char const* str) OVERRIDE + { + if (!str) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } - OUT_SAVE_INST_DATA_COMPLETE; - return str_data; - } + OUT_LOAD_INST_DATA(str); - void Load(const char* in) OVERRIDE - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } + char dataHead1, dataHead2; - OUT_LOAD_INST_DATA(in); + std::istringstream loadStream(str); + loadStream >> dataHead1 >> dataHead2; + + if (dataHead1 == 'A' && dataHead2 == 'K') + { + for (uint32 i = 0; i < EncounterCount; ++i) + { + uint32 tmpState; + loadStream >> tmpState; + if (tmpState == IN_PROGRESS || tmpState > SPECIAL) + tmpState = NOT_STARTED; + SetBossState(i, EncounterState(tmpState)); + } - char dataHead1, dataHead2; - uint16 data0, data1, data2, data3, data4, data5, data6; + loadStream >> SpheresState[0]; + loadStream >> SpheresState[1]; + } + else + OUT_LOAD_INST_DATA_FAIL; - std::istringstream loadStream(in); - loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3 >> data4 >> data5 >> data6; + OUT_LOAD_INST_DATA_COMPLETE; + } - if (dataHead1 == 'A' && dataHead2 == 'K') - { - m_auiEncounter[0] = data0; - m_auiEncounter[1] = data1; - m_auiEncounter[2] = data2; - m_auiEncounter[3] = data3; - m_auiEncounter[4] = data4; + protected: + uint64 ElderNadoxGUID; + uint64 PrinceTaldaramGUID; + uint64 JedogaShadowseekerGUID; + uint64 AmanitarGUID; + uint64 HeraldVolazjGUID; - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - m_auiEncounter[i] = NOT_STARTED; + uint64 PrinceTaldaramPlatformGUID; + uint64 JedogaSacrifices; + uint64 JedogaTarget; - spheres[0] = data5; - spheres[1] = data6; + std::set<uint64> InitiandGUIDs; - } else OUT_LOAD_INST_DATA_FAIL; + uint8 SpheresState[2]; + uint8 SwitchTrigger; + }; - OUT_LOAD_INST_DATA_COMPLETE; + InstanceScript* GetInstanceScript(InstanceMap* map) const OVERRIDE + { + return new instance_ahnkahet_InstanceScript(map); } - }; - - InstanceScript* GetInstanceScript(InstanceMap* map) const OVERRIDE - { - return new instance_ahnkahet_InstanceScript(map); - } }; void AddSC_instance_ahnkahet() { - new instance_ahnkahet(); + new instance_ahnkahet(); } diff --git a/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/azjol_nerub.h b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/azjol_nerub.h index 5970a85cc38..5087ed0cec3 100644 --- a/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/azjol_nerub.h +++ b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/azjol_nerub.h @@ -15,24 +15,49 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef DEF_AZJOL_NERUB_H -#define DEF_AZJOL_NERUB_H +#ifndef AZJOL_NERUB_H_ +#define AZJOL_NERUB_H_ -enum Data64 +#define AzjolNerubScriptName "instance_azjol_nerub" + +uint32 const EncounterCount = 3; + +enum DataTypes { - DATA_KRIKTHIR_THE_GATEWATCHER, - DATA_HADRONOX, - DATA_ANUBARAK, - DATA_WATCHER_GASHRA, - DATA_WATCHER_SILTHIK, - DATA_WATCHER_NARJIL + // Encounter States/Boss GUIDs + DATA_KRIKTHIR_THE_GATEWATCHER = 0, + DATA_HADRONOX = 1, + DATA_ANUBARAK = 2, + + // Additional Data + DATA_WATCHER_GASHRA = 3, + DATA_WATCHER_SILTHIK = 4, + DATA_WATCHER_NARJIL = 5 }; -enum Data +enum CreatureIds { - DATA_KRIKTHIR_THE_GATEWATCHER_EVENT, - DATA_HADRONOX_EVENT, - DATA_ANUBARAK_EVENT + NPC_KRIKTHIR = 28684, + NPC_HADRONOX = 28921, + NPC_ANUBARAK = 29120, + + NPC_WATCHER_NARJIL = 28729, + NPC_WATCHER_GASHRA = 28730, + NPC_WATCHER_SILTHIK = 28731 }; -#endif +enum GameObjectIds +{ + GO_KRIKTHIR_DOOR = 192395, + GO_ANUBARAK_DOOR_1 = 192396, + GO_ANUBARAK_DOOR_2 = 192397, + GO_ANUBARAK_DOOR_3 = 192398 +}; + +template<class AI> +AI* GetAzjolNerubAI(Creature* creature) +{ + return GetInstanceAI<AI>(creature, AzjolNerubScriptName); +} + +#endif // AZJOL_NERUB_H_ diff --git a/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_anubarak.cpp b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_anubarak.cpp index 05e758f5cf9..81530265617 100644 --- a/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_anubarak.cpp +++ b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_anubarak.cpp @@ -132,7 +132,7 @@ public: if (instance) { - instance->SetData(DATA_ANUBARAK_EVENT, NOT_STARTED); + instance->SetBossState(DATA_ANUBARAK, NOT_STARTED); instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); } } @@ -165,7 +165,7 @@ public: void DelayEventStart() { if (instance) - instance->SetData(DATA_ANUBARAK_EVENT, IN_PROGRESS); + instance->SetBossState(DATA_ANUBARAK, IN_PROGRESS); } void UpdateAI(uint32 diff) OVERRIDE @@ -336,7 +336,7 @@ public: Talk(SAY_DEATH); Summons.DespawnAll(); if (instance) - instance->SetData(DATA_ANUBARAK_EVENT, DONE); + instance->SetBossState(DATA_ANUBARAK, DONE); } void KilledUnit(Unit* victim) OVERRIDE diff --git a/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_hadronox.cpp b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_hadronox.cpp index 6b556f4fe4d..1664a1375ae 100644 --- a/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_hadronox.cpp +++ b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_hadronox.cpp @@ -84,8 +84,8 @@ public: uiDoorsTimer = urand(20*IN_MILLISECONDS, 30*IN_MILLISECONDS); uiCheckDistanceTimer = 2*IN_MILLISECONDS; - if (instance && (instance->GetData(DATA_HADRONOX_EVENT) != DONE && !bFirstTime)) - instance->SetData(DATA_HADRONOX_EVENT, FAIL); + if (instance && (instance->GetBossState(DATA_HADRONOX) != DONE && !bFirstTime)) + instance->SetBossState(DATA_HADRONOX, FAIL); bFirstTime = false; } @@ -103,13 +103,13 @@ public: void JustDied(Unit* /*killer*/) OVERRIDE { if (instance) - instance->SetData(DATA_HADRONOX_EVENT, DONE); + instance->SetBossState(DATA_HADRONOX, DONE); } void EnterCombat(Unit* /*who*/) OVERRIDE { if (instance) - instance->SetData(DATA_HADRONOX_EVENT, IN_PROGRESS); + instance->SetBossState(DATA_HADRONOX, IN_PROGRESS); me->SetInCombatWithZone(); } diff --git a/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_krikthir_the_gatewatcher.cpp b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_krikthir_the_gatewatcher.cpp index 2222d16f68b..c5e40052a9d 100644 --- a/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_krikthir_the_gatewatcher.cpp +++ b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_krikthir_the_gatewatcher.cpp @@ -105,7 +105,7 @@ public: uiCurseFatigueTimer = 12*IN_MILLISECONDS; if (instance) - instance->SetData(DATA_KRIKTHIR_THE_GATEWATCHER_EVENT, NOT_STARTED); + instance->SetBossState(DATA_KRIKTHIR_THE_GATEWATCHER, NOT_STARTED); } void EnterCombat(Unit* /*who*/) OVERRIDE @@ -115,7 +115,7 @@ public: uiSummonTimer = 15*IN_MILLISECONDS; if (instance) - instance->SetData(DATA_KRIKTHIR_THE_GATEWATCHER_EVENT, IN_PROGRESS); + instance->SetBossState(DATA_KRIKTHIR_THE_GATEWATCHER, IN_PROGRESS); } void Summon() @@ -176,7 +176,7 @@ public: Talk(SAY_DEATH); if (instance) - instance->SetData(DATA_KRIKTHIR_THE_GATEWATCHER_EVENT, DONE); + instance->SetBossState(DATA_KRIKTHIR_THE_GATEWATCHER, DONE); } void KilledUnit(Unit* victim) OVERRIDE @@ -537,15 +537,14 @@ class achievement_watch_him_die : public AchievementCriteriaScript return false; InstanceScript* instance = target->GetInstanceScript(); - Creature* Watcher[3]; if (!instance) return false; for (uint8 n = 0; n < 3; ++n) { - Watcher[n] = ObjectAccessor::GetCreature(*target, instance->GetData64(DATA_WATCHER_GASHRA + n)); - if (Watcher[n] && !Watcher[n]->IsAlive()) - return false; + if (Creature* watcher = ObjectAccessor::GetCreature(*target, instance->GetData64(DATA_WATCHER_GASHRA + n))) + if (!watcher->IsAlive()) + return false; } return true; diff --git a/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/instance_azjol_nerub.cpp b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/instance_azjol_nerub.cpp index 261a2748579..b20a28b7a75 100644 --- a/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/instance_azjol_nerub.cpp +++ b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/instance_azjol_nerub.cpp @@ -19,196 +19,171 @@ #include "InstanceScript.h" #include "azjol_nerub.h" -#define MAX_ENCOUNTER 3 - -/* Azjol Nerub encounters: -0 - Krik'thir the Gatewatcher -1 - Hadronox -2 - Anub'arak -*/ +DoorData const doorData[] = +{ + { GO_KRIKTHIR_DOOR, DATA_KRIKTHIR_THE_GATEWATCHER, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, + { GO_ANUBARAK_DOOR_1, DATA_ANUBARAK, DOOR_TYPE_ROOM, BOUNDARY_NONE }, + { GO_ANUBARAK_DOOR_2, DATA_ANUBARAK, DOOR_TYPE_ROOM, BOUNDARY_NONE }, + { GO_ANUBARAK_DOOR_3, DATA_ANUBARAK, DOOR_TYPE_ROOM, BOUNDARY_NONE }, + { 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE } // END +}; class instance_azjol_nerub : public InstanceMapScript { -public: - instance_azjol_nerub() : InstanceMapScript("instance_azjol_nerub", 601) { } - - struct instance_azjol_nerub_InstanceScript : public InstanceScript - { - instance_azjol_nerub_InstanceScript(Map* map) : InstanceScript(map) {} - - uint64 uiKrikthir; - uint64 uiHadronox; - uint64 uiAnubarak; - uint64 uiWatcherGashra; - uint64 uiWatcherSilthik; - uint64 uiWatcherNarjil; - uint64 uiAnubarakDoor[3]; - - uint64 uiKrikthirDoor; - - uint32 auiEncounter[MAX_ENCOUNTER]; - - void Initialize() OVERRIDE - { - memset(&auiEncounter, 0, sizeof(auiEncounter)); - memset(&uiAnubarakDoor, 0, sizeof(uiAnubarakDoor)); - - uiKrikthir = 0; - uiHadronox = 0; - uiAnubarak = 0; - uiWatcherGashra = 0; - uiWatcherSilthik = 0; - uiWatcherNarjil = 0; - uiKrikthirDoor = 0; - } + public: + instance_azjol_nerub() : InstanceMapScript(AzjolNerubScriptName, 601) { } - bool IsEncounterInProgress() const OVERRIDE + struct instance_azjol_nerub_InstanceScript : public InstanceScript { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (auiEncounter[i] == IN_PROGRESS) - return true; - - return false; - } - - void OnCreatureCreate(Creature* creature) OVERRIDE - { - switch (creature->GetEntry()) + instance_azjol_nerub_InstanceScript(Map* map) : InstanceScript(map) { - case 28684: uiKrikthir = creature->GetGUID(); break; - case 28921: uiHadronox = creature->GetGUID(); break; - case 29120: uiAnubarak = creature->GetGUID(); break; - case 28730: uiWatcherGashra = creature->GetGUID(); break; - case 28731: uiWatcherSilthik = creature->GetGUID(); break; - case 28729: uiWatcherNarjil = creature->GetGUID(); break; + SetBossNumber(EncounterCount); + LoadDoorData(doorData); + + KrikthirGUID = 0; + HadronoxGUID = 0; + AnubarakGUID = 0; + WatcherGashraGUID = 0; + WatcherSilthikGUID = 0; + WatcherNarjilGUID = 0; } - } - void OnGameObjectCreate(GameObject* go) OVERRIDE - { - switch (go->GetEntry()) + void OnCreatureCreate(Creature* creature) OVERRIDE { - case 192395: - uiKrikthirDoor = go->GetGUID(); - if (auiEncounter[0] == DONE) - HandleGameObject(0, true, go); - break; - case 192396: - uiAnubarakDoor[0] = go->GetGUID(); - break; - case 192397: - uiAnubarakDoor[1] = go->GetGUID(); - break; - case 192398: - uiAnubarakDoor[2] = go->GetGUID(); - break; + switch (creature->GetEntry()) + { + case NPC_KRIKTHIR: + KrikthirGUID = creature->GetGUID(); + break; + case NPC_HADRONOX: + HadronoxGUID = creature->GetGUID(); + break; + case NPC_ANUBARAK: + AnubarakGUID = creature->GetGUID(); + break; + case NPC_WATCHER_NARJIL: + WatcherNarjilGUID = creature->GetGUID(); + break; + case NPC_WATCHER_GASHRA: + WatcherGashraGUID = creature->GetGUID(); + break; + case NPC_WATCHER_SILTHIK: + WatcherSilthikGUID = creature->GetGUID(); + break; + default: + break; + } } - } - uint64 GetData64(uint32 identifier) const OVERRIDE - { - switch (identifier) + void OnGameObjectCreate(GameObject* go) OVERRIDE { - case DATA_KRIKTHIR_THE_GATEWATCHER: return uiKrikthir; - case DATA_HADRONOX: return uiHadronox; - case DATA_ANUBARAK: return uiAnubarak; - case DATA_WATCHER_GASHRA: return uiWatcherGashra; - case DATA_WATCHER_SILTHIK: return uiWatcherSilthik; - case DATA_WATCHER_NARJIL: return uiWatcherNarjil; + switch (go->GetEntry()) + { + case GO_KRIKTHIR_DOOR: + case GO_ANUBARAK_DOOR_1: + case GO_ANUBARAK_DOOR_2: + case GO_ANUBARAK_DOOR_3: + AddDoor(go, true); + break; + default: + break; + } } - return 0; - } - - void SetData(uint32 type, uint32 data) OVERRIDE - { - switch (type) + void OnGameObjectRemove(GameObject* go) OVERRIDE { - case DATA_KRIKTHIR_THE_GATEWATCHER_EVENT: - auiEncounter[0] = data; - if (data == DONE) - HandleGameObject(uiKrikthirDoor, true); - break; - case DATA_HADRONOX_EVENT: - auiEncounter[1] = data; - break; - case DATA_ANUBARAK_EVENT: - auiEncounter[2] = data; - if (data == IN_PROGRESS) - for (uint8 i = 0; i < 3; ++i) - HandleGameObject(uiAnubarakDoor[i], false); - else if (data == NOT_STARTED || data == DONE) - for (uint8 i = 0; i < 3; ++i) - HandleGameObject(uiAnubarakDoor[i], true); - break; + switch (go->GetEntry()) + { + case GO_KRIKTHIR_DOOR: + case GO_ANUBARAK_DOOR_1: + case GO_ANUBARAK_DOOR_2: + case GO_ANUBARAK_DOOR_3: + AddDoor(go, false); + break; + default: + break; + } } - if (data == DONE) + uint64 GetData64(uint32 type) const OVERRIDE { - SaveToDB(); + switch (type) + { + case DATA_KRIKTHIR_THE_GATEWATCHER: + return KrikthirGUID; + case DATA_HADRONOX: + return HadronoxGUID; + case DATA_ANUBARAK: + return AnubarakGUID; + case DATA_WATCHER_GASHRA: + return WatcherGashraGUID; + case DATA_WATCHER_SILTHIK: + return WatcherSilthikGUID; + case DATA_WATCHER_NARJIL: + return WatcherNarjilGUID; + default: + break; + } + + return 0; } - } - uint32 GetData(uint32 type) const OVERRIDE - { - switch (type) + std::string GetSaveData() OVERRIDE { - case DATA_KRIKTHIR_THE_GATEWATCHER_EVENT: return auiEncounter[0]; - case DATA_HADRONOX_EVENT: return auiEncounter[1]; - case DATA_ANUBARAK_EVENT: return auiEncounter[2]; - } - - return 0; - } - - std::string GetSaveData() OVERRIDE - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << "A N " << auiEncounter[0] << ' ' << auiEncounter[1] << ' ' - << auiEncounter[2]; + OUT_SAVE_INST_DATA; - OUT_SAVE_INST_DATA_COMPLETE; - return saveStream.str(); - } + std::ostringstream saveStream; + saveStream << "A N " << GetBossSaveData(); - void Load(const char* in) OVERRIDE - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; + OUT_SAVE_INST_DATA_COMPLETE; + return saveStream.str(); } - OUT_LOAD_INST_DATA(in); - - char dataHead1, dataHead2; - uint16 data0, data1, data2; - - std::istringstream loadStream(in); - loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2; - - if (dataHead1 == 'A' && dataHead2 == 'N') + void Load(char const* str) OVERRIDE { - auiEncounter[0] = data0; - auiEncounter[1] = data1; - auiEncounter[2] = data2; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (auiEncounter[i] == IN_PROGRESS) - auiEncounter[i] = NOT_STARTED; + if (!str) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(str); + + char dataHead1, dataHead2; + + std::istringstream loadStream(str); + loadStream >> dataHead1 >> dataHead2; + + if (dataHead1 == 'A' && dataHead2 == 'N') + { + for (uint32 i = 0; i < EncounterCount; ++i) + { + uint32 tmpState; + loadStream >> tmpState; + if (tmpState == IN_PROGRESS || tmpState > SPECIAL) + tmpState = NOT_STARTED; + SetBossState(i, EncounterState(tmpState)); + } + } + else + OUT_LOAD_INST_DATA_FAIL; + + OUT_LOAD_INST_DATA_COMPLETE; + } - } else OUT_LOAD_INST_DATA_FAIL; + protected: + uint64 KrikthirGUID; + uint64 HadronoxGUID; + uint64 AnubarakGUID; + uint64 WatcherGashraGUID; + uint64 WatcherSilthikGUID; + uint64 WatcherNarjilGUID; + }; - OUT_LOAD_INST_DATA_COMPLETE; + InstanceScript* GetInstanceScript(InstanceMap* map) const OVERRIDE + { + return new instance_azjol_nerub_InstanceScript(map); } - }; - - InstanceScript* GetInstanceScript(InstanceMap* map) const OVERRIDE - { - return new instance_azjol_nerub_InstanceScript(map); - } }; void AddSC_instance_azjol_nerub() diff --git a/src/server/scripts/Northrend/CMakeLists.txt b/src/server/scripts/Northrend/CMakeLists.txt index e04a4c43479..3c56361d096 100644 --- a/src/server/scripts/Northrend/CMakeLists.txt +++ b/src/server/scripts/Northrend/CMakeLists.txt @@ -125,11 +125,11 @@ set(scripts_STAT_SRCS Northrend/VaultOfArchavon/boss_emalon.cpp Northrend/VaultOfArchavon/boss_toravon.cpp Northrend/zone_sholazar_basin.cpp - Northrend/UtgardeKeep/UtgardePinnacle/boss_palehoof.cpp Northrend/UtgardeKeep/UtgardePinnacle/boss_svala.cpp - Northrend/UtgardeKeep/UtgardePinnacle/instance_pinnacle.cpp - Northrend/UtgardeKeep/UtgardePinnacle/boss_ymiron.cpp + Northrend/UtgardeKeep/UtgardePinnacle/boss_palehoof.cpp Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp + Northrend/UtgardeKeep/UtgardePinnacle/boss_ymiron.cpp + Northrend/UtgardeKeep/UtgardePinnacle/instance_utgarde_pinnacle.cpp Northrend/UtgardeKeep/UtgardePinnacle/utgarde_pinnacle.h Northrend/UtgardeKeep/UtgardeKeep/boss_ingvar_the_plunderer.cpp Northrend/UtgardeKeep/UtgardeKeep/boss_skarvald_dalronn.cpp diff --git a/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/boss_sartharion.cpp b/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/boss_sartharion.cpp index a9f92521ef8..1c1cdbdac53 100644 --- a/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/boss_sartharion.cpp +++ b/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/boss_sartharion.cpp @@ -1001,6 +1001,8 @@ public: void Reset() OVERRIDE { + dummy_dragonAI::Reset(); + m_uiShadowBreathTimer = 20000; m_uiShadowFissureTimer = 5000; m_uiHatchEggTimer = 30000; @@ -1090,6 +1092,8 @@ public: void Reset() OVERRIDE { + dummy_dragonAI::Reset(); + m_uiShadowBreathTimer = 20000; m_uiShadowFissureTimer = 5000; m_uiAcolyteShadronTimer = 60000; @@ -1194,6 +1198,8 @@ public: void Reset() OVERRIDE { + dummy_dragonAI::Reset(); + m_uiShadowBreathTimer = 20000; m_uiShadowFissureTimer = 5000; m_uiAcolyteVesperonTimer = 60000; @@ -1401,9 +1407,7 @@ public: { uiDespawnTimer = 28000; if (instance) - { me->AddAura(SPELL_TWILIGHT_SHIFT_ENTER, me); - } DoCast(me, SPELL_TWILIGHT_TORMENT_VESP_ACO); } @@ -1498,9 +1502,7 @@ public: void Reset() OVERRIDE { if (instance) - { me->AddAura(SPELL_TWILIGHT_SHIFT_ENTER, me); - } m_uiFadeArmorTimer = 1000; m_uiHatchEggTimer = 20000; } diff --git a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp index 189b1489940..f6223165b70 100644 --- a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp +++ b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp @@ -835,8 +835,6 @@ class npc_halion_controller : public CreatureScript _twilightDamageTaken = 0; return; } - default: - break; } _materialDamageTaken = 0; @@ -883,8 +881,6 @@ class npc_halion_controller : public CreatureScript InstanceScript* _instance; SummonList _summons; - bool _corporealityCheck; - uint32 _twilightDamageTaken; uint32 _materialDamageTaken; uint8 _materialCorporealityValue; @@ -1623,16 +1619,16 @@ class spell_halion_clear_debuffs : public SpellScriptLoader class TwilightCutterSelector { public: - TwilightCutterSelector(Unit* caster, Unit* cutterCaster) : _caster(caster), _cutterCaster(cutterCaster) {} + TwilightCutterSelector(Unit* caster, Unit* target) : _caster(caster), _channelTarget(target) {} bool operator()(WorldObject* unit) { - return !unit->IsInBetween(_caster, _cutterCaster, 4.0f); + return !unit->IsInBetween(_caster, _channelTarget, 4.0f); } private: Unit* _caster; - Unit* _cutterCaster; + Unit* _channelTarget; }; class spell_halion_twilight_cutter : public SpellScriptLoader @@ -1650,13 +1646,10 @@ class spell_halion_twilight_cutter : public SpellScriptLoader return; Unit* caster = GetCaster(); - if (Aura* cutter = caster->GetAura(SPELL_TWILIGHT_CUTTER)) + if (Unit* channelTarget = ObjectAccessor::GetUnit(*caster, caster->GetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT))) { - if (Unit* cutterCaster = cutter->GetCaster()) - { - unitList.remove_if(TwilightCutterSelector(caster, cutterCaster)); - return; - } + unitList.remove_if(TwilightCutterSelector(caster, channelTarget)); + return; } // In case cutter caster werent found for some reason diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp index f346c796976..53b11de921a 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp @@ -419,8 +419,6 @@ class boss_anubarak_trial : public CreatureScript uint64 _sphereGUID[6]; bool _intro; bool _reachedPhase3; - uint32 _frostSphereTimer; - uint32 _berserkTimer; }; CreatureAI* GetAI(Creature* creature) const OVERRIDE @@ -579,7 +577,6 @@ class npc_nerubian_burrower : public CreatureScript private: uint32 _submergeTimer; - Phases _phase; EventMap _events; InstanceScript* _instance; }; diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp index 50179d138ae..18cc45657f0 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp @@ -352,7 +352,7 @@ class npc_snobold_vassal : public CreatureScript void JustDied(Unit* /*killer*/) OVERRIDE { - if (Unit* target = Unit::GetPlayer(*me, _targetGUID)) + if (Unit* target = ObjectAccessor::GetPlayer(*me, _targetGUID)) if (target->IsAlive()) target->RemoveAurasDueToSpell(SPELL_SNOBOLLED); if (_instance) @@ -379,7 +379,7 @@ class npc_snobold_vassal : public CreatureScript if (!UpdateVictim() || _targetDied) return; - if (Unit* target = Unit::GetPlayer(*me, _targetGUID)) + if (Unit* target = ObjectAccessor::GetPlayer(*me, _targetGUID)) { if (!target->IsAlive()) { @@ -428,13 +428,13 @@ class npc_snobold_vassal : public CreatureScript return; case EVENT_HEAD_CRACK: // commented out while SPELL_SNOBOLLED gets fixed - //if (Unit* target = Unit::GetPlayer(*me, m_uiTargetGUID)) + //if (Unit* target = ObjectAccessor::GetPlayer(*me, m_uiTargetGUID)) DoCastVictim(SPELL_HEAD_CRACK); _events.ScheduleEvent(EVENT_HEAD_CRACK, 30*IN_MILLISECONDS); return; case EVENT_BATTER: // commented out while SPELL_SNOBOLLED gets fixed - //if (Unit* target = Unit::GetPlayer(*me, m_uiTargetGUID)) + //if (Unit* target = ObjectAccessor::GetPlayer(*me, m_uiTargetGUID)) DoCastVictim(SPELL_BATTER); _events.ScheduleEvent(EVENT_BATTER, 10*IN_MILLISECONDS); return; @@ -907,7 +907,7 @@ class boss_icehowl : public CreatureScript else { // Landed from Hop backwards (start trample) - if (Unit::GetPlayer(*me, _trampleTargetGUID)) + if (ObjectAccessor::GetPlayer(*me, _trampleTargetGUID)) _stage = 4; else _stage = 6; @@ -1046,7 +1046,7 @@ class boss_icehowl : public CreatureScript { case EVENT_TRAMPLE: { - if (Unit* target = Unit::GetPlayer(*me, _trampleTargetGUID)) + if (Unit* target = ObjectAccessor::GetPlayer(*me, _trampleTargetGUID)) { me->StopMoving(); me->AttackStop(); @@ -1135,7 +1135,6 @@ class boss_icehowl : public CreatureScript bool _movementFinish; bool _trampleCasted; uint8 _stage; - Unit* _target; }; CreatureAI* GetAI(Creature* creature) const OVERRIDE diff --git a/src/server/scripts/Northrend/DraktharonKeep/drak_tharon_keep.h b/src/server/scripts/Northrend/DraktharonKeep/drak_tharon_keep.h index 072a5f2f534..c2d957b7c0a 100644 --- a/src/server/scripts/Northrend/DraktharonKeep/drak_tharon_keep.h +++ b/src/server/scripts/Northrend/DraktharonKeep/drak_tharon_keep.h @@ -18,9 +18,6 @@ #ifndef DRAK_THARON_KEEP_H_ #define DRAK_THARON_KEEP_H_ -#include "Map.h" -#include "Creature.h" - #define DrakTharonKeepScriptName "instance_drak_tharon_keep" uint32 const EncounterCount = 4; @@ -89,11 +86,7 @@ enum GameObjectIds template<class AI> AI* GetDrakTharonKeepAI(Creature* creature) { - if (InstanceMap* instance = creature->GetMap()->ToInstanceMap()) - if (instance->GetInstanceScript()) - if (instance->GetScriptId() == sObjectMgr->GetScriptId(DrakTharonKeepScriptName)) - return new AI(creature); - return NULL; + return GetInstanceAI<AI>(creature, DrakTharonKeepScriptName); } #endif // DRAK_THARON_KEEP_H_ diff --git a/src/server/scripts/Northrend/DraktharonKeep/instance_drak_tharon_keep.cpp b/src/server/scripts/Northrend/DraktharonKeep/instance_drak_tharon_keep.cpp index 240e27ad026..d9e34ee2af3 100644 --- a/src/server/scripts/Northrend/DraktharonKeep/instance_drak_tharon_keep.cpp +++ b/src/server/scripts/Northrend/DraktharonKeep/instance_drak_tharon_keep.cpp @@ -36,7 +36,7 @@ class instance_drak_tharon_keep : public InstanceMapScript KingDredGUID = 0; TharonJaGUID = 0; - memset(TrollgoreInvaderSummonerGuids, 0, 4 * sizeof(uint64)); + memset(TrollgoreInvaderSummonerGuids, 0, 3 * sizeof(uint64)); memset(NovosCrystalGUIDs, 0, 4 * sizeof(uint64)); memset(NovosSummonerGUIDs, 0, 4 * sizeof(uint64)); } diff --git a/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_devourer_of_souls.cpp b/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_devourer_of_souls.cpp index b1ecdc5904e..7d923e7686f 100644 --- a/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_devourer_of_souls.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_devourer_of_souls.cpp @@ -403,21 +403,19 @@ class spell_devourer_of_souls_mirrored_soul_proc : public SpellScriptLoader bool Load() OVERRIDE { - _procTarget = NULL; return true; } bool CheckProc(ProcEventInfo& /*eventInfo*/) { - _procTarget = GetCaster(); - return _procTarget && _procTarget->IsAlive(); + return GetCaster() && GetCaster()->IsAlive(); } void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo) { PreventDefaultAction(); int32 damage = int32(CalculatePct(eventInfo.GetDamageInfo()->GetDamage(), 45)); - GetTarget()->CastCustomSpell(SPELL_MIRRORED_SOUL_DAMAGE, SPELLVALUE_BASE_POINT0, damage, _procTarget, true); + GetTarget()->CastCustomSpell(SPELL_MIRRORED_SOUL_DAMAGE, SPELLVALUE_BASE_POINT0, damage, GetCaster(), true); } void Register() OVERRIDE @@ -425,9 +423,6 @@ class spell_devourer_of_souls_mirrored_soul_proc : public SpellScriptLoader DoCheckProc += AuraCheckProcFn(spell_devourer_of_souls_mirrored_soul_proc_AuraScript::CheckProc); OnEffectProc += AuraEffectProcFn(spell_devourer_of_souls_mirrored_soul_proc_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL); } - - private: - Unit* _procTarget; }; AuraScript* GetAuraScript() const OVERRIDE diff --git a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp index 6408417e902..987807c2080 100644 --- a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp @@ -714,7 +714,9 @@ class npc_jaina_or_sylvanas_escape_hor : public CreatureScript // AI of Part2 struct npc_jaina_or_sylvanas_escape_horAI : public ScriptedAI { - npc_jaina_or_sylvanas_escape_horAI(Creature* creature) : ScriptedAI(creature) + npc_jaina_or_sylvanas_escape_horAI(Creature* creature) : ScriptedAI(creature), + _instance(creature->GetInstanceScript()), _lichkingGUID(0), _walltargetGUID(0), + _icewallGUID(0), _icewall(0), _isattackingwall(0) { _instance = me->GetInstanceScript(); } @@ -988,12 +990,15 @@ class npc_jaina_or_sylvanas_escape_hor : public CreatureScript lichking->SetReactState(REACT_PASSIVE); lichking->Attack(me,true); } - if (Creature* walltarget = me->SummonCreature(NPC_ICE_WALL, IceWalls[_icewall].GetPositionX(), IceWalls[_icewall].GetPositionY(), IceWalls[_icewall].GetPositionZ(), IceWalls[_icewall].GetOrientation(), TEMPSUMMON_MANUAL_DESPAWN, 720000)) + if (_icewall < 4) { - _walltargetGUID = walltarget->GetGUID(); - walltarget->AI()->DoCast(walltarget, SPELL_SUMMON_ICE_WALL); - walltarget->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); - me->Attack(walltarget,false); + if (Creature* walltarget = me->SummonCreature(NPC_ICE_WALL, IceWalls[_icewall].GetPositionX(), IceWalls[_icewall].GetPositionY(), IceWalls[_icewall].GetPositionZ(), IceWalls[_icewall].GetOrientation(), TEMPSUMMON_MANUAL_DESPAWN, 720000)) + { + _walltargetGUID = walltarget->GetGUID(); + walltarget->AI()->DoCast(walltarget, SPELL_SUMMON_ICE_WALL); + walltarget->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); + me->Attack(walltarget,false); + } } _events.ScheduleEvent(EVENT_ESCAPE_20, 3000); break; @@ -1014,7 +1019,7 @@ class npc_jaina_or_sylvanas_escape_hor : public CreatureScript else if (_icewall == 3) me->AI()->Talk(SAY_JAINA_ESCAPE_5); } - else if (_instance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE) + else if (_instance->GetData(DATA_TEAM_IN_INSTANCE) == HORDE) { if (_icewall == 1) me->AI()->Talk(SAY_SYLVANAS_ESCAPE_3); 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 40110b8a509..50600453368 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 @@ -79,20 +79,27 @@ public: { SetBossNumber(MAX_ENCOUNTER); events.Reset(); + _falricGUID = 0; _marwynGUID = 0; _jainaOrSylvanasPart1GUID = 0; + _jainaOrSylvanasPart2GUID = 0; + _lichkingPart1GUID = 0; _frostwornGeneralGUID = 0; + _frostmourneGUID = 0; _entranceDoorGUID = 0; _frostwornDoorGUID = 0; _arthasDoorGUID = 0; + _escapeDoorGUID = 0; + _caveGUID = 0; + _teamInInstance = 0; _waveCount = 0; - _mobsaticewall = 0; _introEvent = NOT_STARTED; _frostwornGeneral = NOT_STARTED; _escapeevent = NOT_STARTED; + _mobsaticewall = 0; } void OnPlayerEnter(Player* player) OVERRIDE diff --git a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_forgemaster_garfrost.cpp b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_forgemaster_garfrost.cpp index 4bb989bf2e4..20b7d39815f 100644 --- a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_forgemaster_garfrost.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_forgemaster_garfrost.cpp @@ -23,26 +23,26 @@ enum Yells { - SAY_AGGRO = 0, - SAY_PHASE2 = 1, - SAY_PHASE3 = 2, - SAY_DEATH = 3, - SAY_SLAY = 4, - SAY_THROW_SARONITE = 5, - SAY_CAST_DEEP_FREEZE = 6, - - SAY_TYRANNUS_DEATH = 0 + SAY_AGGRO = 0, + SAY_PHASE2 = 1, + SAY_PHASE3 = 2, + SAY_DEATH = 3, + SAY_SLAY = 4, + SAY_THROW_SARONITE = 5, + SAY_CAST_DEEP_FREEZE = 6, + + SAY_TYRANNUS_DEATH = 0 }; enum Spells { - SPELL_PERMAFROST = 70326, - SPELL_THROW_SARONITE = 68788, - SPELL_THUNDERING_STOMP = 68771, - SPELL_CHILLING_WAVE = 68778, - SPELL_DEEP_FREEZE = 70381, - SPELL_FORGE_MACE = 68785, - SPELL_FORGE_BLADE = 68774, + SPELL_PERMAFROST = 70326, + SPELL_THROW_SARONITE = 68788, + SPELL_THUNDERING_STOMP = 68771, + SPELL_CHILLING_WAVE = 68778, + SPELL_DEEP_FREEZE = 70381, + SPELL_FORGE_MACE = 68785, + SPELL_FORGE_BLADE = 68774 }; #define SPELL_PERMAFROST_HELPER RAID_MODE<uint32>(68786, 70336) @@ -50,9 +50,9 @@ enum Spells enum Phases { - PHASE_ONE = 1, - PHASE_TWO = 2, - PHASE_THREE = 3 + PHASE_ONE = 1, + PHASE_TWO = 2, + PHASE_THREE = 3 }; enum MiscData @@ -60,58 +60,45 @@ enum MiscData EQUIP_ID_SWORD = 49345, EQUIP_ID_MACE = 49344, ACHIEV_DOESNT_GO_TO_ELEVEN = 0, - POINT_FORGE = 0, + POINT_FORGE = 0 }; -Position const northForgePos = {722.5643f, -234.1615f, 527.182f, 2.16421f}; -Position const southForgePos = {639.257f, -210.1198f, 529.015f, 0.523599f}; - -class boss_garfrost : public CreatureScript -{ enum Events { - EVENT_THROW_SARONITE = 1, - EVENT_CHILLING_WAVE = 2, - EVENT_DEEP_FREEZE = 3, - EVENT_JUMP = 4, - EVENT_FORGING = 5, - EVENT_RESUME_ATTACK = 6, + EVENT_THROW_SARONITE = 1, + EVENT_CHILLING_WAVE = 2, + EVENT_DEEP_FREEZE = 3, + EVENT_FORGE_JUMP = 4, + EVENT_RESUME_ATTACK = 5 }; + +Position const northForgePos = { 722.5643f, -234.1615f, 527.182f, 2.16421f }; +Position const southForgePos = { 639.257f, -210.1198f, 529.015f, 0.523599f }; + +class boss_garfrost : public CreatureScript +{ public: boss_garfrost() : CreatureScript("boss_garfrost") { } struct boss_garfrostAI : public BossAI { - boss_garfrostAI(Creature* creature) : BossAI(creature, DATA_GARFROST) - { - } - - void InitializeAI() OVERRIDE - { - if (!instance || static_cast<InstanceMap*>(me->GetMap())->GetScriptId() != sObjectMgr->GetScriptId(PoSScriptName)) - me->IsAIEnabled = false; - else if (!me->isDead()) - Reset(); - } + boss_garfrostAI(Creature* creature) : BossAI(creature, DATA_GARFROST) { } void Reset() OVERRIDE { - events.Reset(); + _Reset(); events.SetPhase(PHASE_ONE); SetEquipmentSlots(true); _permafrostStack = 0; - - instance->SetBossState(DATA_GARFROST, NOT_STARTED); } void EnterCombat(Unit* /*who*/) OVERRIDE { + _EnterCombat(); Talk(SAY_AGGRO); DoCast(me, SPELL_PERMAFROST); me->CallForHelp(70.0f); events.ScheduleEvent(EVENT_THROW_SARONITE, 7000); - - instance->SetBossState(DATA_GARFROST, IN_PROGRESS); } void KilledUnit(Unit* victim) OVERRIDE @@ -122,12 +109,11 @@ enum Events void JustDied(Unit* /*killer*/) OVERRIDE { + _JustDied(); Talk(SAY_DEATH); if (Creature* tyrannus = me->GetCreature(*me, instance->GetData64(DATA_TYRANNUS))) tyrannus->AI()->Talk(SAY_TYRANNUS_DEATH); - - instance->SetBossState(DATA_GARFROST, DONE); } void DamageTaken(Unit* /*attacker*/, uint32& /*uiDamage*/) OVERRIDE @@ -138,7 +124,7 @@ enum Events Talk(SAY_PHASE2); events.DelayEvents(8000); DoCast(me, SPELL_THUNDERING_STOMP); - events.ScheduleEvent(EVENT_JUMP, 1500); + events.ScheduleEvent(EVENT_FORGE_JUMP, 1500); return; } @@ -148,7 +134,7 @@ enum Events Talk(SAY_PHASE3); events.DelayEvents(8000); DoCast(me, SPELL_THUNDERING_STOMP); - events.ScheduleEvent(EVENT_JUMP, 1500); + events.ScheduleEvent(EVENT_FORGE_JUMP, 1500); return; } } @@ -220,15 +206,15 @@ enum Events } events.ScheduleEvent(EVENT_DEEP_FREEZE, 35000, 0, PHASE_THREE); break; - case EVENT_JUMP: + case EVENT_FORGE_JUMP: me->AttackStop(); if (events.IsInPhase(PHASE_TWO)) - me->GetMotionMaster()->MoveJump(northForgePos.GetPositionX(), northForgePos.GetPositionY(), northForgePos.GetPositionZ(), 25.0f, 15.0f); + me->GetMotionMaster()->MoveJump(northForgePos, 25.0f, 15.0f, POINT_FORGE); else if (events.IsInPhase(PHASE_THREE)) - me->GetMotionMaster()->MoveJump(southForgePos.GetPositionX(), southForgePos.GetPositionY(), southForgePos.GetPositionZ(), 25.0f, 15.0f); + me->GetMotionMaster()->MoveJump(southForgePos, 25.0f, 15.0f, POINT_FORGE); break; case EVENT_RESUME_ATTACK: - if (events.IsInPhase(PHASE_THREE)) + if (events.IsInPhase(PHASE_TWO)) events.ScheduleEvent(EVENT_CHILLING_WAVE, 5000, 0, PHASE_TWO); else if (events.IsInPhase(PHASE_THREE)) events.ScheduleEvent(EVENT_DEEP_FREEZE, 10000, 0, PHASE_THREE); @@ -248,7 +234,7 @@ enum Events CreatureAI* GetAI(Creature* creature) const OVERRIDE { - return new boss_garfrostAI(creature); + return GetPitOfSaronAI<boss_garfrostAI>(creature); } }; diff --git a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_krickandick.cpp b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_krickandick.cpp index b738f0c9358..3b3f65c7704 100644 --- a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_krickandick.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_krickandick.cpp @@ -42,7 +42,7 @@ enum Spells SPELL_STRANGULATING = 69413, //krick's selfcast in intro SPELL_SUICIDE = 7, SPELL_KRICK_KILL_CREDIT = 71308, - SPELL_NECROMANTIC_POWER = 69753, + SPELL_NECROMANTIC_POWER = 69753 }; enum Yells @@ -71,7 +71,7 @@ enum Yells SAY_SYLVANAS_OUTRO_4 = 1, SAY_SYLVANAS_OUTRO_10 = 2, SAY_TYRANNUS_OUTRO_7 = 1, - SAY_TYRANNUS_OUTRO_9 = 2, + SAY_TYRANNUS_OUTRO_9 = 2 }; enum Events @@ -98,24 +98,24 @@ enum Events EVENT_OUTRO_11 = 18, EVENT_OUTRO_12 = 19, EVENT_OUTRO_13 = 20, - EVENT_OUTRO_END = 21, + EVENT_OUTRO_END = 21 }; enum KrickPhase { PHASE_COMBAT = 1, - PHASE_OUTRO = 2, + PHASE_OUTRO = 2 }; enum Actions { - ACTION_OUTRO = 1, + ACTION_OUTRO = 1 }; enum Points { POINT_KRICK_INTRO = 364770, - POINT_KRICK_DEATH = 364771, + POINT_KRICK_DEATH = 364771 }; static const Position outroPos[8] = @@ -127,7 +127,7 @@ static const Position outroPos[8] = {835.5887f, 139.4345f, 530.9526f, 0.0000000f}, // Tyrannus fly down Position (not sniffed) {828.9342f, 118.6247f, 514.5190f, 0.0000000f}, // Krick's Choke Position {828.9342f, 118.6247f, 509.4958f, 0.0000000f}, // Kirck's Death Position - {914.4820f, 143.1602f, 633.3624f, 0.0000000f}, // Tyrannus fly up (not sniffed) + {914.4820f, 143.1602f, 633.3624f, 0.0000000f} // Tyrannus fly up (not sniffed) }; class boss_ick : public CreatureScript @@ -142,14 +142,6 @@ class boss_ick : public CreatureScript ASSERT(_vehicle); } - void InitializeAI() OVERRIDE - { - if (!instance || static_cast<InstanceMap*>(me->GetMap())->GetScriptId() != sObjectMgr->GetScriptId(PoSScriptName)) - me->IsAIEnabled = false; - else if (!me->isDead()) - Reset(); - } - void Reset() OVERRIDE { events.Reset(); @@ -163,6 +155,8 @@ class boss_ick : public CreatureScript void EnterCombat(Unit* /*who*/) OVERRIDE { + _EnterCombat(); + if (Creature* krick = GetKrick()) krick->AI()->Talk(SAY_KRICK_AGGRO); @@ -170,8 +164,6 @@ class boss_ick : public CreatureScript events.ScheduleEvent(EVENT_TOXIC_WASTE, 5000); events.ScheduleEvent(EVENT_SHADOW_BOLT, 10000); events.ScheduleEvent(EVENT_SPECIAL, urand(30000, 35000)); - - instance->SetBossState(DATA_ICK, IN_PROGRESS); } void EnterEvadeMode() OVERRIDE @@ -281,7 +273,7 @@ class boss_ick : public CreatureScript CreatureAI* GetAI(Creature* creature) const OVERRIDE { - return new boss_ickAI(creature); + return GetPitOfSaronAI<boss_ickAI>(creature); } }; @@ -296,14 +288,6 @@ class boss_krick : public CreatureScript { } - void InitializeAI() OVERRIDE - { - if (!_instanceScript || static_cast<InstanceMap*>(me->GetMap())->GetScriptId() != sObjectMgr->GetScriptId(PoSScriptName)) - me->IsAIEnabled = false; - else if (!me->isDead()) - Reset(); - } - void Reset() OVERRIDE { _events.Reset(); @@ -509,7 +493,7 @@ class boss_krick : public CreatureScript CreatureAI* GetAI(Creature* creature) const OVERRIDE { - return new boss_krickAI(creature); + return GetPitOfSaronAI<boss_krickAI>(creature); } }; diff --git a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/instance_pit_of_saron.cpp b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/instance_pit_of_saron.cpp index a789d0c6a70..7aa8b123f98 100644 --- a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/instance_pit_of_saron.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/instance_pit_of_saron.cpp @@ -41,7 +41,7 @@ class instance_pit_of_saron : public InstanceMapScript { instance_pit_of_saron_InstanceScript(Map* map) : InstanceScript(map) { - SetBossNumber(MAX_ENCOUNTER); + SetBossNumber(EncounterCount); LoadDoorData(Doors); _garfrostGUID = 0; _krickGUID = 0; @@ -292,7 +292,7 @@ class instance_pit_of_saron : public InstanceMapScript if (dataHead1 == 'P' && dataHead2 == 'S') { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + for (uint8 i = 0; i < EncounterCount; ++i) { uint32 tmpState; loadStream >> tmpState; diff --git a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.h b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.h index a9b88ca3066..e7a3b069ce3 100644 --- a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.h +++ b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.h @@ -15,14 +15,12 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef DEF_PIT_OF_SARON_H -#define DEF_PIT_OF_SARON_H - -#include "Map.h" -#include "Creature.h" +#ifndef PIT_OF_SARON_H_ +#define PIT_OF_SARON_H_ #define PoSScriptName "instance_pit_of_saron" -#define MAX_ENCOUNTER 3 + +uint32 const EncounterCount = 3; enum DataTypes { @@ -37,7 +35,7 @@ enum DataTypes DATA_JAINA_SYLVANAS_1 = 5, // GUID of either Jaina or Sylvanas part 1, depending on team, as it's the same spawn. DATA_JAINA_SYLVANAS_2 = 6, // GUID of either Jaina or Sylvanas part 2, depending on team, as it's the same spawn. DATA_TYRANNUS_EVENT = 7, - DATA_TEAM_IN_INSTANCE = 8, + DATA_TEAM_IN_INSTANCE = 8 }; enum CreatureIds @@ -94,17 +92,13 @@ enum GameObjectIds { GO_SARONITE_ROCK = 196485, GO_ICE_WALL = 201885, - GO_HALLS_OF_REFLECTION_PORTCULLIS = 201848, + GO_HALLS_OF_REFLECTION_PORTCULLIS = 201848 }; template<class AI> AI* GetPitOfSaronAI(Creature* creature) { - if (InstanceMap* instance = creature->GetMap()->ToInstanceMap()) - if (instance->GetInstanceScript()) - if (instance->GetScriptId() == sObjectMgr->GetScriptId(PoSScriptName)) - return new AI(creature); - return NULL; + return GetInstanceAI<AI>(creature, PoSScriptName); } -#endif +#endif // PIT_OF_SARON_H_ diff --git a/src/server/scripts/Northrend/Gundrak/boss_slad_ran.cpp b/src/server/scripts/Northrend/Gundrak/boss_slad_ran.cpp index afd0e8a4342..0097fe8c4d7 100644 --- a/src/server/scripts/Northrend/Gundrak/boss_slad_ran.cpp +++ b/src/server/scripts/Northrend/Gundrak/boss_slad_ran.cpp @@ -256,8 +256,6 @@ public: } } else uiGripOfSladRanTimer -= diff; } - - InstanceScript* instance; }; }; @@ -278,8 +276,6 @@ public: uint32 uiVenomousBiteTimer; - InstanceScript* instance; - void Reset() OVERRIDE { uiVenomousBiteTimer = 2*IN_MILLISECONDS; diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp index 107b95c5990..bdab8f3fce6 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp @@ -157,7 +157,7 @@ class boss_blood_queen_lana_thel : public CreatureScript events.ScheduleEvent(EVENT_TWILIGHT_BLOODBOLT, urand(20000, 25000), EVENT_GROUP_NORMAL); events.ScheduleEvent(EVENT_AIR_PHASE, 124000 + uint32(Is25ManRaid() ? 3000 : 0)); CleanAuras(); - _offtank = NULL; + _offtankGUID = 0; _vampires.clear(); _creditBloodQuickening = false; _killMinchar = false; @@ -366,29 +366,33 @@ class boss_blood_queen_lana_thel : public CreatureScript if (me->GetVictim()) { Player* newOfftank = SelectRandomTarget(true); - if (_offtank != newOfftank) + if (newOfftank) { - _offtank = newOfftank; - if (_offtank) + if (_offtankGUID != newOfftank->GetGUID()) { + _offtankGUID = newOfftank->GetGUID(); + // both spells have SPELL_ATTR5_SINGLE_TARGET_SPELL, no manual removal needed - _offtank->CastSpell(me->GetVictim(), SPELL_BLOOD_MIRROR_DAMAGE, true); - me->GetVictim()->CastSpell(_offtank, SPELL_BLOOD_MIRROR_DUMMY, true); + newOfftank->CastSpell(me->GetVictim(), SPELL_BLOOD_MIRROR_DAMAGE, true); + me->GetVictim()->CastSpell(newOfftank, SPELL_BLOOD_MIRROR_DUMMY, true); DoCastVictim(SPELL_BLOOD_MIRROR_VISUAL); - if (Is25ManRaid() && _offtank->GetQuestStatus(QUEST_BLOOD_INFUSION) == QUEST_STATUS_INCOMPLETE && - _offtank->HasAura(SPELL_UNSATED_CRAVING) && !_offtank->HasAura(SPELL_THIRST_QUENCHED) && - !_offtank->HasAura(SPELL_GUSHING_WOUND)) - _offtank->CastSpell(_offtank, SPELL_GUSHING_WOUND, TRIGGERED_FULL_MASK); + if (Is25ManRaid() && newOfftank->GetQuestStatus(QUEST_BLOOD_INFUSION) == QUEST_STATUS_INCOMPLETE && + newOfftank->HasAura(SPELL_UNSATED_CRAVING) && !newOfftank->HasAura(SPELL_THIRST_QUENCHED) && + !newOfftank->HasAura(SPELL_GUSHING_WOUND)) + newOfftank->CastSpell(newOfftank, SPELL_GUSHING_WOUND, TRIGGERED_FULL_MASK); } } + else + _offtankGUID = 0; } events.ScheduleEvent(EVENT_BLOOD_MIRROR, 2500, EVENT_GROUP_CANCELLABLE); break; } case EVENT_DELIRIOUS_SLASH: - if (_offtank && !me->HasByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER)) - DoCast(_offtank, SPELL_DELIRIOUS_SLASH); + if (_offtankGUID && !me->HasByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER)) + if (Player* _offtank = ObjectAccessor::GetPlayer(*me, _offtankGUID)) + DoCast(_offtank, SPELL_DELIRIOUS_SLASH); events.ScheduleEvent(EVENT_DELIRIOUS_SLASH, urand(20000, 24000), EVENT_GROUP_NORMAL); break; case EVENT_PACT_OF_THE_DARKFALLEN: @@ -470,7 +474,7 @@ class boss_blood_queen_lana_thel : public CreatureScript for (std::list<HostileReference*>::const_iterator itr = threatlist.begin(); itr != threatlist.end(); ++itr) if (Unit* refTarget = (*itr)->getTarget()) - if (refTarget != me->GetVictim() && refTarget->GetTypeId() == TYPEID_PLAYER && (includeOfftank || (refTarget != _offtank))) + if (refTarget != me->GetVictim() && refTarget->GetTypeId() == TYPEID_PLAYER && (includeOfftank || (refTarget->GetGUID() != _offtankGUID))) tempTargets.push_back(refTarget->ToPlayer()); if (tempTargets.empty()) @@ -493,7 +497,7 @@ class boss_blood_queen_lana_thel : public CreatureScript std::set<uint64> _vampires; std::set<uint64> _bloodboltedPlayers; - Player* _offtank; + uint64 _offtankGUID; bool _creditBloodQuickening; bool _killMinchar; }; diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_festergut.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_festergut.cpp index bf85fe455c7..68df37f0fdd 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_festergut.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_festergut.cpp @@ -206,15 +206,27 @@ class boss_festergut : public CreatureScript } case EVENT_VILE_GAS: { - std::list<Unit*> targets; + std::list<Unit*> ranged, melee; uint32 minTargets = RAID_MODE<uint32>(3, 8, 3, 8); - SelectTargetList(targets, minTargets, SELECT_TARGET_RANDOM, -5.0f, true); - float minDist = 0.0f; - if (targets.size() >= minTargets) - minDist = -5.0f; + SelectTargetList(ranged, 25, SELECT_TARGET_RANDOM, -5.0f, true); + SelectTargetList(melee, 25, SELECT_TARGET_RANDOM, 5.0f, true); + while (ranged.size() < minTargets) + { + if (melee.empty()) + break; + + Unit* target = Trinity::Containers::SelectRandomContainerElement(melee); + ranged.push_back(target); + melee.remove(target); + } + + if (!ranged.empty()) + { + Trinity::Containers::RandomResizeList(ranged, RAID_MODE<uint32>(1, 3, 1, 3)); + for (std::list<Unit*>::iterator itr = ranged.begin(); itr != ranged.end(); ++itr) + DoCast(*itr, SPELL_VILE_GAS); + } - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, minDist, true)) - DoCast(target, SPELL_VILE_GAS); events.ScheduleEvent(EVENT_VILE_GAS, urand(28000, 35000)); break; } diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp index 8e783fa9361..96627548848 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp @@ -55,10 +55,8 @@ enum Spells SPELL_GASEOUS_BLIGHT_LARGE = 69157, SPELL_GASEOUS_BLIGHT_MEDIUM = 69162, SPELL_GASEOUS_BLIGHT_SMALL = 69164, - SPELL_MALLABLE_GOO_H = 70852, - - // Rotface - SPELL_VILE_GAS_H = 69240, + SPELL_MALLEABLE_GOO_H = 72296, + SPELL_MALLEABLE_GOO_SUMMON = 72299, // Professor Putricide SPELL_SLIME_PUDDLE_TRIGGER = 70341, @@ -122,7 +120,6 @@ enum Events // Rotface EVENT_ROTFACE_DIES = 3, - EVENT_ROTFACE_VILE_GAS = 4, EVENT_ROTFACE_OOZE_FLOOD = 5, // Professor Putricide @@ -305,6 +302,9 @@ class boss_professor_putricide : public CreatureScript summons.Summon(summon); switch (summon->GetEntry()) { + case NPC_MALLEABLE_OOZE_STALKER: + DoCast(summon, SPELL_MALLEABLE_GOO_H); + return; case NPC_GROWING_OOZE_PUDDLE: summon->CastSpell(summon, SPELL_GROW_STACKER, true); summon->CastSpell(summon, SPELL_SLIME_PUDDLE_AURA, true); @@ -424,7 +424,7 @@ class boss_professor_putricide : public CreatureScript me->SetReactState(REACT_PASSIVE); DoZoneInCombat(me); if (IsHeroic()) - events.ScheduleEvent(EVENT_FESTERGUT_GOO, urand(15000, 20000), 0, PHASE_FESTERGUT); + events.ScheduleEvent(EVENT_FESTERGUT_GOO, urand(13000, 18000), 0, PHASE_FESTERGUT); break; case ACTION_FESTERGUT_GAS: Talk(SAY_FESTERGUT_GASEOUS_BLIGHT); @@ -441,8 +441,6 @@ class boss_professor_putricide : public CreatureScript me->SetReactState(REACT_PASSIVE); _oozeFloodStage = 0; DoZoneInCombat(me); - if (IsHeroic()) - events.ScheduleEvent(EVENT_ROTFACE_VILE_GAS, urand(15000, 20000), 0, PHASE_ROTFACE); // init random sequence of floods if (Creature* rotface = Unit::GetCreature(*me, instance->GetData64(DATA_ROTFACE))) { @@ -582,19 +580,13 @@ class boss_professor_putricide : public CreatureScript EnterEvadeMode(); break; case EVENT_FESTERGUT_GOO: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, NonTankTargetSelector(me))) - DoCast(target, SPELL_MALLABLE_GOO_H, true); // triggered, to skip LoS check - events.ScheduleEvent(EVENT_FESTERGUT_GOO, urand(15000, 20000), 0, PHASE_FESTERGUT); + me->CastCustomSpell(SPELL_MALLEABLE_GOO_SUMMON, SPELLVALUE_MAX_TARGETS, 1, NULL, true); + events.ScheduleEvent(EVENT_FESTERGUT_GOO, (Is25ManRaid() ? 10000 : 30000) + urand(0, 5000), 0, PHASE_FESTERGUT); break; case EVENT_ROTFACE_DIES: Talk(SAY_ROTFACE_DEATH); EnterEvadeMode(); break; - case EVENT_ROTFACE_VILE_GAS: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, NonTankTargetSelector(me))) - DoCast(target, SPELL_VILE_GAS_H, true); // triggered, to skip LoS check - events.ScheduleEvent(EVENT_ROTFACE_VILE_GAS, urand(15000, 20000), 0, PHASE_ROTFACE); - break; case EVENT_ROTFACE_OOZE_FLOOD: DoAction(ACTION_ROTFACE_OOZE); events.ScheduleEvent(EVENT_ROTFACE_OOZE_FLOOD, 25000, 0, PHASE_ROTFACE); @@ -955,7 +947,7 @@ class spell_putricide_slime_puddle : public SpellScriptLoader void ScaleRange(std::list<WorldObject*>& targets) { - targets.remove_if(ExactDistanceCheck(GetCaster(), 2.5f * GetCaster()->GetFloatValue(OBJECT_FIELD_SCALE_X))); + targets.remove_if(ExactDistanceCheck(GetCaster(), 2.5f * GetCaster()->GetObjectScale())); } void Register() OVERRIDE diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_rotface.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_rotface.cpp index 97385b108b6..eddc67b5f5e 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_rotface.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_rotface.cpp @@ -46,6 +46,7 @@ enum Spells // Rotface SPELL_SLIME_SPRAY = 69508, // every 20 seconds SPELL_MUTATED_INFECTION = 69674, // hastens every 1:30 + SPELL_VILE_GAS_TRIGGER_SUMMON = 72287, // Oozes SPELL_LITTLE_OOZE_COMBINE = 69537, // combine 2 Small Oozes @@ -64,6 +65,10 @@ enum Spells SPELL_MORTAL_WOUND = 71127, SPELL_DECIMATE = 71123, SPELL_AWAKEN_PLAGUED_ZOMBIES = 71159, + + // Professor Putricide + SPELL_VILE_GAS_H = 72272, + SPELL_VILE_GAS_TRIGGER = 72285, }; #define MUTATED_INFECTION RAID_MODE<int32>(69674, 71224, 73022, 73023) @@ -74,13 +79,14 @@ enum Events EVENT_SLIME_SPRAY = 1, EVENT_HASTEN_INFECTIONS = 2, EVENT_MUTATED_INFECTION = 3, + EVENT_VILE_GAS = 4, // Precious - EVENT_DECIMATE = 4, - EVENT_MORTAL_WOUND = 5, - EVENT_SUMMON_ZOMBIES = 6, + EVENT_DECIMATE = 5, + EVENT_MORTAL_WOUND = 6, + EVENT_SUMMON_ZOMBIES = 7, - EVENT_STICKY_OOZE = 7, + EVENT_STICKY_OOZE = 8, }; class boss_rotface : public CreatureScript @@ -102,6 +108,9 @@ class boss_rotface : public CreatureScript events.ScheduleEvent(EVENT_SLIME_SPRAY, 20000); events.ScheduleEvent(EVENT_HASTEN_INFECTIONS, 90000); events.ScheduleEvent(EVENT_MUTATED_INFECTION, 14000); + if (IsHeroic()) + events.ScheduleEvent(EVENT_VILE_GAS, urand(22000, 27000)); + infectionStage = 0; infectionCooldown = 14000; } @@ -119,7 +128,9 @@ class boss_rotface : public CreatureScript Talk(SAY_AGGRO); if (Creature* professor = Unit::GetCreature(*me, instance->GetData64(DATA_PROFESSOR_PUTRICIDE))) professor->AI()->DoAction(ACTION_ROTFACE_COMBAT); + DoZoneInCombat(); + DoCast(me, SPELL_GREEN_ABOMINATION_HITTIN__YA_PROC, true); } void JustDied(Unit* /*killer*/) OVERRIDE @@ -158,11 +169,17 @@ class boss_rotface : public CreatureScript } void MoveInLineOfSight(Unit* /*who*/) OVERRIDE - { // don't enter combat } + void JustSummoned(Creature* summon) OVERRIDE + { + if (summon->GetEntry() == NPC_VILE_GAS_STALKER) + if (Creature* professor = Unit::GetCreature(*me, instance->GetData64(DATA_PROFESSOR_PUTRICIDE))) + professor->CastSpell(summon, SPELL_VILE_GAS_H, true); + } + void UpdateAI(uint32 diff) OVERRIDE { if (!UpdateVictim() || !CheckInRoom()) @@ -197,6 +214,10 @@ class boss_rotface : public CreatureScript me->CastCustomSpell(SPELL_MUTATED_INFECTION, SPELLVALUE_MAX_TARGETS, 1, NULL, false); events.ScheduleEvent(EVENT_MUTATED_INFECTION, infectionCooldown); break; + case EVENT_VILE_GAS: + DoCastAOE(SPELL_VILE_GAS_TRIGGER); + events.ScheduleEvent(EVENT_VILE_GAS, urand(30000, 35000)); + break; default: break; } @@ -231,6 +252,7 @@ class npc_little_ooze : public CreatureScript { DoCast(me, SPELL_LITTLE_OOZE_COMBINE, true); DoCast(me, SPELL_WEAK_RADIATING_OOZE, true); + DoCast(me, SPELL_GREEN_ABOMINATION_HITTIN__YA_PROC, true); events.ScheduleEvent(EVENT_STICKY_OOZE, 5000); me->AddThreat(summoner, 500000.0f); } @@ -775,6 +797,71 @@ class spell_rotface_unstable_ooze_explosion_suicide : public SpellScriptLoader } }; +class spell_rotface_vile_gas_trigger : public SpellScriptLoader +{ + public: + spell_rotface_vile_gas_trigger() : SpellScriptLoader("spell_rotface_vile_gas_trigger") { } + + class spell_rotface_vile_gas_trigger_SpellScript : public SpellScript + { + PrepareSpellScript(spell_rotface_vile_gas_trigger_SpellScript); + + void FilterTargets(std::list<WorldObject*>& targets) + { + targets.sort(Trinity::ObjectDistanceOrderPred(GetCaster())); + if (targets.empty()) + return; + + std::list<WorldObject*> ranged, melee; + std::list<WorldObject*>::iterator itr = targets.begin(); + while (itr != targets.end() && (*itr)->GetDistance(GetCaster()) < 5.0f) + { + melee.push_back((*itr)->ToUnit()); + ++itr; + } + + while (itr != targets.end()) + { + ranged.push_back((*itr)->ToUnit()); + ++itr; + } + + uint32 minTargets = GetCaster()->GetMap()->Is25ManRaid() ? 8 : 3; + while (ranged.size() < minTargets) + { + if (melee.empty()) + break; + + WorldObject* target = Trinity::Containers::SelectRandomContainerElement(melee); + ranged.push_back(target); + melee.remove(target); + } + + if (!ranged.empty()) + Trinity::Containers::RandomResizeList(ranged, GetCaster()->GetMap()->Is25ManRaid() ? 3 : 1); + + targets.swap(ranged); + } + + void HandleDummy(SpellEffIndex effIndex) + { + PreventHitDefaultEffect(effIndex); + GetCaster()->CastSpell(GetHitUnit(), SPELL_VILE_GAS_TRIGGER_SUMMON); + } + + void Register() + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_rotface_vile_gas_trigger_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + OnEffectHitTarget += SpellEffectFn(spell_rotface_vile_gas_trigger_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_rotface_vile_gas_trigger_SpellScript(); + } +}; + void AddSC_boss_rotface() { new boss_rotface(); @@ -789,4 +876,5 @@ void AddSC_boss_rotface() new spell_rotface_unstable_ooze_explosion_init(); new spell_rotface_unstable_ooze_explosion(); new spell_rotface_unstable_ooze_explosion_suicide(); + new spell_rotface_vile_gas_trigger(); } diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp index 999e7081d52..1b03022c9bd 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp @@ -196,6 +196,22 @@ class FrostBombExplosion : public BasicEvent uint64 _sindragosaGUID; }; +class FrostBeaconSelector +{ + public: + FrostBeaconSelector(Unit* source) : _source(source) { } + + bool operator()(Unit* target) const + { + return target->GetTypeId() == TYPEID_PLAYER && + target != _source->GetVictim() && + !target->HasAura(SPELL_ICE_TOMB_UNTARGETABLE); + } + + private: + Unit* _source; +}; + class boss_sindragosa : public CreatureScript { public: @@ -466,7 +482,7 @@ class boss_sindragosa : public CreatureScript me->GetMotionMaster()->MovePoint(POINT_AIR_PHASE_FAR, SindragosaAirPosFar); break; case EVENT_ICE_TOMB: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true, -SPELL_ICE_TOMB_UNTARGETABLE)) + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, FrostBeaconSelector(me))) { Talk(EMOTE_WARN_FROZEN_ORB, target->GetGUID()); DoCast(target, SPELL_ICE_TOMB_DUMMY, true); diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp index b3f0d4131c4..8ee9a1188c0 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp @@ -2425,12 +2425,12 @@ class spell_the_lich_king_defile : public SpellScriptLoader void CorrectRange(std::list<WorldObject*>& targets) { - targets.remove_if(ExactDistanceCheck(GetCaster(), 10.0f * GetCaster()->GetFloatValue(OBJECT_FIELD_SCALE_X))); + targets.remove_if(ExactDistanceCheck(GetCaster(), 10.0f * GetCaster()->GetObjectScale())); } void ChangeDamageAndGrow() { - SetHitDamage(int32(GetHitDamage() * GetCaster()->GetFloatValue(OBJECT_FIELD_SCALE_X))); + SetHitDamage(int32(GetHitDamage() * GetCaster()->GetObjectScale())); // HACK: target player should cast this spell on defile // however with current aura handling auras cast by different units // cannot stack on the same aura object increasing the stack count diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp index 557d6768790..bbd700b7edd 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp @@ -493,7 +493,7 @@ class npc_green_dragon_combat_trigger : public CreatureScript struct npc_green_dragon_combat_triggerAI : public BossAI { - npc_green_dragon_combat_triggerAI(Creature* creature) : BossAI(creature, DATA_VALITHRIA_DREAMWALKER) + npc_green_dragon_combat_triggerAI(Creature* creature) : BossAI(creature, DATA_VALITHRIA_DREAMWALKER), _evadeCheck(false) { } diff --git a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h index e328658b9af..6090d4b8368 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h +++ b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.h @@ -183,12 +183,14 @@ enum CreaturesIds // Festergut NPC_FESTERGUT = 36626, NPC_GAS_DUMMY = 36659, + NPC_MALLEABLE_OOZE_STALKER = 38556, // Rotface NPC_ROTFACE = 36627, NPC_OOZE_SPRAY_STALKER = 37986, NPC_PUDDLE_STALKER = 37013, NPC_UNSTABLE_EXPLOSION_STALKER = 38107, + NPC_VILE_GAS_STALKER = 38548, // Professor Putricide NPC_PROFESSOR_PUTRICIDE = 36678, diff --git a/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp b/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp index 5578d199ec3..a77b21a900b 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp @@ -283,6 +283,18 @@ public: SummonList spawns; // adds spawn by the trigger. kept in separated list (i.e. not in summons) + void ResetPlayerScale() + { + std::map<uint64, float>::const_iterator itr; + for (itr = chained.begin(); itr != chained.end(); ++itr) + { + if (Player* charmed = ObjectAccessor::GetPlayer(*me, itr->first)) + charmed->SetObjectScale(itr->second); + } + + chained.clear(); + } + void Reset() OVERRIDE { _Reset(); @@ -292,14 +304,8 @@ public: me->setFaction(35); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_NOT_SELECTABLE); - std::map<uint64, float>::const_iterator itr; - for (itr = chained.begin(); itr != chained.end(); ++itr) - { - if (Player* charmed = Unit::GetPlayer(*me, (*itr).first)) - charmed->SetObjectScale((*itr).second); - } - chained.clear(); + ResetPlayerScale(); spawns.DespawnAll(); FindGameObjects(); @@ -340,13 +346,7 @@ public: _JustDied(); Talk(SAY_DEATH); - std::map<uint64, float>::const_iterator itr; - for (itr = chained.begin(); itr != chained.end(); ++itr) - { - if (Player* player = Unit::GetPlayer(*me, (*itr).first)) - player->SetObjectScale((*itr).second); - } - chained.clear(); + ResetPlayerScale(); } void EnterCombat(Unit* /*who*/) OVERRIDE @@ -507,7 +507,7 @@ public: if (target && !target->IsCharmed() && (chained.find(target->GetGUID()) == chained.end())) { DoCast(target, SPELL_CHAINS_OF_KELTHUZAD); - float scale = target->GetFloatValue(OBJECT_FIELD_SCALE_X); + float scale = target->GetObjectScale(); chained.insert(std::make_pair(target->GetGUID(), scale)); target->SetObjectScale(scale * 2); events.ScheduleEvent(EVENT_CHAINED_SPELL, 2000); //core has 2000ms to set unit flag charm @@ -523,11 +523,11 @@ public: std::map<uint64, float>::iterator itr; for (itr = chained.begin(); itr != chained.end();) { - if (Unit* player = Unit::GetPlayer(*me, (*itr).first)) + if (Unit* player = ObjectAccessor::GetPlayer(*me, itr->first)) { if (!player->IsCharmed()) { - player->SetObjectScale((*itr).second); + player->SetObjectScale(itr->second); std::map<uint64, float>::iterator next = itr; ++next; chained.erase(itr); diff --git a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp index 629f9b309e4..c073ec28a2b 100644 --- a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp +++ b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp @@ -1967,7 +1967,7 @@ class spell_arcane_overload : public SpellScriptLoader { Creature* arcaneOverload = GetCaster()->ToCreature(); targets.remove_if(ExactDistanceCheck(arcaneOverload, - GetSpellInfo()->Effects[EFFECT_0].CalcRadius(arcaneOverload) * arcaneOverload->GetFloatValue(OBJECT_FIELD_SCALE_X))); + GetSpellInfo()->Effects[EFFECT_0].CalcRadius(arcaneOverload) * arcaneOverload->GetObjectScale())); } void Register() OVERRIDE diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_bjarngrim.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_bjarngrim.cpp index 2077049641f..944eacda34e 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_bjarngrim.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_bjarngrim.cpp @@ -181,7 +181,7 @@ public: SetEquipmentSlots(false, EQUIP_SWORD, EQUIP_SHIELD, EQUIP_NO_CHANGE); if (instance) - instance->SetData(TYPE_BJARNGRIM, NOT_STARTED); + instance->SetBossState(DATA_BJARNGRIM, NOT_STARTED); } void EnterEvadeMode() OVERRIDE @@ -202,7 +202,7 @@ public: me->CallForHelp(30.0f); if (instance) - instance->SetData(TYPE_BJARNGRIM, IN_PROGRESS); + instance->SetBossState(DATA_BJARNGRIM, IN_PROGRESS); } void KilledUnit(Unit* /*victim*/) OVERRIDE @@ -215,7 +215,7 @@ public: Talk(SAY_DEATH); if (instance) - instance->SetData(TYPE_BJARNGRIM, DONE); + instance->SetBossState(DATA_BJARNGRIM, DONE); } /// @todo remove when removal is done by the core diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp index dfb21edf9af..af6beca608d 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp @@ -116,7 +116,7 @@ public: me->SetVisible(true); if (instance) - instance->SetData(TYPE_IONAR, NOT_STARTED); + instance->SetBossState(DATA_IONAR, NOT_STARTED); } void EnterCombat(Unit* /*who*/) OVERRIDE @@ -124,7 +124,7 @@ public: Talk(SAY_AGGRO); if (instance) - instance->SetData(TYPE_IONAR, IN_PROGRESS); + instance->SetBossState(DATA_IONAR, IN_PROGRESS); } void JustDied(Unit* /*killer*/) OVERRIDE @@ -134,7 +134,7 @@ public: lSparkList.DespawnAll(); if (instance) - instance->SetData(TYPE_IONAR, DONE); + instance->SetBossState(DATA_IONAR, DONE); } void KilledUnit(Unit* /*victim*/) OVERRIDE @@ -338,7 +338,7 @@ public: void UpdateAI(uint32 uiDiff) OVERRIDE { // Despawn if the encounter is not running - if (instance && instance->GetData(TYPE_IONAR) != IN_PROGRESS) + if (instance && instance->GetBossState(DATA_IONAR) != IN_PROGRESS) { me->DespawnOrUnsummon(); return; diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_loken.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_loken.cpp index d8ab71870a8..61687de1b58 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_loken.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_loken.cpp @@ -97,7 +97,7 @@ public: if (instance) { - instance->SetData(TYPE_LOKEN, NOT_STARTED); + instance->SetBossState(DATA_LOKEN, NOT_STARTED); instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMELY_DEATH_START_EVENT); } } @@ -108,7 +108,7 @@ public: if (instance) { - instance->SetData(TYPE_LOKEN, IN_PROGRESS); + instance->SetBossState(DATA_LOKEN, IN_PROGRESS); instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMELY_DEATH_START_EVENT); } } @@ -119,7 +119,7 @@ public: if (instance) { - instance->SetData(TYPE_LOKEN, DONE); + instance->SetBossState(DATA_LOKEN, DONE); instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_PULSING_SHOCKWAVE_AURA); } } @@ -140,6 +140,7 @@ public: if (m_uiResumePulsingShockwave_Timer <= uiDiff) { DoCast(me, SPELL_PULSING_SHOCKWAVE_AURA, true); + me->ClearUnitState(UNIT_STATE_CASTING); // this flag breaks movement DoCast(me, SPELL_PULSING_SHOCKWAVE_N, true); m_uiResumePulsingShockwave_Timer = 0; diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp index 725293a7e60..b6790a088ad 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp @@ -121,7 +121,7 @@ public: m_lGolemGUIDList.clear(); if (instance) - instance->SetData(TYPE_VOLKHAN, NOT_STARTED); + instance->SetBossState(DATA_VOLKHAN, NOT_STARTED); } void EnterCombat(Unit* /*who*/) OVERRIDE @@ -129,7 +129,7 @@ public: Talk(SAY_AGGRO); if (instance) - instance->SetData(TYPE_VOLKHAN, IN_PROGRESS); + instance->SetBossState(DATA_VOLKHAN, IN_PROGRESS); } void AttackStart(Unit* who) OVERRIDE @@ -151,7 +151,7 @@ public: DespawnGolem(); if (instance) - instance->SetData(TYPE_VOLKHAN, DONE); + instance->SetBossState(DATA_VOLKHAN, DONE); } void KilledUnit(Unit* /*victim*/) OVERRIDE diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/halls_of_lightning.h b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/halls_of_lightning.h index c45feab1e8a..17c049e8292 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/halls_of_lightning.h +++ b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/halls_of_lightning.h @@ -1,6 +1,5 @@ /* * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/> * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -16,22 +15,20 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef DEF_HALLS_OF_LIGHTNING_H -#define DEF_HALLS_OF_LIGHTNING_H +#ifndef HALLS_OF_LIGHTNING_H_ +#define HALLS_OF_LIGHTNING_H_ -enum Types -{ - MAX_ENCOUNTER = 4, +#define HoLScriptName "instance_halls_of_lightning" - DATA_BJARNGRIM = 1, - DATA_IONAR = 2, - DATA_LOKEN = 3, - DATA_VOLKHAN = 4, +uint32 const EncounterCount = 4; - TYPE_BJARNGRIM = 10, - TYPE_IONAR = 11, - TYPE_LOKEN = 12, - TYPE_VOLKHAN = 13, +enum DataTypes +{ + // Encounter States/Boss GUIDs + DATA_BJARNGRIM = 0, + DATA_VOLKHAN = 1, + DATA_IONAR = 2, + DATA_LOKEN = 3 }; enum CreaturesIds @@ -44,11 +41,17 @@ enum CreaturesIds enum GameObjectIds { - GO_BJARNGRIM_DOOR = 191416, //_doors10 - GO_VOLKHAN_DOOR = 191325, //_doors07 - GO_IONAR_DOOR = 191326, //_doors05 - GO_LOKEN_DOOR = 191324, //_doors02 + GO_BJARNGRIM_DOOR = 191416, + GO_VOLKHAN_DOOR = 191325, + GO_IONAR_DOOR = 191326, + GO_LOKEN_DOOR = 191324, GO_LOKEN_THRONE = 192654 }; -#endif +template<class AI> +AI* GetHallsOfLightningAI(Creature* creature) +{ + return GetInstanceAI<AI>(creature, HoLScriptName); +} + +#endif // HALLS_OF_LIGHTNING_H_ diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/instance_halls_of_lightning.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/instance_halls_of_lightning.cpp index e6d2ededd73..394fbc84253 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/instance_halls_of_lightning.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/instance_halls_of_lightning.cpp @@ -1,6 +1,5 @@ /* * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/> * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -16,240 +15,183 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -/* ScriptData -SDName: Instance_Halls_of_Lightning -SD%Complete: 90% -SDComment: All ready. -SDCategory: Halls of Lightning -EndScriptData */ - #include "ScriptMgr.h" #include "InstanceScript.h" #include "halls_of_lightning.h" -/* Halls of Lightning encounters: -0 - General Bjarngrim -1 - Volkhan -2 - Ionar -3 - Loken -*/ +DoorData const doorData[] = +{ + { GO_VOLKHAN_DOOR, DATA_VOLKHAN, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, + { GO_IONAR_DOOR, DATA_IONAR, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, + { GO_LOKEN_DOOR, DATA_LOKEN, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, + { 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE } // END +}; class instance_halls_of_lightning : public InstanceMapScript { -public: - instance_halls_of_lightning() : InstanceMapScript("instance_halls_of_lightning", 602) { } - - InstanceScript* GetInstanceScript(InstanceMap* map) const OVERRIDE - { - return new instance_halls_of_lightning_InstanceMapScript(map); - } - - struct instance_halls_of_lightning_InstanceMapScript : public InstanceScript - { - instance_halls_of_lightning_InstanceMapScript(Map* map) : InstanceScript(map) {} + public: + instance_halls_of_lightning() : InstanceMapScript(HoLScriptName, 602) { } - uint32 m_auiEncounter[MAX_ENCOUNTER]; - - uint64 m_uiGeneralBjarngrimGUID; - uint64 m_uiIonarGUID; - uint64 m_uiLokenGUID; - uint64 m_uiVolkhanGUID; - - uint64 m_uiBjarngrimDoorGUID; - uint64 m_uiVolkhanDoorGUID; - uint64 m_uiIonarDoorGUID; - uint64 m_uiLokenDoorGUID; - uint64 m_uiLokenGlobeGUID; - - void Initialize() OVERRIDE + struct instance_halls_of_lightning_InstanceMapScript : public InstanceScript { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + instance_halls_of_lightning_InstanceMapScript(Map* map) : InstanceScript(map) + { + SetBossNumber(EncounterCount); + LoadDoorData(doorData); - m_uiGeneralBjarngrimGUID = 0; - m_uiVolkhanGUID = 0; - m_uiIonarGUID = 0; - m_uiLokenGUID = 0; + GeneralBjarngrimGUID = 0; + VolkhanGUID = 0; + IonarGUID = 0; + LokenGUID = 0; - m_uiBjarngrimDoorGUID = 0; - m_uiVolkhanDoorGUID = 0; - m_uiIonarDoorGUID = 0; - m_uiLokenDoorGUID = 0; - m_uiLokenGlobeGUID = 0; - } + LokenGlobeGUID = 0; + } - void OnCreatureCreate(Creature* creature) OVERRIDE - { - switch (creature->GetEntry()) + void OnCreatureCreate(Creature* creature) OVERRIDE { - case NPC_BJARNGRIM: - m_uiGeneralBjarngrimGUID = creature->GetGUID(); - break; - case NPC_VOLKHAN: - m_uiVolkhanGUID = creature->GetGUID(); - break; - case NPC_IONAR: - m_uiIonarGUID = creature->GetGUID(); - break; - case NPC_LOKEN: - m_uiLokenGUID = creature->GetGUID(); - break; + switch (creature->GetEntry()) + { + case NPC_BJARNGRIM: + GeneralBjarngrimGUID = creature->GetGUID(); + break; + case NPC_VOLKHAN: + VolkhanGUID = creature->GetGUID(); + break; + case NPC_IONAR: + IonarGUID = creature->GetGUID(); + break; + case NPC_LOKEN: + LokenGUID = creature->GetGUID(); + break; + default: + break; + } } - } - void OnGameObjectCreate(GameObject* go) OVERRIDE - { - switch (go->GetEntry()) + void OnGameObjectCreate(GameObject* go) OVERRIDE { - case GO_BJARNGRIM_DOOR: - m_uiBjarngrimDoorGUID = go->GetGUID(); - if (m_auiEncounter[0] == DONE) - go->SetGoState(GO_STATE_ACTIVE); - else - go->SetGoState(GO_STATE_READY); - break; - case GO_VOLKHAN_DOOR: - m_uiVolkhanDoorGUID = go->GetGUID(); - if (m_auiEncounter[1] == DONE) - go->SetGoState(GO_STATE_ACTIVE); - else - go->SetGoState(GO_STATE_READY); - break; - case GO_IONAR_DOOR: - m_uiIonarDoorGUID = go->GetGUID(); - if (m_auiEncounter[2] == DONE) - go->SetGoState(GO_STATE_ACTIVE); - else - go->SetGoState(GO_STATE_READY); - break; - case GO_LOKEN_DOOR: - m_uiLokenDoorGUID = go->GetGUID(); - if (m_auiEncounter[3] == DONE) - go->SetGoState(GO_STATE_ACTIVE); - else - go->SetGoState(GO_STATE_READY); - break; - case GO_LOKEN_THRONE: - m_uiLokenGlobeGUID = go->GetGUID(); - break; + switch (go->GetEntry()) + { + case GO_VOLKHAN_DOOR: + case GO_IONAR_DOOR: + case GO_LOKEN_DOOR: + AddDoor(go, true); + break; + case GO_LOKEN_THRONE: + LokenGlobeGUID = go->GetGUID(); + break; + default: + break; + } } - } - void SetData(uint32 uiType, uint32 uiData) OVERRIDE - { - switch (uiType) + void OnGameObjectRemove(GameObject* go) OVERRIDE { - case TYPE_BJARNGRIM: - if (uiData == DONE) - if (GameObject* pDoor = instance->GetGameObject(m_uiBjarngrimDoorGUID)) - pDoor->SetGoState(GO_STATE_ACTIVE); - m_auiEncounter[0] = uiData; - break; - case TYPE_VOLKHAN: - if (uiData == DONE) - if (GameObject* pDoor = instance->GetGameObject(m_uiVolkhanDoorGUID)) - pDoor->SetGoState(GO_STATE_ACTIVE); - m_auiEncounter[1] = uiData; - break; - case TYPE_IONAR: - if (uiData == DONE) - if (GameObject* pDoor = instance->GetGameObject(m_uiIonarDoorGUID)) - pDoor->SetGoState(GO_STATE_ACTIVE); - m_auiEncounter[2] = uiData; - break; - case TYPE_LOKEN: - if (uiData == DONE) - { - if (GameObject* pDoor = instance->GetGameObject(m_uiLokenDoorGUID)) - pDoor->SetGoState(GO_STATE_ACTIVE); - - // Appears to be type 5 GO with animation. Need to figure out how this work, code below only placeholder - if (GameObject* pGlobe = instance->GetGameObject(m_uiLokenGlobeGUID)) - pGlobe->SetGoState(GO_STATE_ACTIVE); - } - m_auiEncounter[3] = uiData; - break; + switch (go->GetEntry()) + { + case GO_VOLKHAN_DOOR: + case GO_IONAR_DOOR: + case GO_LOKEN_DOOR: + AddDoor(go, false); + break; + default: + break; + } } - if (uiData == DONE) - SaveToDB(); - } - - uint32 GetData(uint32 uiType) const OVERRIDE - { - switch (uiType) + bool SetBossState(uint32 type, EncounterState state) OVERRIDE { - case TYPE_BJARNGRIM: - return m_auiEncounter[0]; - case TYPE_VOLKHAN: - return m_auiEncounter[1]; - case TYPE_IONAR: - return m_auiEncounter[2]; - case TYPE_LOKEN: - return m_auiEncounter[3]; + if (!InstanceScript::SetBossState(type, state)) + return false; + + switch (type) + { + case DATA_LOKEN: + if (state == DONE) + if (GameObject* globe = instance->GetGameObject(LokenGlobeGUID)) + globe->SendCustomAnim(0); + break; + default: + break; + } + + return true; } - return 0; - } - uint64 GetData64(uint32 uiData) const OVERRIDE - { - switch (uiData) + uint64 GetData64(uint32 type) const OVERRIDE { - case DATA_BJARNGRIM: - return m_uiGeneralBjarngrimGUID; - case DATA_VOLKHAN: - return m_uiVolkhanGUID; - case DATA_IONAR: - return m_uiIonarGUID; - case DATA_LOKEN: - return m_uiLokenGUID; + switch (type) + { + case DATA_BJARNGRIM: + return GeneralBjarngrimGUID; + case DATA_VOLKHAN: + return VolkhanGUID; + case DATA_IONAR: + return IonarGUID; + case DATA_LOKEN: + return LokenGUID; + default: + break; + } + return 0; } - return 0; - } - std::string GetSaveData() OVERRIDE - { - OUT_SAVE_INST_DATA; + std::string GetSaveData() OVERRIDE + { + OUT_SAVE_INST_DATA; - std::ostringstream saveStream; - saveStream << "H L " << m_auiEncounter[0] << ' ' << m_auiEncounter[1] << ' ' - << m_auiEncounter[2] << ' ' << m_auiEncounter[3]; + std::ostringstream saveStream; + saveStream << "H L " << GetBossSaveData(); - OUT_SAVE_INST_DATA_COMPLETE; - return saveStream.str(); - } + OUT_SAVE_INST_DATA_COMPLETE; + return saveStream.str(); + } - void Load(const char* in) OVERRIDE - { - if (!in) + void Load(const char* str) OVERRIDE { - OUT_LOAD_INST_DATA_FAIL; - return; - } + if (!str) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } - OUT_LOAD_INST_DATA(in); + OUT_LOAD_INST_DATA(str); - char dataHead1, dataHead2; - uint16 data0, data1, data2, data3; + char dataHead1, dataHead2; - std::istringstream loadStream(in); - loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3; + std::istringstream loadStream(str); + loadStream >> dataHead1 >> dataHead2; - if (dataHead1 == 'H' && dataHead2 == 'L') - { - m_auiEncounter[0] = data0; - m_auiEncounter[1] = data1; - m_auiEncounter[2] = data2; - m_auiEncounter[3] = data3; + if (dataHead1 == 'H' && dataHead2 == 'L') + { + for (uint32 i = 0; i < EncounterCount; ++i) + { + uint32 tmpState; + loadStream >> tmpState; + if (tmpState == IN_PROGRESS || tmpState > SPECIAL) + tmpState = NOT_STARTED; + SetBossState(i, EncounterState(tmpState)); + } + } + else + OUT_LOAD_INST_DATA_FAIL; - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - m_auiEncounter[i] = NOT_STARTED; - } else OUT_LOAD_INST_DATA_FAIL; + OUT_LOAD_INST_DATA_COMPLETE; + } - OUT_LOAD_INST_DATA_COMPLETE; - } - }; + protected: + uint64 GeneralBjarngrimGUID; + uint64 VolkhanGUID; + uint64 IonarGUID; + uint64 LokenGUID; + + uint64 LokenGlobeGUID; + }; + InstanceScript* GetInstanceScript(InstanceMap* map) const OVERRIDE + { + return new instance_halls_of_lightning_InstanceMapScript(map); + } }; void AddSC_instance_halls_of_lightning() diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_krystallus.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_krystallus.cpp index e1c9dec8540..b6a4375d0eb 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_krystallus.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_krystallus.cpp @@ -56,11 +56,6 @@ class boss_krystallus : public CreatureScript public: boss_krystallus() : CreatureScript("boss_krystallus") { } - CreatureAI* GetAI(Creature* creature) const OVERRIDE - { - return new boss_krystallusAI(creature); - } - struct boss_krystallusAI : public ScriptedAI { boss_krystallusAI(Creature* creature) : ScriptedAI(creature) @@ -89,14 +84,14 @@ public: uiShatterTimer = 0; if (instance) - instance->SetData(DATA_KRYSTALLUS_EVENT, NOT_STARTED); + instance->SetBossState(DATA_KRYSTALLUS, NOT_STARTED); } void EnterCombat(Unit* /*who*/) OVERRIDE { Talk(SAY_AGGRO); if (instance) - instance->SetData(DATA_KRYSTALLUS_EVENT, IN_PROGRESS); + instance->SetBossState(DATA_KRYSTALLUS, IN_PROGRESS); } void UpdateAI(uint32 diff) OVERRIDE @@ -149,7 +144,7 @@ public: Talk(SAY_DEATH); if (instance) - instance->SetData(DATA_KRYSTALLUS_EVENT, DONE); + instance->SetBossState(DATA_KRYSTALLUS, DONE); } void KilledUnit(Unit* victim) OVERRIDE @@ -182,6 +177,10 @@ public: } }; + CreatureAI* GetAI(Creature* creature) const OVERRIDE + { + return GetHallsOfStoneAI<boss_krystallusAI>(creature); + } }; class spell_krystallus_shatter : public SpellScriptLoader diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_maiden_of_grief.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_maiden_of_grief.cpp index 5b34db663d5..f4ea3ff556c 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_maiden_of_grief.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_maiden_of_grief.cpp @@ -56,11 +56,6 @@ class boss_maiden_of_grief : public CreatureScript public: boss_maiden_of_grief() : CreatureScript("boss_maiden_of_grief") { } - CreatureAI* GetAI(Creature* creature) const OVERRIDE - { - return new boss_maiden_of_griefAI(creature); - } - struct boss_maiden_of_griefAI : public ScriptedAI { boss_maiden_of_griefAI(Creature* creature) : ScriptedAI(creature) @@ -84,7 +79,7 @@ public: if (instance) { - instance->SetData(DATA_MAIDEN_OF_GRIEF_EVENT, NOT_STARTED); + instance->SetBossState(DATA_MAIDEN_OF_GRIEF, NOT_STARTED); instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_GOOD_GRIEF_START_EVENT); } } @@ -95,14 +90,7 @@ public: if (instance) { - if (GameObject* pDoor = instance->instance->GetGameObject(instance->GetData64(DATA_MAIDEN_DOOR))) - if (pDoor->GetGoState() == GO_STATE_READY) - { - EnterEvadeMode(); - return; - } - - instance->SetData(DATA_MAIDEN_OF_GRIEF_EVENT, IN_PROGRESS); + instance->SetBossState(DATA_MAIDEN_OF_GRIEF, IN_PROGRESS); instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_GOOD_GRIEF_START_EVENT); } } @@ -158,7 +146,7 @@ public: Talk(SAY_DEATH); if (instance) - instance->SetData(DATA_MAIDEN_OF_GRIEF_EVENT, DONE); + instance->SetBossState(DATA_MAIDEN_OF_GRIEF, DONE); } void KilledUnit(Unit* victim) OVERRIDE @@ -170,6 +158,10 @@ public: } }; + CreatureAI* GetAI(Creature* creature) const OVERRIDE + { + return GetHallsOfStoneAI<boss_maiden_of_griefAI>(creature); + } }; void AddSC_boss_maiden_of_grief() diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_sjonnir.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_sjonnir.cpp index 185d8e5fd0c..618628adf88 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_sjonnir.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_sjonnir.cpp @@ -15,310 +15,265 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -/* Script Data Start -SDName: Boss sjonnir -SDAuthor: LordVanMartin -SD%Complete: -SDComment: -SDCategory: -Script Data End */ - #include "ScriptMgr.h" #include "ScriptedCreature.h" #include "halls_of_stone.h" enum Spells { - SPELL_LIGHTING_RING = 51849, //Periodic Trigger (interval 2s) spell = 50841 - H_SPELL_LIGHTING_RING = 59861, //Periodic Trigger (interval 2s) spell = 59849 - SPELL_LIGHTING_RING_1 = 50840, //Periodic Trigger (interval 2s) spell = 50841 - H_SPELL_LIGHTING_RING_1 = 59848, //Periodic Trigger (interval 2s) spell = 59849 - SPELL_STATIC_CHARGE = 50834, //Periodic Trigger 2s interval, spell =50835 - H_SPELL_STATIC_CHARGE = 59846, //Periodic Trigger 2s interval, spell =50847 - SPELL_CHAIN_LIGHTING = 50830, - H_SPELL_CHAIN_LIGHTING = 59844, - SPELL_LIGHTING_SHIELD = 50831, - H_SPELL_LIGHTING_SHIELD = 59845, - SPELL_FRENZY = 28747 + SPELL_LIGHTING_RING = 51849, // Periodic Trigger (interval 2s) spell = 50841 + SPELL_LIGHTING_RING_1 = 50840, // Periodic Trigger (interval 2s) spell = 50841 + SPELL_STATIC_CHARGE = 50834, // Periodic Trigger 2s interval, spell =50835 + SPELL_CHAIN_LIGHTING = 50830, + SPELL_LIGHTING_SHIELD = 50831, + SPELL_FRENZY = 28747 }; enum Yells { - SAY_AGGRO = 0, - SAY_SLAY = 1, - SAY_DEATH = 2 + SAY_AGGRO = 0, + SAY_SLAY = 1, + SAY_DEATH = 2 }; -#define EMOTE_GENERIC_FRENZY -1000002 - enum SjonnirCreatures { - CREATURE_FORGED_IRON_TROGG = 27979, - CREATURE_MALFORMED_OOZE = 27981, - CREATURE_FORGED_IRON_DWARF = 27982, - CREATURE_IRON_SLUDGE = 28165 + NPC_FORGED_IRON_TROGG = 27979, + NPC_MALFORMED_OOZE = 27981, + NPC_FORGED_IRON_DWARF = 27982, + NPC_IRON_SLUDGE = 28165, + NPC_EARTHEN_DWARF = 27980 }; enum Misc { - DATA_TIME_BEFORE_OOZE = 150000, // 2min 30 secs - ACTION_OOZE_DEAD = 1, - DATA_ABUSE_THE_OOZE = 2 + ACTION_OOZE_DEAD = 1, + DATA_ABUSE_THE_OOZE = 2 }; -struct Locations +enum Events { - float x, y, z; + EVENT_CHAIN_LIGHTNING = 1, + EVENT_LIGHTNING_SHIELD, + EVENT_STATIC_CHARGE, + EVENT_LIGHTNING_RING, + EVENT_SUMMON, + EVENT_FRENZY, }; -static Locations PipeLocations[] = +Position const PipeLocations[] = { - {1295.44f, 734.07f, 200.3f}, //left - {1297.7f, 595.6f, 199.9f} //right + { 1295.44f, 734.07f, 200.3f, 0.0f }, // left + { 1297.7f, 595.6f, 199.9f, 0.0f } // right }; -static Locations CenterPoint = {1295.21f, 667.157f, 189.691f}; +Position const CenterPoint = { 1295.21f, 667.157f, 189.691f, 0.0f }; class boss_sjonnir : public CreatureScript { -public: - boss_sjonnir() : CreatureScript("boss_sjonnir") { } - - CreatureAI* GetAI(Creature* creature) const OVERRIDE - { - return new boss_sjonnirAI(creature); - } - - struct boss_sjonnirAI : public ScriptedAI - { - boss_sjonnirAI(Creature* creature) : ScriptedAI(creature), lSummons(me) - { - instance = creature->GetInstanceScript(); - } - - bool bIsFrenzy; - - uint32 uiChainLightningTimer; - uint32 uiLightningShieldTimer; - uint32 uiStaticChargeTimer; - uint32 uiLightningRingTimer; - uint32 uiSummonTimer; - uint32 uiFrenzyTimer; - uint32 uiEncounterTimer; - uint8 abuseTheOoze; - - SummonList lSummons; - - InstanceScript* instance; + public: + boss_sjonnir() : CreatureScript("boss_sjonnir") { } - void Reset() OVERRIDE + struct boss_sjonnirAI : public BossAI { - bIsFrenzy = false; - - uiEncounterTimer = 0; - uiChainLightningTimer = urand(3000, 8000); - uiLightningShieldTimer = urand(20000, 25000); - uiStaticChargeTimer = urand(20000, 25000); - uiLightningRingTimer = urand(30000, 35000); - uiSummonTimer = 5000; - uiFrenzyTimer = 300000; //5 minutes - abuseTheOoze = 0; + boss_sjonnirAI(Creature* creature) : BossAI(creature, DATA_SJONNIR) { } - lSummons.DespawnAll(); + void Reset() OVERRIDE + { + _Reset(); + abuseTheOoze = 0; + } - if (instance) - instance->SetData(DATA_SJONNIR_EVENT, NOT_STARTED); - } + void EnterCombat(Unit* who) OVERRIDE + { + if (!instance->CheckRequiredBosses(DATA_SJONNIR, who->ToPlayer())) + { + EnterEvadeMode(); + return; + } - void EnterCombat(Unit* /*who*/) OVERRIDE - { - Talk(SAY_AGGRO); + _EnterCombat(); + Talk(SAY_AGGRO); - uiEncounterTimer = 0; + events.ScheduleEvent(EVENT_CHAIN_LIGHTNING, urand(3000, 8000)); + events.ScheduleEvent(EVENT_LIGHTNING_SHIELD, urand(20000, 25000)); + events.ScheduleEvent(EVENT_STATIC_CHARGE, urand(20000, 25000)); + events.ScheduleEvent(EVENT_LIGHTNING_RING, urand(30000, 35000)); + events.ScheduleEvent(EVENT_SUMMON, 5000); + events.ScheduleEvent(EVENT_FRENZY, 300000); + } - if (instance) + void JustSummoned(Creature* summon) OVERRIDE { - if (GameObject* pDoor = instance->instance->GetGameObject(instance->GetData64(DATA_SJONNIR_DOOR))) - if (pDoor->GetGoState() == GO_STATE_READY) - { - EnterEvadeMode(); - return; - } - - instance->SetData(DATA_SJONNIR_EVENT, IN_PROGRESS); + summon->GetMotionMaster()->MovePoint(0, CenterPoint); + /*if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + summon->AI()->AttackStart(target);*/ + summons.Summon(summon); } - } - void UpdateAI(uint32 diff) OVERRIDE - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (uiChainLightningTimer <= diff) + void JustDied(Unit* /*killer*/) OVERRIDE { - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(target, SPELL_CHAIN_LIGHTING); - uiChainLightningTimer = urand(10000, 15000); - } else uiChainLightningTimer -= diff; + _JustDied(); + Talk(SAY_DEATH); + } - if (uiLightningShieldTimer <= diff) + void KilledUnit(Unit* who) OVERRIDE { - DoCast(me, SPELL_LIGHTING_SHIELD); - uiLightningShieldTimer -= diff; + if (who->GetTypeId() == TYPEID_PLAYER) + Talk(SAY_SLAY); } - if (uiStaticChargeTimer <= diff) + void DoAction(int32 action) OVERRIDE { - DoCastVictim(SPELL_STATIC_CHARGE); - uiStaticChargeTimer = urand(20000, 25000); - } uiStaticChargeTimer -= diff; + if (action == ACTION_OOZE_DEAD) + ++abuseTheOoze; + } - if (uiLightningRingTimer <= diff) + uint32 GetData(uint32 type) const OVERRIDE { - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(false); - DoCast(me, SPELL_LIGHTING_RING); - uiLightningRingTimer = urand(30000, 35000); - } else uiLightningRingTimer -= diff; + if (type == DATA_ABUSE_THE_OOZE) + return abuseTheOoze; - if (uiSummonTimer <= diff) - { - uint32 uiSummonPipe = rand()%2; - me->SummonCreature(uiEncounterTimer > DATA_TIME_BEFORE_OOZE ? CREATURE_MALFORMED_OOZE : - RAND(CREATURE_FORGED_IRON_DWARF, CREATURE_FORGED_IRON_TROGG), - PipeLocations[uiSummonPipe].x, PipeLocations[uiSummonPipe].y, PipeLocations[uiSummonPipe].z, 0.0f, - TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000); - uiSummonTimer = 20000; - } else uiSummonTimer -= diff; - - if (!bIsFrenzy) - { - if (uiFrenzyTimer <= diff) - { - DoCast(me, SPELL_FRENZY); - bIsFrenzy = true; - } - else uiFrenzyTimer -= diff; + return 0; } - uiEncounterTimer +=diff; - - DoMeleeAttackIfReady(); - } - - void JustSummoned(Creature* summon) OVERRIDE - { - summon->GetMotionMaster()->MovePoint(0, CenterPoint.x, CenterPoint.y, CenterPoint.z); - /*if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - summon->AI()->AttackStart(target);*/ - lSummons.Summon(summon); - } + void UpdateAI(uint32 diff) OVERRIDE + { + if (!UpdateVictim()) + return; - void JustDied(Unit* /*killer*/) OVERRIDE - { - Talk(SAY_DEATH); - lSummons.DespawnAll(); + events.Update(diff); - if (instance) - instance->SetData(DATA_SJONNIR_EVENT, DONE); - } + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; - void KilledUnit(Unit* victim) OVERRIDE - { - if (victim->GetTypeId() != TYPEID_PLAYER) - return; + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_CHAIN_LIGHTNING: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(target, SPELL_CHAIN_LIGHTING); + events.ScheduleEvent(EVENT_CHAIN_LIGHTNING, urand(10000, 15000)); + break; + case EVENT_LIGHTNING_SHIELD: + DoCast(me, SPELL_LIGHTING_SHIELD); + break; + case EVENT_STATIC_CHARGE: + DoCastVictim(SPELL_STATIC_CHARGE); + events.ScheduleEvent(EVENT_STATIC_CHARGE, urand(20000, 25000)); + break; + case EVENT_LIGHTNING_RING: + DoCast(me, SPELL_LIGHTING_RING); + events.ScheduleEvent(EVENT_LIGHTNING_RING, urand(30000, 35000)); + break; + case EVENT_SUMMON: + { + uint8 summonPipe = urand(0, 1); + if (HealthAbovePct(75)) + me->SummonCreature(NPC_FORGED_IRON_DWARF, PipeLocations[summonPipe], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000); + else if (HealthAbovePct(50)) + me->SummonCreature(NPC_FORGED_IRON_TROGG, PipeLocations[summonPipe], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000); + else if (HealthAbovePct(25)) + me->SummonCreature(NPC_MALFORMED_OOZE, PipeLocations[summonPipe], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000); + else + me->SummonCreature(NPC_EARTHEN_DWARF, PipeLocations[summonPipe], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000); + + events.ScheduleEvent(EVENT_SUMMON, 20000); + break; + } + case EVENT_FRENZY: + /// @todo: add emote + DoCast(me, SPELL_FRENZY, true); + break; + default: + break; + } + } - Talk(SAY_SLAY); - } + DoMeleeAttackIfReady(); + } - void DoAction(int32 action) OVERRIDE - { - if (action == ACTION_OOZE_DEAD) - ++abuseTheOoze; - } + private: + uint8 abuseTheOoze; + }; - uint32 GetData(uint32 type) const OVERRIDE + CreatureAI* GetAI(Creature* creature) const OVERRIDE { - if (type == DATA_ABUSE_THE_OOZE) - return abuseTheOoze; - - return 0; + return GetHallsOfStoneAI<boss_sjonnirAI>(creature); } - }; - }; class npc_malformed_ooze : public CreatureScript { -public: - npc_malformed_ooze() : CreatureScript("npc_malformed_ooze") { } - - CreatureAI* GetAI(Creature* creature) const OVERRIDE - { - return new npc_malformed_oozeAI(creature); - } - - struct npc_malformed_oozeAI : public ScriptedAI - { - npc_malformed_oozeAI(Creature* creature) : ScriptedAI(creature) {} - - uint32 uiMergeTimer; + public: + npc_malformed_ooze() : CreatureScript("npc_malformed_ooze") { } - void Reset() OVERRIDE + struct npc_malformed_oozeAI : public ScriptedAI { - uiMergeTimer = 10000; - } + npc_malformed_oozeAI(Creature* creature) : ScriptedAI(creature) { } - void UpdateAI(uint32 diff) OVERRIDE - { - if (uiMergeTimer <= diff) + void Reset() OVERRIDE { - if (Creature* temp = me->FindNearestCreature(CREATURE_MALFORMED_OOZE, 3.0f, true)) + _mergeTimer = 10000; + } + + void UpdateAI(uint32 diff) OVERRIDE + { + if (_mergeTimer <= diff) { - DoSpawnCreature(CREATURE_IRON_SLUDGE, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 20000); - temp->DisappearAndDie(); - me->DisappearAndDie(); + if (Creature* temp = me->FindNearestCreature(NPC_MALFORMED_OOZE, 3.0f, true)) + { + DoSpawnCreature(NPC_IRON_SLUDGE, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 20000); + temp->DisappearAndDie(); + me->DisappearAndDie(); + } + _mergeTimer = 3000; } - uiMergeTimer = 3000; - } else uiMergeTimer -= diff; + else + _mergeTimer -= diff; - if (!UpdateVictim()) - return; + if (!UpdateVictim()) + return; - DoMeleeAttackIfReady(); - } - }; + DoMeleeAttackIfReady(); + } + + private: + uint32 _mergeTimer; + }; + CreatureAI* GetAI(Creature* creature) const OVERRIDE + { + return GetHallsOfStoneAI<npc_malformed_oozeAI>(creature); + } }; class npc_iron_sludge : public CreatureScript { -public: - npc_iron_sludge() : CreatureScript("npc_iron_sludge") { } - - CreatureAI* GetAI(Creature* creature) const OVERRIDE - { - return new npc_iron_sludgeAI(creature); - } + public: + npc_iron_sludge() : CreatureScript("npc_iron_sludge") { } - struct npc_iron_sludgeAI : public ScriptedAI - { - npc_iron_sludgeAI(Creature* creature) : ScriptedAI(creature) + struct npc_iron_sludgeAI : public ScriptedAI { - instance = creature->GetInstanceScript(); - } + npc_iron_sludgeAI(Creature* creature) : ScriptedAI(creature) + { + instance = creature->GetInstanceScript(); + } - InstanceScript* instance; + InstanceScript* instance; - void JustDied(Unit* /*killer*/) OVERRIDE + void JustDied(Unit* /*killer*/) OVERRIDE + { + if (Creature* sjonnir = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_SJONNIR))) + sjonnir->AI()->DoAction(ACTION_OOZE_DEAD); + } + }; + + CreatureAI* GetAI(Creature* creature) const OVERRIDE { - if (instance) - if (Creature* Sjonnir = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_SJONNIR))) - Sjonnir->AI()->DoAction(ACTION_OOZE_DEAD); + return GetHallsOfStoneAI<npc_iron_sludgeAI>(creature); } - }; - }; class achievement_abuse_the_ooze : public AchievementCriteriaScript diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfStone/halls_of_stone.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfStone/halls_of_stone.cpp index 7b5c7f2e061..ff4a5d1b43a 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfStone/halls_of_stone.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfStone/halls_of_stone.cpp @@ -137,11 +137,6 @@ class npc_tribuna_controller : public CreatureScript public: npc_tribuna_controller() : CreatureScript("npc_tribuna_controller") { } - CreatureAI* GetAI(Creature* creature) const OVERRIDE - { - return new npc_tribuna_controllerAI(creature); - } - struct npc_tribuna_controllerAI : public ScriptedAI { npc_tribuna_controllerAI(Creature* creature) : ScriptedAI(creature) @@ -263,6 +258,10 @@ public: } }; + CreatureAI* GetAI(Creature* creature) const OVERRIDE + { + return GetHallsOfStoneAI<npc_tribuna_controllerAI>(creature); + } }; class npc_brann_hos : public CreatureScript @@ -293,11 +292,6 @@ public: return true; } - CreatureAI* GetAI(Creature* creature) const OVERRIDE - { - return new npc_brann_hosAI(creature); - } - struct npc_brann_hosAI : public npc_escortAI { npc_brann_hosAI(Creature* creature) : npc_escortAI(creature) @@ -331,7 +325,7 @@ public: DespawnDwarf(); if (instance) - instance->SetData(DATA_BRANN_EVENT, NOT_STARTED); + instance->SetBossState(DATA_BRANN_EVENT, NOT_STARTED); } } @@ -446,9 +440,9 @@ public: case 1: if (instance) { - if (instance->GetData(DATA_BRANN_EVENT) != NOT_STARTED) + if (instance->GetBossState(DATA_BRANN_EVENT) != NOT_STARTED) return; - instance->SetData(DATA_BRANN_EVENT, IN_PROGRESS); + instance->SetBossState(DATA_BRANN_EVENT, IN_PROGRESS); } bIsBattle = false; Talk(SAY_ESCORT_START); @@ -598,7 +592,7 @@ public: case 29: Talk(SAY_EVENT_END_02); if (instance) - instance->SetData(DATA_BRANN_EVENT, DONE); + instance->SetBossState(DATA_BRANN_EVENT, DONE); me->CastSpell(me, SPELL_REWARD_ACHIEVEMENT, true); JumpToNextStep(5500); break; @@ -735,6 +729,10 @@ public: } }; + CreatureAI* GetAI(Creature* creature) const OVERRIDE + { + return GetHallsOfStoneAI<npc_brann_hosAI>(creature); + } }; class achievement_brann_spankin_new : public AchievementCriteriaScript diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfStone/halls_of_stone.h b/src/server/scripts/Northrend/Ulduar/HallsOfStone/halls_of_stone.h index d00649e409b..b8af76bba20 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfStone/halls_of_stone.h +++ b/src/server/scripts/Northrend/Ulduar/HallsOfStone/halls_of_stone.h @@ -15,55 +15,61 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef DEF_HALLS_OF_STONE_H -#define DEF_HALLS_OF_STONE_H -enum Data -{ - DATA_KRYSTALLUS_EVENT, - DATA_MAIDEN_OF_GRIEF_EVENT, - DATA_SJONNIR_EVENT, - DATA_BRANN_EVENT -}; +#ifndef HALLS_OF_STONE_H_ +#define HALLS_OF_STONE_H_ + +#define HoSScriptName "instance_halls_of_stone" + +uint32 const EncounterCount = 4; -enum Data64 +enum DataTypes { - DATA_KRYSTALLUS, - DATA_MAIDEN_OF_GRIEF, - DATA_SJONNIR, - DATA_KADDRAK, - DATA_MARNAK, - DATA_ABEDNEUM, - DATA_GO_TRIBUNAL_CONSOLE, - DATA_GO_KADDRAK, - DATA_GO_MARNAK, - DATA_GO_ABEDNEUM, - DATA_GO_SKY_FLOOR, - DATA_SJONNIR_DOOR, - DATA_MAIDEN_DOOR + // Encounter States/Boss GUIDs + DATA_KRYSTALLUS = 0, + DATA_MAIDEN_OF_GRIEF = 1, + DATA_BRANN_EVENT = 2, + DATA_SJONNIR = 3, + + // Additional data + DATA_KADDRAK = 4, + DATA_MARNAK = 5, + DATA_ABEDNEUM = 6, + DATA_GO_TRIBUNAL_CONSOLE = 7, + DATA_GO_KADDRAK = 8, + DATA_GO_MARNAK = 9, + DATA_GO_ABEDNEUM = 10, + DATA_GO_SKY_FLOOR = 11 }; -enum CreaturesIds +enum CreatureIds { - CREATURE_MAIDEN = 27975, - CREATURE_KRYSTALLUS = 27977, - CREATURE_SJONNIR = 27978, - CREATURE_MARNAK = 30897, - CREATURE_KADDRAK = 30898, - CREATURE_ABEDNEUM = 30899, - CREATURE_BRANN = 28070 + NPC_MAIDEN = 27975, + NPC_KRYSTALLUS = 27977, + NPC_SJONNIR = 27978, + NPC_MARNAK = 30897, + NPC_KADDRAK = 30898, + NPC_ABEDNEUM = 30899, + NPC_BRANN = 28070 }; enum GameObjectIds { - GO_ABEDNEUM = 191669, - GO_MARNAK = 192170, - GO_KADDRAK = 192171, - GO_MAIDEN_DOOR = 191292, - GO_BRANN_DOOR = 191295, - GO_SJONNIR_DOOR = 191296, - GO_TRIBUNAL_CONSOLE = 193907, - GO_TRIBUNAL_CHEST = 190586, - GO_TRIBUNAL_CHEST_HERO = 193996 + GO_ABEDNEUM = 191669, + GO_MARNAK = 191670, + GO_KADDRAK = 191671, + GO_MAIDEN_DOOR = 191292, + GO_BRANN_DOOR = 191295, + GO_SJONNIR_DOOR = 191296, + GO_TRIBUNAL_CONSOLE = 193907, + GO_TRIBUNAL_CHEST = 190586, + GO_TRIBUNAL_CHEST_HERO = 193996, + GO_TRIBUNAL_SKY_FLOOR = 191527 }; -#endif +template<class AI> +AI* GetHallsOfStoneAI(Creature* creature) +{ + return GetInstanceAI<AI>(creature, HoSScriptName); +} + +#endif // HALLS_OF_STONE_H_ diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfStone/instance_halls_of_stone.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfStone/instance_halls_of_stone.cpp index d4b8750dbba..1268207388c 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfStone/instance_halls_of_stone.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfStone/instance_halls_of_stone.cpp @@ -17,256 +17,257 @@ #include "ScriptMgr.h" #include "InstanceScript.h" +#include "WorldSession.h" #include "halls_of_stone.h" +#include <Player.h> -#define MAX_ENCOUNTER 4 - -/* Halls of Stone encounters: -0- Krystallus -1- Maiden of Grief -2- Escort Event -3- Sjonnir The Ironshaper -*/ +DoorData const doorData[] = +{ + { GO_SJONNIR_DOOR, DATA_BRANN_EVENT, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, + { 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE } // END +}; class instance_halls_of_stone : public InstanceMapScript { -public: - instance_halls_of_stone() : InstanceMapScript("instance_halls_of_stone", 599) { } - - InstanceScript* GetInstanceScript(InstanceMap* map) const OVERRIDE - { - return new instance_halls_of_stone_InstanceMapScript(map); - } - - struct instance_halls_of_stone_InstanceMapScript : public InstanceScript - { - instance_halls_of_stone_InstanceMapScript(Map* map) : InstanceScript(map) {} - - uint64 uiMaidenOfGrief; - uint64 uiKrystallus; - uint64 uiSjonnir; - - uint64 uiKaddrak; - uint64 uiAbedneum; - uint64 uiMarnak; - uint64 uiBrann; - - uint64 uiMaidenOfGriefDoor; - uint64 uiSjonnirDoor; - uint64 uiBrannDoor; - uint64 uiTribunalConsole; - uint64 uiTribunalChest; - uint64 uiTribunalSkyFloor; - uint64 uiKaddrakGo; - uint64 uiAbedneumGo; - uint64 uiMarnakGo; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - - std::string str_data; - - void Initialize() OVERRIDE - { - uiMaidenOfGrief = 0; - uiKrystallus = 0; - uiSjonnir = 0; - - uiKaddrak = 0; - uiMarnak = 0; - uiAbedneum = 0; - uiBrann = 0; - - uiMaidenOfGriefDoor = 0; - uiSjonnirDoor = 0; - uiBrannDoor = 0; - uiKaddrakGo = 0; - uiMarnakGo = 0; - uiAbedneumGo = 0; - uiTribunalConsole = 0; - uiTribunalChest = 0; - uiTribunalSkyFloor = 0; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - m_auiEncounter[i] = NOT_STARTED; - } + public: + instance_halls_of_stone() : InstanceMapScript(HoSScriptName, 599) { } - void OnCreatureCreate(Creature* creature) OVERRIDE + struct instance_halls_of_stone_InstanceMapScript : public InstanceScript { - switch (creature->GetEntry()) + instance_halls_of_stone_InstanceMapScript(Map* map) : InstanceScript(map) { - case CREATURE_MAIDEN: uiMaidenOfGrief = creature->GetGUID(); break; - case CREATURE_KRYSTALLUS: uiKrystallus = creature->GetGUID(); break; - case CREATURE_SJONNIR: uiSjonnir = creature->GetGUID(); break; - case CREATURE_MARNAK: uiMarnak = creature->GetGUID(); break; - case CREATURE_KADDRAK: uiKaddrak = creature->GetGUID(); break; - case CREATURE_ABEDNEUM: uiAbedneum = creature->GetGUID(); break; - case CREATURE_BRANN: uiBrann = creature->GetGUID(); break; + SetBossNumber(EncounterCount); + LoadDoorData(doorData); + + KrystallusGUID = 0; + MaidenOfGriefGUID = 0; + SjonnirGUID = 0; + + KaddrakGUID = 0; + AbedneumGUID = 0; + MarnakGUID = 0; + BrannGUID = 0; + + TribunalConsoleGUID = 0; + TribunalChestGUID = 0; + TribunalSkyFloorGUID = 0; + KaddrakGoGUID = 0; + AbedneumGoGUID = 0; + MarnakGoGUID = 0; } - } - void OnGameObjectCreate(GameObject* go) OVERRIDE - { - switch (go->GetEntry()) + void OnCreatureCreate(Creature* creature) OVERRIDE { - case GO_ABEDNEUM: - uiAbedneumGo = go->GetGUID(); - break; - case GO_MARNAK: - uiMarnakGo = go->GetGUID(); - break; - case GO_KADDRAK: - uiKaddrakGo = go->GetGUID(); - break; - case GO_MAIDEN_DOOR: - uiMaidenOfGriefDoor = go->GetGUID(); - if (m_auiEncounter[0] == DONE) - go->SetGoState(GO_STATE_ACTIVE); - else - go->SetGoState(GO_STATE_READY); - break; - case GO_BRANN_DOOR: - uiBrannDoor = go->GetGUID(); - if (m_auiEncounter[1] == DONE) - go->SetGoState(GO_STATE_ACTIVE); - else - go->SetGoState(GO_STATE_READY); - break; - case GO_SJONNIR_DOOR: - uiSjonnirDoor = go->GetGUID(); - if (m_auiEncounter[2] == DONE) - go->SetGoState(GO_STATE_ACTIVE); - else - go->SetGoState(GO_STATE_READY); - break; - case GO_TRIBUNAL_CONSOLE: - uiTribunalConsole = go->GetGUID(); - break; - case GO_TRIBUNAL_CHEST: - case GO_TRIBUNAL_CHEST_HERO: - uiTribunalChest = go->GetGUID(); - if (m_auiEncounter[2] == DONE) - go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_INTERACT_COND); - break; - case 191527: - uiTribunalSkyFloor = go->GetGUID(); - break; + switch (creature->GetEntry()) + { + case NPC_KRYSTALLUS: + KrystallusGUID = creature->GetGUID(); + break; + case NPC_MAIDEN: + MaidenOfGriefGUID = creature->GetGUID(); + break; + case NPC_SJONNIR: + SjonnirGUID = creature->GetGUID(); + break; + case NPC_MARNAK: + MarnakGUID = creature->GetGUID(); + break; + case NPC_KADDRAK: + KaddrakGUID = creature->GetGUID(); + break; + case NPC_ABEDNEUM: + AbedneumGUID = creature->GetGUID(); + break; + case NPC_BRANN: + BrannGUID = creature->GetGUID(); + break; + default: + break; + } } - } - void SetData(uint32 type, uint32 data) OVERRIDE - { - switch (type) + void OnGameObjectCreate(GameObject* go) OVERRIDE { - case DATA_MAIDEN_OF_GRIEF_EVENT: - m_auiEncounter[1] = data; - if (m_auiEncounter[1] == DONE) - HandleGameObject(uiBrannDoor, true); - break; - case DATA_KRYSTALLUS_EVENT: - m_auiEncounter[0] = data; - if (m_auiEncounter[0] == DONE) - HandleGameObject(uiMaidenOfGriefDoor, true); - break; - case DATA_SJONNIR_EVENT: - m_auiEncounter[3] = data; - break; - case DATA_BRANN_EVENT: - m_auiEncounter[2] = data; - if (m_auiEncounter[2] == DONE) - { - HandleGameObject(uiSjonnirDoor, true); - GameObject* go = instance->GetGameObject(uiTribunalChest); - if (go) + switch (go->GetEntry()) + { + case GO_ABEDNEUM: + AbedneumGoGUID = go->GetGUID(); + break; + case GO_MARNAK: + MarnakGoGUID = go->GetGUID(); + break; + case GO_KADDRAK: + KaddrakGoGUID = go->GetGUID(); + break; + case GO_TRIBUNAL_CONSOLE: + TribunalConsoleGUID = go->GetGUID(); + break; + case GO_TRIBUNAL_CHEST: + case GO_TRIBUNAL_CHEST_HERO: + TribunalChestGUID = go->GetGUID(); + if (GetBossState(DATA_BRANN_EVENT) == DONE) go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_INTERACT_COND); - } - break; + break; + case GO_TRIBUNAL_SKY_FLOOR: + TribunalSkyFloorGUID = go->GetGUID(); + break; + case GO_SJONNIR_DOOR: + AddDoor(go, true); + break; + default: + break; + } } - if (data == DONE) - SaveToDB(); - } - - uint32 GetData(uint32 type) const OVERRIDE - { - switch (type) + void OnGameObjectRemove(GameObject* go) OVERRIDE { - case DATA_KRYSTALLUS_EVENT: return m_auiEncounter[0]; - case DATA_MAIDEN_OF_GRIEF_EVENT: return m_auiEncounter[1]; - case DATA_SJONNIR_EVENT: return m_auiEncounter[2]; - case DATA_BRANN_EVENT: return m_auiEncounter[3]; + switch (go->GetEntry()) + { + case GO_SJONNIR_DOOR: + AddDoor(go, false); + break; + default: + break; + } } - return 0; - } - - uint64 GetData64(uint32 identifier) const OVERRIDE - { - switch (identifier) + uint64 GetData64(uint32 type) const OVERRIDE { - case DATA_MAIDEN_OF_GRIEF: return uiMaidenOfGrief; - case DATA_KRYSTALLUS: return uiKrystallus; - case DATA_SJONNIR: return uiSjonnir; - case DATA_KADDRAK: return uiKaddrak; - case DATA_MARNAK: return uiMarnak; - case DATA_ABEDNEUM: return uiAbedneum; - case DATA_GO_TRIBUNAL_CONSOLE: return uiTribunalConsole; - case DATA_GO_KADDRAK: return uiKaddrakGo; - case DATA_GO_ABEDNEUM: return uiAbedneumGo; - case DATA_GO_MARNAK: return uiMarnakGo; - case DATA_GO_SKY_FLOOR: return uiTribunalSkyFloor; - case DATA_SJONNIR_DOOR: return uiSjonnirDoor; - case DATA_MAIDEN_DOOR: return uiMaidenOfGriefDoor; + switch (type) + { + case DATA_MAIDEN_OF_GRIEF: + return MaidenOfGriefGUID; + case DATA_KRYSTALLUS: + return KrystallusGUID; + case DATA_SJONNIR: + return SjonnirGUID; + case DATA_KADDRAK: + return KaddrakGUID; + case DATA_MARNAK: + return MarnakGUID; + case DATA_ABEDNEUM: + return AbedneumGUID; + case DATA_GO_TRIBUNAL_CONSOLE: + return TribunalConsoleGUID; + case DATA_GO_KADDRAK: + return KaddrakGoGUID; + case DATA_GO_ABEDNEUM: + return AbedneumGoGUID; + case DATA_GO_MARNAK: + return MarnakGoGUID; + case DATA_GO_SKY_FLOOR: + return TribunalSkyFloorGUID; + default: + break; + } + + return 0; } - return 0; - } - - std::string GetSaveData() OVERRIDE - { - OUT_SAVE_INST_DATA; + bool SetBossState(uint32 type, EncounterState state) OVERRIDE + { + if (!InstanceScript::SetBossState(type, state)) + return false; + + switch (type) + { + case DATA_BRANN_EVENT: + if (state == DONE) + { + if (GameObject* go = instance->GetGameObject(TribunalChestGUID)) + go->RemoveFlag(GAMEOBJECT_FLAGS,GO_FLAG_INTERACT_COND); + } + break; + default: + break; + } + + return true; + } - std::ostringstream saveStream; - saveStream << "H S " << m_auiEncounter[0] << ' ' << m_auiEncounter[1] << ' ' << m_auiEncounter[2] << ' ' << m_auiEncounter[3]; + bool CheckRequiredBosses(uint32 bossId, Player const* player /*= NULL*/) const OVERRIDE + { + if (player && player->GetSession()->HasPermission(RBAC_PERM_SKIP_CHECK_INSTANCE_REQUIRED_BOSSES)) + return true; + + switch (bossId) + { + case DATA_SJONNIR: + if (GetBossState(DATA_BRANN_EVENT) != DONE) + return false; + break; + default: + break; + } + + return true; + } - str_data = saveStream.str(); + std::string GetSaveData() OVERRIDE + { + OUT_SAVE_INST_DATA; - OUT_SAVE_INST_DATA_COMPLETE; - return str_data; - } + std::ostringstream saveStream; + saveStream << "H S " << GetBossSaveData(); - void Load(const char* in) OVERRIDE - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; + OUT_SAVE_INST_DATA_COMPLETE; + return saveStream.str(); } - OUT_LOAD_INST_DATA(in); + void Load(char const* str) OVERRIDE + { + if (!str) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } - char dataHead1, dataHead2; - uint16 data0, data1, data2, data3; + OUT_LOAD_INST_DATA(str); - std::istringstream loadStream(in); - loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3; + char dataHead1, dataHead2; - if (dataHead1 == 'H' && dataHead2 == 'S') - { - m_auiEncounter[0] = data0; - m_auiEncounter[1] = data1; - m_auiEncounter[2] = data2; - m_auiEncounter[3] = data3; + std::istringstream loadStream(str); + loadStream >> dataHead1 >> dataHead2; - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - m_auiEncounter[i] = NOT_STARTED; + if (dataHead1 == 'H' && dataHead2 == 'S') + { + for (uint32 i = 0; i < EncounterCount; ++i) + { + uint32 tmpState; + loadStream >> tmpState; + if (tmpState == IN_PROGRESS || tmpState > SPECIAL) + tmpState = NOT_STARTED; + SetBossState(i, EncounterState(tmpState)); + } + } + else + OUT_LOAD_INST_DATA_FAIL; - } else OUT_LOAD_INST_DATA_FAIL; + OUT_LOAD_INST_DATA_COMPLETE; + } - OUT_LOAD_INST_DATA_COMPLETE; + protected: + uint64 KrystallusGUID; + uint64 MaidenOfGriefGUID; + uint64 SjonnirGUID; + + uint64 KaddrakGUID; + uint64 AbedneumGUID; + uint64 MarnakGUID; + uint64 BrannGUID; + + uint64 TribunalConsoleGUID; + uint64 TribunalChestGUID; + uint64 TribunalSkyFloorGUID; + uint64 KaddrakGoGUID; + uint64 AbedneumGoGUID; + uint64 MarnakGoGUID; + }; + + InstanceScript* GetInstanceScript(InstanceMap* map) const OVERRIDE + { + return new instance_halls_of_stone_InstanceMapScript(map); } - }; - }; void AddSC_instance_halls_of_stone() diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_general_vezax.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_general_vezax.cpp index 38864effe9f..46776ae9b96 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_general_vezax.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_general_vezax.cpp @@ -39,7 +39,7 @@ enum VezaxEmotes EMOTE_SURGE_OF_DARKNESS = 8, // Saronite Vapor - EMOTE_VAPORS = 9 + EMOTE_VAPORS = 0 }; enum VezaxSpells @@ -443,14 +443,21 @@ class npc_saronite_vapors : public CreatureScript } }; -class spell_mark_of_the_faceless : public SpellScriptLoader +class spell_general_vezax_mark_of_the_faceless : public SpellScriptLoader { public: - spell_mark_of_the_faceless() : SpellScriptLoader("spell_mark_of_the_faceless") { } + spell_general_vezax_mark_of_the_faceless() : SpellScriptLoader("spell_general_vezax_mark_of_the_faceless") { } - class spell_mark_of_the_faceless_AuraScript : public AuraScript + class spell_general_vezax_mark_of_the_faceless_AuraScript : public AuraScript { - PrepareAuraScript(spell_mark_of_the_faceless_AuraScript); + PrepareAuraScript(spell_general_vezax_mark_of_the_faceless_AuraScript); + + bool Validate(SpellInfo const* /*spellInfo*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_MARK_OF_THE_FACELESS_DAMAGE)) + return false; + return true; + } void HandleEffectPeriodic(AuraEffect const* aurEff) { @@ -460,13 +467,42 @@ class spell_mark_of_the_faceless : public SpellScriptLoader void Register() OVERRIDE { - OnEffectPeriodic += AuraEffectPeriodicFn(spell_mark_of_the_faceless_AuraScript::HandleEffectPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); + OnEffectPeriodic += AuraEffectPeriodicFn(spell_general_vezax_mark_of_the_faceless_AuraScript::HandleEffectPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY); } }; AuraScript* GetAuraScript() const OVERRIDE { - return new spell_mark_of_the_faceless_AuraScript(); + return new spell_general_vezax_mark_of_the_faceless_AuraScript(); + } +}; + +class spell_general_vezax_mark_of_the_faceless_leech : public SpellScriptLoader +{ + public: + spell_general_vezax_mark_of_the_faceless_leech() : SpellScriptLoader("spell_general_vezax_mark_of_the_faceless_leech") { } + + class spell_general_vezax_mark_of_the_faceless_leech_SpellScript : public SpellScript + { + PrepareSpellScript(spell_general_vezax_mark_of_the_faceless_leech_SpellScript); + + void FilterTargets(std::list<WorldObject*>& targets) + { + targets.remove(GetExplTargetWorldObject()); + + if (targets.empty()) + FinishCast(SPELL_FAILED_NO_VALID_TARGETS); + } + + void Register() + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_general_vezax_mark_of_the_faceless_leech_SpellScript::FilterTargets, EFFECT_1, TARGET_UNIT_DEST_AREA_ENEMY); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_general_vezax_mark_of_the_faceless_leech_SpellScript(); } }; @@ -554,7 +590,8 @@ void AddSC_boss_general_vezax() new boss_general_vezax(); new boss_saronite_animus(); new npc_saronite_vapors(); - new spell_mark_of_the_faceless(); + new spell_general_vezax_mark_of_the_faceless(); + new spell_general_vezax_mark_of_the_faceless_leech(); new spell_general_vezax_saronite_vapors(); new achievement_shadowdodger(); new achievement_smell_saronite(); diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp index 56fd4b310ee..6783d8cd428 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp @@ -16,6 +16,7 @@ */ #include "ScriptMgr.h" +#include "ScriptedCreature.h" #include "SpellScript.h" #include "ulduar.h" 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 4c6b3ae8b3f..7fcb624c35e 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp @@ -989,6 +989,7 @@ class boss_yogg_saron : public CreatureScript Talk(SAY_YOGG_SARON_PHASE_3); DoCast(me, SPELL_PHASE_3_TRANSFORM); me->RemoveAurasDueToSpell(SPELL_SHADOWY_BARRIER_YOGG); + me->ResetPlayerDamageReq(); break; default: break; diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp index 8691f9769fa..d0cb7108c09 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp @@ -24,15 +24,21 @@ static DoorData const doorData[] = { - {GO_LEVIATHAN_DOOR, BOSS_LEVIATHAN, DOOR_TYPE_ROOM, BOUNDARY_S }, - {GO_XT_002_DOOR, BOSS_XT002, DOOR_TYPE_ROOM, BOUNDARY_S }, - {GO_YOGG_SARON_DOOR, BOSS_YOGG_SARON, DOOR_TYPE_ROOM, BOUNDARY_S }, - {GO_DOODAD_UL_SIGILDOOR_03, BOSS_ALGALON, DOOR_TYPE_ROOM, BOUNDARY_W }, - {GO_DOODAD_UL_UNIVERSEFLOOR_01, BOSS_ALGALON, DOOR_TYPE_ROOM, BOUNDARY_NONE }, - {GO_DOODAD_UL_UNIVERSEFLOOR_02, BOSS_ALGALON, DOOR_TYPE_SPAWN_HOLE, BOUNDARY_NONE }, - {GO_DOODAD_UL_UNIVERSEGLOBE01, BOSS_ALGALON, DOOR_TYPE_SPAWN_HOLE, BOUNDARY_NONE }, - {GO_DOODAD_UL_ULDUAR_TRAPDOOR_03, BOSS_ALGALON, DOOR_TYPE_SPAWN_HOLE, BOUNDARY_NONE }, - {0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE }, + { GO_LEVIATHAN_DOOR, BOSS_LEVIATHAN, DOOR_TYPE_ROOM, BOUNDARY_S }, + { GO_XT_002_DOOR, BOSS_XT002, DOOR_TYPE_ROOM, BOUNDARY_S }, + { GO_IRON_COUNCIL_DOOR, BOSS_ASSEMBLY_OF_IRON, DOOR_TYPE_ROOM, BOUNDARY_N }, + { GO_ARCHIVUM_DOOR, BOSS_ASSEMBLY_OF_IRON, DOOR_TYPE_PASSAGE, BOUNDARY_S }, + { GO_HODIR_ENTRANCE, BOSS_HODIR, DOOR_TYPE_ROOM, BOUNDARY_E }, + { GO_HODIR_DOOR, BOSS_HODIR, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, + { GO_HODIR_ICE_DOOR, BOSS_HODIR, DOOR_TYPE_PASSAGE, BOUNDARY_W }, + { GO_VEZAX_DOOR, BOSS_VEZAX, DOOR_TYPE_PASSAGE, BOUNDARY_E }, + { GO_YOGG_SARON_DOOR, BOSS_YOGG_SARON, DOOR_TYPE_ROOM, BOUNDARY_S }, + { GO_DOODAD_UL_SIGILDOOR_03, BOSS_ALGALON, DOOR_TYPE_ROOM, BOUNDARY_W }, + { GO_DOODAD_UL_UNIVERSEFLOOR_01, BOSS_ALGALON, DOOR_TYPE_ROOM, BOUNDARY_NONE }, + { GO_DOODAD_UL_UNIVERSEFLOOR_02, BOSS_ALGALON, DOOR_TYPE_SPAWN_HOLE, BOUNDARY_NONE }, + { GO_DOODAD_UL_UNIVERSEGLOBE01, BOSS_ALGALON, DOOR_TYPE_SPAWN_HOLE, BOUNDARY_NONE }, + { GO_DOODAD_UL_ULDUAR_TRAPDOOR_03, BOSS_ALGALON, DOOR_TYPE_SPAWN_HOLE, BOUNDARY_NONE }, + { 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE }, }; MinionData const minionData[] = @@ -46,7 +52,7 @@ MinionData const minionData[] = class instance_ulduar : public InstanceMapScript { public: - instance_ulduar() : InstanceMapScript("instance_ulduar", 603) { } + instance_ulduar() : InstanceMapScript(UlduarScriptName, 603) { } struct instance_ulduar_InstanceMapScript : public InstanceScript { @@ -73,6 +79,7 @@ class instance_ulduar : public InstanceMapScript uint64 VoiceOfYoggSaronGUID; uint64 SaraGUID; uint64 BrainOfYoggSaronGUID; + uint64 KeeperGUIDs[4]; uint64 AlgalonGUID; uint64 BrannBronzebeardAlgGUID; @@ -81,16 +88,10 @@ class instance_ulduar : public InstanceMapScript uint64 RazorHarpoonGUIDs[4]; uint64 KologarnChestGUID; uint64 KologarnBridgeGUID; - uint64 KologarnDoorGUID; uint64 ThorimChestGUID; uint64 HodirRareCacheGUID; uint64 HodirChestGUID; - uint64 HodirDoorGUID; - uint64 HodirIceDoorGUID; - uint64 ArchivumDoorGUID; - uint64 VezaxDoorGUID; uint64 BrainRoomDoorGUIDs[3]; - uint64 KeeperGUIDs[4]; uint64 AlgalonSigilDoorGUID[3]; uint64 AlgalonFloorGUID[2]; uint64 AlgalonUniverseGUID; @@ -138,10 +139,6 @@ class instance_ulduar : public InstanceMapScript HodirRareCacheGUID = 0; HodirChestGUID = 0; LeviathanGateGUID = 0; - VezaxDoorGUID = 0; - HodirDoorGUID = 0; - HodirIceDoorGUID = 0; - ArchivumDoorGUID = 0; AlgalonUniverseGUID = 0; AlgalonTrapdoorGUID = 0; BrannBronzebeardAlgGUID = 0; @@ -458,9 +455,6 @@ class instance_ulduar : public InstanceMapScript if (GetBossState(BOSS_KOLOGARN) == DONE) HandleGameObject(0, false, gameObject); break; - case GO_KOLOGARN_DOOR: - KologarnDoorGUID = gameObject->GetGUID(); - break; case GO_THORIM_CHEST_HERO: case GO_THORIM_CHEST: ThorimChestGUID = gameObject->GetGUID(); @@ -473,20 +467,21 @@ class instance_ulduar : public InstanceMapScript case GO_HODIR_CHEST: HodirChestGUID = gameObject->GetGUID(); break; - case GO_LEVIATHAN_DOOR: - AddDoor(gameObject, true); - break; case GO_LEVIATHAN_GATE: LeviathanGateGUID = gameObject->GetGUID(); if (GetBossState(BOSS_LEVIATHAN) == DONE) gameObject->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE); break; + case GO_LEVIATHAN_DOOR: case GO_XT_002_DOOR: - AddDoor(gameObject, true); - break; + case GO_IRON_COUNCIL_DOOR: + case GO_ARCHIVUM_DOOR: + case GO_HODIR_ENTRANCE: + case GO_HODIR_DOOR: + case GO_HODIR_ICE_DOOR: case GO_VEZAX_DOOR: - VezaxDoorGUID = gameObject->GetGUID(); - HandleGameObject(0, false, gameObject); + case GO_YOGG_SARON_DOOR: + AddDoor(gameObject, true); break; case GO_RAZOR_HARPOON_1: RazorHarpoonGUIDs[0] = gameObject->GetGUID(); @@ -504,20 +499,6 @@ class instance_ulduar : public InstanceMapScript if (GetBossState(BOSS_RAZORSCALE) == IN_PROGRESS) gameObject->SetGoState(GO_STATE_ACTIVE); break; - case GO_HODIR_DOOR: - HodirDoorGUID = gameObject->GetGUID(); - break; - case GO_HODIR_ICE_DOOR: - HodirIceDoorGUID = gameObject->GetGUID(); - break; - case GO_ARCHIVUM_DOOR: - ArchivumDoorGUID = gameObject->GetGUID(); - if (GetBossState(BOSS_ASSEMBLY_OF_IRON) != DONE) - HandleGameObject(ArchivumDoorGUID, false); - break; - case GO_YOGG_SARON_DOOR: - AddDoor(gameObject, true); - break; case GO_BRAIN_ROOM_DOOR_1: BrainRoomDoorGUIDs[0] = gameObject->GetGUID(); break; @@ -566,6 +547,8 @@ class instance_ulduar : public InstanceMapScript case GO_GIFT_OF_THE_OBSERVER_25: GiftOfTheObserverGUID = gameObject->GetGUID(); break; + default: + break; } } @@ -575,6 +558,13 @@ class instance_ulduar : public InstanceMapScript { case GO_LEVIATHAN_DOOR: case GO_XT_002_DOOR: + case GO_IRON_COUNCIL_DOOR: + case GO_ARCHIVUM_DOOR: + case GO_HODIR_ENTRANCE: + case GO_HODIR_DOOR: + case GO_HODIR_ICE_DOOR: + case GO_VEZAX_DOOR: + case GO_YOGG_SARON_DOOR: case GO_DOODAD_UL_SIGILDOOR_03: case GO_DOODAD_UL_UNIVERSEFLOOR_01: case GO_DOODAD_UL_UNIVERSEFLOOR_02: @@ -659,7 +649,10 @@ class instance_ulduar : public InstanceMapScript case BOSS_IGNIS: case BOSS_RAZORSCALE: case BOSS_XT002: + case BOSS_ASSEMBLY_OF_IRON: case BOSS_AURIAYA: + case BOSS_VEZAX: + case BOSS_YOGG_SARON: break; case BOSS_MIMIRON: if (state == DONE) @@ -669,16 +662,6 @@ class instance_ulduar : public InstanceMapScript if (state == DONE) instance->SummonCreature(NPC_FREYA_OBSERVATION_RING, ObservationRingKeepersPos[0]); break; - case BOSS_ASSEMBLY_OF_IRON: - if (state == DONE) - HandleGameObject(ArchivumDoorGUID, true); - break; - case BOSS_VEZAX: - if (state == DONE) - HandleGameObject(VezaxDoorGUID, true); - break; - case BOSS_YOGG_SARON: - break; case BOSS_KOLOGARN: if (state == DONE) { @@ -698,8 +681,6 @@ class instance_ulduar : public InstanceMapScript HodirRareCache->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); if (GameObject* HodirChest = instance->GetGameObject(HodirChestGUID)) HodirChest->SetRespawnTime(HodirChest->GetRespawnDelay()); - HandleGameObject(HodirDoorGUID, true); - HandleGameObject(HodirIceDoorGUID, true); instance->SummonCreature(NPC_HODIR_OBSERVATION_RING, ObservationRingKeepersPos[1]); } diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h b/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h index 35d11522580..45134cd9ff6 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h @@ -166,29 +166,46 @@ enum UlduarNPCs enum UlduarGameObjects { - GO_KOLOGARN_CHEST_HERO = 195047, - GO_KOLOGARN_CHEST = 195046, - GO_KOLOGARN_BRIDGE = 194232, - GO_KOLOGARN_DOOR = 194553, - GO_THORIM_CHEST_HERO = 194315, - GO_THORIM_CHEST = 194314, - GO_HODIR_RARE_CACHE_OF_WINTER = 194200, - GO_HODIR_RARE_CACHE_OF_WINTER_HERO = 194201, - GO_HODIR_CHEST_HERO = 194308, - GO_HODIR_CHEST = 194307, + // Leviathan GO_LEVIATHAN_DOOR = 194905, GO_LEVIATHAN_GATE = 194630, - GO_XT_002_DOOR = 194631, - GO_VEZAX_DOOR = 194750, + + // Razorscale GO_MOLE_MACHINE = 194316, GO_RAZOR_HARPOON_1 = 194542, GO_RAZOR_HARPOON_2 = 194541, GO_RAZOR_HARPOON_3 = 194543, GO_RAZOR_HARPOON_4 = 194519, GO_RAZOR_BROKEN_HARPOON = 194565, + + // XT-002 + GO_XT_002_DOOR = 194631, + + // Assembly of Iron + GO_IRON_COUNCIL_DOOR = 194554, + GO_ARCHIVUM_DOOR = 194556, + + // Kologarn + GO_KOLOGARN_CHEST_HERO = 195047, + GO_KOLOGARN_CHEST = 195046, + GO_KOLOGARN_BRIDGE = 194232, + GO_KOLOGARN_DOOR = 194553, + + // Hodir + GO_HODIR_ENTRANCE = 194442, GO_HODIR_DOOR = 194634, GO_HODIR_ICE_DOOR = 194441, - GO_ARCHIVUM_DOOR = 194556, + GO_HODIR_RARE_CACHE_OF_WINTER = 194200, + GO_HODIR_RARE_CACHE_OF_WINTER_HERO = 194201, + GO_HODIR_CHEST_HERO = 194308, + GO_HODIR_CHEST = 194307, + + // Thorim + GO_THORIM_CHEST_HERO = 194315, + GO_THORIM_CHEST = 194314, + + // Vezax + GO_VEZAX_DOOR = 194750, // Yogg-Saron GO_YOGG_SARON_DOOR = 194773, @@ -327,26 +344,10 @@ enum YoggSaronIllusions STORMWIND_ILLUSION = 2, }; -template<class AI> -CreatureAI* GetUlduarAI(Creature* creature) +template<class AI, class T> +AI* GetUlduarAI(T* obj) { - if (InstanceMap* instance = creature->GetMap()->ToInstanceMap()) - if (instance->GetInstanceScript()) - if (instance->GetScriptId() == sObjectMgr->GetScriptId(UlduarScriptName)) - return new AI(creature); - - return NULL; -} - -template<class AI> -GameObjectAI* GetUlduarAI(GameObject* go) -{ - if (InstanceMap* instance = go->GetMap()->ToInstanceMap()) - if (instance->GetInstanceScript()) - if (instance->GetScriptId() == sObjectMgr->GetScriptId(UlduarScriptName)) - return new AI(go); - - return NULL; + return GetInstanceAI<AI, T>(obj, UlduarScriptName); } class PlayerOrPetCheck diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar_teleporter.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar_teleporter.cpp index 054a32a75d2..0daa9ea16c6 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar_teleporter.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar_teleporter.cpp @@ -18,9 +18,9 @@ #include "ScriptMgr.h" #include "ScriptedGossip.h" -#include "ulduar.h" #include "InstanceScript.h" #include "Player.h" +#include "ulduar.h" /* The teleporter appears to be active and stable. diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_ingvar_the_plunderer.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_ingvar_the_plunderer.cpp index 0afec32ec84..30174996a42 100644 --- a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_ingvar_the_plunderer.cpp +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_ingvar_the_plunderer.cpp @@ -28,21 +28,18 @@ EndScriptData */ enum Yells { - YELL_AGGRO_1 = 0, - YELL_KILL_1 = 1, - YELL_DEAD_1 = 2, - - YELL_AGGRO_2 = 0, - YELL_KILL_2 = 1, - YELL_DEAD_2 = 2 -}; - -enum Creatures -{ - NPC_INGVAR_HUMAN = 23954, - NPC_ANNHYLDE_THE_CALLER = 24068, - NPC_INGVAR_UNDEAD = 23980, - NPC_THROW_TARGET = 23996, + // Ingvar (Human) + SAY_AGGRO_1 = 0, + SAY_SLAY_1 = 1, + SAY_DEATH_1 = 2, + + // Ingvar (Undead) + SAY_AGGRO_2 = 3, + SAY_SLAY_2 = 4, + SAY_DEATH_2 = 5, + + // Annhylde The Caller + YELL_RESURRECT = 0 }; enum Events @@ -57,7 +54,10 @@ enum Events EVENT_WOE_STRIKE, EVENT_SHADOW_AXE, EVENT_JUST_TRANSFORMED, - EVENT_SUMMON_BANSHEE + EVENT_SUMMON_BANSHEE, + + EVENT_RESURRECT_1, + EVENT_RESURRECT_2 }; enum Phases @@ -93,296 +93,270 @@ enum Spells SPELL_INGVAR_TRANSFORM = 42796 }; -class boss_ingvar_the_plunderer : public CreatureScript +enum Misc { -public: - boss_ingvar_the_plunderer() : CreatureScript("boss_ingvar_the_plunderer") { } + ACTION_START_PHASE_2 +}; - CreatureAI* GetAI(Creature* creature) const OVERRIDE - { - return new boss_ingvar_the_plundererAI(creature); - } +class boss_ingvar_the_plunderer : public CreatureScript +{ + public: + boss_ingvar_the_plunderer() : CreatureScript("boss_ingvar_the_plunderer") { } - struct boss_ingvar_the_plundererAI : public ScriptedAI - { - boss_ingvar_the_plundererAI(Creature* creature) : ScriptedAI(creature) + struct boss_ingvar_the_plundererAI : public BossAI { - instance = creature->GetInstanceScript(); - bIsUndead = false; - } + boss_ingvar_the_plundererAI(Creature* creature) : BossAI(creature, DATA_INGVAR) + { + _isUndead = false; + } - InstanceScript* instance; + void Reset() OVERRIDE + { + _isUndead = false; - bool bIsUndead; + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); - void Reset() OVERRIDE - { - if (bIsUndead) - me->UpdateEntry(NPC_INGVAR_HUMAN); + _Reset(); + events.SetPhase(PHASE_HUMAN); - bIsUndead = false; + events.ScheduleEvent(EVENT_CLEAVE, urand(6, 12)*IN_MILLISECONDS, 0, PHASE_HUMAN); + events.ScheduleEvent(EVENT_STAGGERING_ROAR, urand(18, 21)*IN_MILLISECONDS, 0, PHASE_HUMAN); + events.ScheduleEvent(EVENT_ENRAGE, urand(7, 14)*IN_MILLISECONDS, 0, PHASE_HUMAN); + events.ScheduleEvent(EVENT_SMASH, urand(12, 17)*IN_MILLISECONDS, 0, PHASE_HUMAN); + } - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); - me->SetStandState(UNIT_STAND_STATE_STAND); + void DamageTaken(Unit* /*doneBy*/, uint32& damage) OVERRIDE + { + if (damage >= me->GetHealth() && events.IsInPhase(PHASE_HUMAN)) + { + me->RemoveAllAuras(); + DoCast(me, SPELL_INGVAR_FEIGN_DEATH, true); - events.Reset(); - events.SetPhase(PHASE_HUMAN); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - events.ScheduleEvent(EVENT_CLEAVE, urand(6, 12)*IN_MILLISECONDS, 0, PHASE_HUMAN); - events.ScheduleEvent(EVENT_STAGGERING_ROAR, urand(18, 21)*IN_MILLISECONDS, 0, PHASE_HUMAN); - events.ScheduleEvent(EVENT_ENRAGE, urand(7, 14)*IN_MILLISECONDS, 0, PHASE_HUMAN); - events.ScheduleEvent(EVENT_SMASH, urand(12, 17)*IN_MILLISECONDS, 0, PHASE_HUMAN); + events.SetPhase(PHASE_EVENT); + events.ScheduleEvent(EVENT_SUMMON_BANSHEE, 3 * IN_MILLISECONDS, 0, PHASE_EVENT); - if (instance) - instance->SetData(DATA_INGVAR_EVENT, NOT_STARTED); - } + Talk(SAY_DEATH_1); + } - void DamageTaken(Unit* /*done_by*/, uint32 &damage) OVERRIDE - { - if (damage >= me->GetHealth() && !bIsUndead) - { - //DoCast(me, SPELL_INGVAR_FEIGN_DEATH, true); // Dont work ??? - // visuel hack - me->SetHealth(0); - me->InterruptNonMeleeSpells(true); - me->RemoveAllAuras(); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->GetMotionMaster()->MovementExpired(false); - me->GetMotionMaster()->MoveIdle(); - me->SetStandState(UNIT_STAND_STATE_DEAD); - // visuel hack end - - events.SetPhase(PHASE_EVENT); - events.ScheduleEvent(EVENT_SUMMON_BANSHEE, 3 * IN_MILLISECONDS, 0, PHASE_EVENT); - - Talk(YELL_DEAD_1); + if (events.IsInPhase(PHASE_EVENT)) + damage = 0; } - if (events.IsInPhase(PHASE_EVENT)) - damage = 0; - } - - void StartZombiePhase() - { - bIsUndead = true; - me->UpdateEntry(NPC_INGVAR_UNDEAD); - events.ScheduleEvent(EVENT_JUST_TRANSFORMED, 2 * IN_MILLISECONDS, 0, PHASE_EVENT); - - Talk(YELL_AGGRO_2); - } + void DoAction(int32 actionId) + { + if (actionId == ACTION_START_PHASE_2) + StartZombiePhase(); + } - void EnterCombat(Unit* /*who*/) OVERRIDE - { - if (!bIsUndead) - Talk(YELL_AGGRO_1); + void StartZombiePhase() + { + _isUndead = true; + me->RemoveAura(SPELL_INGVAR_FEIGN_DEATH); + DoCast(me, SPELL_INGVAR_TRANSFORM, true); /// @todo: should be death persistent + events.ScheduleEvent(EVENT_JUST_TRANSFORMED, 2 * IN_MILLISECONDS, 0, PHASE_EVENT); - if (instance) - instance->SetData(DATA_INGVAR_EVENT, IN_PROGRESS); + Talk(SAY_AGGRO_2); + } - me->SetInCombatWithZone(); - } + void EnterCombat(Unit* /*who*/) OVERRIDE + { + _EnterCombat(); - void JustDied(Unit* /*killer*/) OVERRIDE - { - Talk(YELL_DEAD_2); + if (!_isUndead) + Talk(SAY_AGGRO_1); + } - if (instance) + void JustDied(Unit* /*killer*/) OVERRIDE { - // Ingvar has NPC_INGVAR_UNDEAD id in this moment, so we have to update encounter state for his original id - instance->UpdateEncounterState(ENCOUNTER_CREDIT_KILL_CREATURE, NPC_INGVAR_HUMAN, me); - instance->SetData(DATA_INGVAR_EVENT, DONE); + _JustDied(); + Talk(SAY_DEATH_2); } - } - void ScheduleSecondPhase() - { - events.SetPhase(PHASE_UNDEAD); - events.ScheduleEvent(EVENT_DARK_SMASH, urand(14, 18)*IN_MILLISECONDS, 0, PHASE_UNDEAD); - events.ScheduleEvent(EVENT_DREADFUL_ROAR, urand(18, 22)*IN_MILLISECONDS, 0, PHASE_UNDEAD); - events.ScheduleEvent(EVENT_WOE_STRIKE, urand(10, 14)*IN_MILLISECONDS, 0, PHASE_UNDEAD); - events.ScheduleEvent(EVENT_SHADOW_AXE, 30*IN_MILLISECONDS, 0, PHASE_UNDEAD); - } + void ScheduleSecondPhase() + { + events.SetPhase(PHASE_UNDEAD); + events.ScheduleEvent(EVENT_DARK_SMASH, urand(14, 18)*IN_MILLISECONDS, 0, PHASE_UNDEAD); + events.ScheduleEvent(EVENT_DREADFUL_ROAR, urand(18, 22)*IN_MILLISECONDS, 0, PHASE_UNDEAD); + events.ScheduleEvent(EVENT_WOE_STRIKE, urand(10, 14)*IN_MILLISECONDS, 0, PHASE_UNDEAD); + events.ScheduleEvent(EVENT_SHADOW_AXE, 30*IN_MILLISECONDS, 0, PHASE_UNDEAD); + } - void KilledUnit(Unit* /*victim*/) OVERRIDE - { - Talk(bIsUndead ? YELL_KILL_1 : YELL_KILL_2); - } + void KilledUnit(Unit* /*victim*/) OVERRIDE + { + Talk(_isUndead ? SAY_SLAY_1 : SAY_SLAY_2); + } - void UpdateAI(uint32 diff) OVERRIDE - { - if (!UpdateVictim() && !events.IsInPhase(PHASE_EVENT)) - return; + void UpdateAI(uint32 diff) OVERRIDE + { + if (!UpdateVictim() && !events.IsInPhase(PHASE_EVENT)) + return; - events.Update(diff); + events.Update(diff); - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; - while (uint32 eventId = events.ExecuteEvent()) - { - switch (eventId) + while (uint32 eventId = events.ExecuteEvent()) { - // PHASE ONE - case EVENT_CLEAVE: - DoCastVictim(SPELL_CLEAVE); - events.ScheduleEvent(EVENT_CLEAVE, urand(6, 12)*IN_MILLISECONDS, 0, PHASE_HUMAN); - break; - case EVENT_STAGGERING_ROAR: - DoCast(me, SPELL_STAGGERING_ROAR); - events.ScheduleEvent(EVENT_STAGGERING_ROAR, urand(18, 22)*IN_MILLISECONDS, 0, PHASE_HUMAN); - break; - case EVENT_ENRAGE: - DoCast(me, SPELL_ENRAGE); - events.ScheduleEvent(EVENT_ENRAGE, urand(7, 14)*IN_MILLISECONDS, 0, PHASE_HUMAN); - break; - case EVENT_SMASH: - DoCastAOE(SPELL_SMASH); - events.ScheduleEvent(EVENT_SMASH, urand(12, 16)*IN_MILLISECONDS, 0, PHASE_HUMAN); - break; - case EVENT_JUST_TRANSFORMED: - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->SetInCombatWithZone(); - me->GetMotionMaster()->MoveChase(me->GetVictim()); - ScheduleSecondPhase(); - return; - case EVENT_SUMMON_BANSHEE: - DoCast(me, SPELL_SUMMON_BANSHEE); - return; - // PHASE TWO - case EVENT_DARK_SMASH: - DoCastVictim(SPELL_DARK_SMASH); - events.ScheduleEvent(EVENT_DARK_SMASH, urand(12, 16)*IN_MILLISECONDS, 0, PHASE_UNDEAD); - break; - case EVENT_DREADFUL_ROAR: - DoCast(me, SPELL_DREADFUL_ROAR); - events.ScheduleEvent(EVENT_DREADFUL_ROAR, urand(18, 22)*IN_MILLISECONDS, 0, PHASE_UNDEAD); - break; - case EVENT_WOE_STRIKE: - DoCastVictim(SPELL_WOE_STRIKE); - events.ScheduleEvent(EVENT_WOE_STRIKE, urand(10, 14)*IN_MILLISECONDS, 0, PHASE_UNDEAD); - break; - case EVENT_SHADOW_AXE: - if (Unit* target = SelectTarget(SELECT_TARGET_TOPAGGRO, 1)) - { - DoCast(target, SPELL_SHADOW_AXE_SUMMON); - } - events.ScheduleEvent(EVENT_SHADOW_AXE, 30*IN_MILLISECONDS, 0, PHASE_UNDEAD); - break; + switch (eventId) + { + // PHASE ONE + case EVENT_CLEAVE: + DoCastVictim(SPELL_CLEAVE); + events.ScheduleEvent(EVENT_CLEAVE, urand(6, 12)*IN_MILLISECONDS, 0, PHASE_HUMAN); + break; + case EVENT_STAGGERING_ROAR: + DoCast(me, SPELL_STAGGERING_ROAR); + events.ScheduleEvent(EVENT_STAGGERING_ROAR, urand(18, 22)*IN_MILLISECONDS, 0, PHASE_HUMAN); + break; + case EVENT_ENRAGE: + DoCast(me, SPELL_ENRAGE); + events.ScheduleEvent(EVENT_ENRAGE, urand(7, 14)*IN_MILLISECONDS, 0, PHASE_HUMAN); + break; + case EVENT_SMASH: + DoCastAOE(SPELL_SMASH); + events.ScheduleEvent(EVENT_SMASH, urand(12, 16)*IN_MILLISECONDS, 0, PHASE_HUMAN); + break; + case EVENT_JUST_TRANSFORMED: + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + DoZoneInCombat(); + ScheduleSecondPhase(); + return; + case EVENT_SUMMON_BANSHEE: + DoCast(me, SPELL_SUMMON_BANSHEE); + return; + // PHASE TWO + case EVENT_DARK_SMASH: + DoCastVictim(SPELL_DARK_SMASH); + events.ScheduleEvent(EVENT_DARK_SMASH, urand(12, 16)*IN_MILLISECONDS, 0, PHASE_UNDEAD); + break; + case EVENT_DREADFUL_ROAR: + DoCast(me, SPELL_DREADFUL_ROAR); + events.ScheduleEvent(EVENT_DREADFUL_ROAR, urand(18, 22)*IN_MILLISECONDS, 0, PHASE_UNDEAD); + break; + case EVENT_WOE_STRIKE: + DoCastVictim(SPELL_WOE_STRIKE); + events.ScheduleEvent(EVENT_WOE_STRIKE, urand(10, 14)*IN_MILLISECONDS, 0, PHASE_UNDEAD); + break; + case EVENT_SHADOW_AXE: + if (Unit* target = SelectTarget(SELECT_TARGET_TOPAGGRO, 1)) + DoCast(target, SPELL_SHADOW_AXE_SUMMON); + + events.ScheduleEvent(EVENT_SHADOW_AXE, 30*IN_MILLISECONDS, 0, PHASE_UNDEAD); + break; + } } + + if (!events.IsInPhase(PHASE_EVENT)) + DoMeleeAttackIfReady(); } - DoMeleeAttackIfReady(); - } - private: - EventMap events; - }; + private: + bool _isUndead; + }; + CreatureAI* GetAI(Creature* creature) const OVERRIDE + { + return GetUtgardeKeepAI<boss_ingvar_the_plundererAI>(creature); + } }; class npc_annhylde_the_caller : public CreatureScript { -public: - npc_annhylde_the_caller() : CreatureScript("npc_annhylde_the_caller") { } + public: + npc_annhylde_the_caller() : CreatureScript("npc_annhylde_the_caller") { } - CreatureAI* GetAI(Creature* creature) const OVERRIDE - { - return new npc_annhylde_the_callerAI(creature); - } - - struct npc_annhylde_the_callerAI : public ScriptedAI - { - npc_annhylde_the_callerAI(Creature* creature) : ScriptedAI(creature) + struct npc_annhylde_the_callerAI : public ScriptedAI { - instance = creature->GetInstanceScript(); - } - - float x, y, z; - InstanceScript* instance; - uint32 uiResurectTimer; - uint32 uiResurectPhase; + npc_annhylde_the_callerAI(Creature* creature) : ScriptedAI(creature) + { + _instance = creature->GetInstanceScript(); + } - void Reset() OVERRIDE - { - //! HACK: Creature's can't have MOVEMENTFLAG_FLYING - me->SetHover(true); + void Reset() OVERRIDE + { + _events.Reset(); - me->GetPosition(x, y, z); - DoTeleportTo(x+1, y, z+30); + //! HACK: Creature's can't have MOVEMENTFLAG_FLYING + me->SetHover(true); - Unit* ingvar = Unit::GetUnit(*me, instance ? instance->GetData64(DATA_INGVAR) : 0); - if (ingvar) - { + me->GetPosition(x, y, z); + DoTeleportTo(x+1, y, z+30); me->GetMotionMaster()->MovePoint(1, x, y, z+15); - - // Talk(YELL_RESSURECT); } - } - void MovementInform(uint32 type, uint32 id) OVERRIDE - { - if (type != POINT_MOTION_TYPE) - return; - Unit* ingvar = Unit::GetUnit(*me, instance ? instance->GetData64(DATA_INGVAR) : 0); - if (ingvar) + void MovementInform(uint32 type, uint32 id) OVERRIDE { + if (type != POINT_MOTION_TYPE) + return; + switch (id) { - case 1: - ingvar->RemoveAura(SPELL_SUMMON_BANSHEE); - ingvar->CastSpell(ingvar, SPELL_SCOURG_RESURRECTION_DUMMY, true); - DoCast(ingvar, SPELL_SCOURG_RESURRECTION_BEAM); - uiResurectTimer = 8000; - uiResurectPhase = 1; - break; - case 2: - me->SetVisible(false); - me->DealDamage(me, me->GetHealth()); - me->RemoveCorpse(); - break; + case 1: + Talk(YELL_RESURRECT); + if (Creature* ingvar = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_INGVAR))) + { + ingvar->RemoveAura(SPELL_SUMMON_BANSHEE); + ingvar->CastSpell(ingvar, SPELL_SCOURG_RESURRECTION_DUMMY, true); + DoCast(ingvar, SPELL_SCOURG_RESURRECTION_BEAM); + } + _events.ScheduleEvent(EVENT_RESURRECT_1, 8000); + break; + case 2: + me->DespawnOrUnsummon(); + break; + default: + break; } } - } - void AttackStart(Unit* /*who*/) OVERRIDE {} - void MoveInLineOfSight(Unit* /*who*/) OVERRIDE {} + void AttackStart(Unit* /*who*/) OVERRIDE { } + void MoveInLineOfSight(Unit* /*who*/) OVERRIDE { } + void EnterCombat(Unit* /*who*/) OVERRIDE { } - void EnterCombat(Unit* /*who*/) OVERRIDE {} - void UpdateAI(uint32 diff) OVERRIDE - { - if (uiResurectTimer) + void UpdateAI(uint32 diff) OVERRIDE { - if (uiResurectTimer <= diff) + _events.Update(diff); + + while (uint32 eventId = _events.ExecuteEvent()) { - if (uiResurectPhase == 1) + switch (eventId) { - Unit* ingvar = Unit::GetUnit(*me, instance ? instance->GetData64(DATA_INGVAR) : 0); - if (ingvar) - { - ingvar->SetStandState(UNIT_STAND_STATE_STAND); - ingvar->CastSpell(ingvar, SPELL_SCOURG_RESURRECTION_HEAL, false); - } - uiResurectTimer = 3000; - uiResurectPhase = 2; - } - else if (uiResurectPhase == 2) - { - if (Creature* ingvar = Unit::GetCreature(*me, instance ? instance->GetData64(DATA_INGVAR) : 0)) - { - ingvar->RemoveAurasDueToSpell(SPELL_SCOURG_RESURRECTION_DUMMY); - - if (ingvar->GetVictim()) - if (boss_ingvar_the_plunderer::boss_ingvar_the_plundererAI* ai = CAST_AI(boss_ingvar_the_plunderer::boss_ingvar_the_plundererAI, ingvar->AI())) - ai->StartZombiePhase(); + case EVENT_RESURRECT_1: + if (Creature* ingvar = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_INGVAR))) + { + ingvar->RemoveAura(SPELL_INGVAR_FEIGN_DEATH); + ingvar->CastSpell(ingvar, SPELL_SCOURG_RESURRECTION_HEAL, false); + } + _events.ScheduleEvent(EVENT_RESURRECT_2, 3000); + break; + case EVENT_RESURRECT_2: + if (Creature* ingvar = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_INGVAR))) + { + ingvar->RemoveAurasDueToSpell(SPELL_SCOURG_RESURRECTION_DUMMY); + ingvar->AI()->DoAction(ACTION_START_PHASE_2); + } me->GetMotionMaster()->MovePoint(2, x+1, y, z+30); - ++uiResurectPhase; - uiResurectTimer = 0; - } + break; + default: + break; } - } else uiResurectTimer -= diff; + } } + + private: + InstanceScript* _instance; + EventMap _events; + float x, y, z; + }; + + CreatureAI* GetAI(Creature* creature) const OVERRIDE + { + return GetUtgardeKeepAI<npc_annhylde_the_callerAI>(creature); } - }; }; enum ShadowAxe @@ -427,12 +401,7 @@ public: { DoCast(me, SPELL_SHADOW_AXE_DAMAGE); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); - if (TempSummon* summon = me->ToTempSummon()) - { - summon->UnSummon(10000); - } - else - me->DisappearAndDie(); + me->DespawnOrUnsummon(10000); } } }; diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_keleseth.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_keleseth.cpp index 3bfacbaff5e..f8f35ed7142 100644 --- a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_keleseth.cpp +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_keleseth.cpp @@ -75,268 +75,247 @@ float AttackLoc[3]= {197.636f, 194.046f, 40.8164f}; class npc_frost_tomb : public CreatureScript { -public: - npc_frost_tomb() : CreatureScript("npc_frost_tomb") {} - - CreatureAI* GetAI(Creature* creature) const OVERRIDE - { - return new npc_frost_tombAI(creature); - } + public: + npc_frost_tomb() : CreatureScript("npc_frost_tomb") { } - struct npc_frost_tombAI : public ScriptedAI - { - npc_frost_tombAI(Creature* creature) : ScriptedAI(creature) + struct npc_frost_tombAI : public ScriptedAI { - if (me->IsSummon()) - if (Unit* summon = me->ToTempSummon()->GetSummoner()) - DoCast(summon, SPELL_FROST_TOMB, true); + npc_frost_tombAI(Creature* creature) : ScriptedAI(creature) + { + _instance = creature->GetInstanceScript(); + } - instance = creature->GetInstanceScript(); - } + void IsSummonedBy(Unit* summoner) OVERRIDE + { + DoCast(summoner, SPELL_FROST_TOMB, true); + } + + void UpdateAI(uint32 /*diff*/) OVERRIDE { } + + void JustDied(Unit* /*killer*/) OVERRIDE + { + if (Creature* keleseth = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_PRINCE_KELESETH))) + keleseth->AI()->SetData(DATA_ON_THE_ROCKS, false); + } - void UpdateAI(uint32 /*diff*/) OVERRIDE {} + private: + InstanceScript* _instance; + }; - void JustDied(Unit* /*killer*/) OVERRIDE + CreatureAI* GetAI(Creature* creature) const OVERRIDE { - if (instance) - if (Unit* boss = me->GetUnit(*me, instance->GetData64(DATA_PRINCEKELESETH))) - if (boss->ToCreature() && boss->ToCreature()->AI()) - boss->ToCreature()->AI()->SetData(DATA_ON_THE_ROCKS, false); + return GetUtgardeKeepAI<npc_frost_tombAI>(creature); } - - private: - InstanceScript* instance; - }; }; class boss_keleseth : public CreatureScript { -public: - boss_keleseth() : CreatureScript("boss_keleseth") {} - - CreatureAI* GetAI(Creature* creature) const OVERRIDE - { - return new boss_kelesethAI(creature); - } - - struct boss_kelesethAI : public BossAI - { - boss_kelesethAI(Creature* creature) : BossAI(creature, DATA_PRINCEKELESETH_EVENT){} + public: + boss_keleseth() : CreatureScript("boss_keleseth") { } - void Reset() OVERRIDE + struct boss_kelesethAI : public BossAI { - if (instance) - instance->SetData(DATA_PRINCEKELESETH_EVENT, NOT_STARTED); - - events.Reset(); - events.ScheduleEvent(EVENT_SHADOWBOLT, urand(2, 3)*IN_MILLISECONDS); - events.ScheduleEvent(EVENT_FROST_TOMB, urand(14, 19)*IN_MILLISECONDS); - events.ScheduleEvent(EVENT_SUMMON_SKELETONS, 6*IN_MILLISECONDS); + boss_kelesethAI(Creature* creature) : BossAI(creature, DATA_PRINCE_KELESETH) { } - summons.DespawnAll(); + void Reset() OVERRIDE + { + _Reset(); + events.ScheduleEvent(EVENT_SHADOWBOLT, urand(2, 3)*IN_MILLISECONDS); + events.ScheduleEvent(EVENT_FROST_TOMB, urand(14, 19)*IN_MILLISECONDS); + events.ScheduleEvent(EVENT_SUMMON_SKELETONS, 6*IN_MILLISECONDS); - onTheRocks = true; - } + onTheRocks = true; + } - void EnterCombat(Unit* who) OVERRIDE - { - me->SetInCombatWithZone(); - if (instance) - instance->SetData(DATA_PRINCEKELESETH_EVENT, IN_PROGRESS); - Talk(SAY_START_COMBAT); + void EnterCombat(Unit* who) OVERRIDE + { + _EnterCombat(); + Talk(SAY_START_COMBAT); - if (!who) - return; + if (!who) + return; - std::list<Creature*> runemages; - me->GetCreatureListWithEntryInGrid(runemages, NPC_RUNEMAGE, 60.0f); - if (!runemages.empty()) - { - for (std::list<Creature*>::iterator itr = runemages.begin(); itr != runemages.end(); ++itr) + std::list<Creature*> guards; + me->GetCreatureListWithEntryInGrid(guards, NPC_RUNEMAGE, 60.0f); + me->GetCreatureListWithEntryInGrid(guards, NPC_STRATEGIST, 60.0f); + if (!guards.empty()) { - if ((*itr)->IsAlive() && (*itr)->IsWithinLOSInMap(me)) - (*itr)->AI()->AttackStart(who); + for (std::list<Creature*>::iterator itr = guards.begin(); itr != guards.end(); ++itr) + { + if ((*itr)->IsAlive() && (*itr)->IsWithinLOSInMap(me)) + (*itr)->AI()->AttackStart(who); + } } } - std::list<Creature*> strategists; - me->GetCreatureListWithEntryInGrid(strategists, NPC_STRATEGIST, 60.0f); - if (!strategists.empty()) + void JustDied(Unit* /*killer*/) OVERRIDE { - for (std::list<Creature*>::iterator itr = strategists.begin(); itr != strategists.end(); ++itr) - { - if ((*itr)->IsAlive() && (*itr)->IsWithinLOSInMap(me)) - (*itr)->AI()->AttackStart(who); - } + _JustDied(); + Talk(SAY_DEATH); } - } - - void JustDied(Unit* /*killer*/) OVERRIDE - { - if (instance) - instance->SetData(DATA_PRINCEKELESETH_EVENT, DONE); - summons.DespawnAll(); - Talk(SAY_DEATH); - } - void SetData(uint32 data, uint32 value) OVERRIDE - { - if (data == DATA_ON_THE_ROCKS) - onTheRocks = value; - } + void SetData(uint32 data, uint32 value) OVERRIDE + { + if (data == DATA_ON_THE_ROCKS) + onTheRocks = value; + } - uint32 GetData(uint32 data) const OVERRIDE - { - if (data == DATA_ON_THE_ROCKS) - return onTheRocks; + uint32 GetData(uint32 data) const OVERRIDE + { + if (data == DATA_ON_THE_ROCKS) + return onTheRocks; - return 0; - } + return 0; + } - void UpdateAI(uint32 diff) OVERRIDE - { - if (!UpdateVictim()) - return; + void UpdateAI(uint32 diff) OVERRIDE + { + if (!UpdateVictim()) + return; - events.Update(diff); + events.Update(diff); - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; - while (uint32 eventId = events.ExecuteEvent()) - { - switch (eventId) + while (uint32 eventId = events.ExecuteEvent()) { - case EVENT_SUMMON_SKELETONS: - Talk(SAY_SUMMON_SKELETONS); - SummonSkeletons(); - break; - case EVENT_SHADOWBOLT: - DoCastVictim(SPELL_SHADOWBOLT); - events.ScheduleEvent(EVENT_SHADOWBOLT, urand(2, 3)*IN_MILLISECONDS); - break; - case EVENT_FROST_TOMB: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true, -SPELL_FROST_TOMB)) + switch (eventId) { - Talk(SAY_FROST_TOMB); - Talk(SAY_FROST_TOMB_EMOTE, target->GetGUID()); + case EVENT_SUMMON_SKELETONS: + Talk(SAY_SUMMON_SKELETONS); + SummonSkeletons(); + break; + case EVENT_SHADOWBOLT: + DoCastVictim(SPELL_SHADOWBOLT); + events.ScheduleEvent(EVENT_SHADOWBOLT, urand(2, 3) * IN_MILLISECONDS); + break; + case EVENT_FROST_TOMB: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true, -SPELL_FROST_TOMB)) + { + Talk(SAY_FROST_TOMB); + Talk(SAY_FROST_TOMB_EMOTE, target->GetGUID()); - DoCast(target, SPELL_FROST_TOMB_STUN, true); - // checked from sniffs - the player casts the spell - target->CastSpell(target, SPELL_FROST_TOMB_SUMMON, true); + DoCast(target, SPELL_FROST_TOMB_STUN, true); + // checked from sniffs - the player casts the spell + target->CastSpell(target, SPELL_FROST_TOMB_SUMMON, true); + } + events.ScheduleEvent(EVENT_FROST_TOMB, urand(14, 19) * IN_MILLISECONDS); + break; + default: + break; } - events.ScheduleEvent(EVENT_FROST_TOMB, urand(14, 19)*IN_MILLISECONDS); - break; } + + DoMeleeAttackIfReady(); } - DoMeleeAttackIfReady(); - } + void SummonSkeletons() + { + // I could not found any spell casted for this + for (uint8 i = 0; i < 4; ++i) + me->SummonCreature(NPC_SKELETON, SkeletonSpawnPoint[0][0], SkeletonSpawnPoint[0][1], SKELETONSPAWN_Z, 0); + } + + private: + bool onTheRocks; + }; - void SummonSkeletons() + CreatureAI* GetAI(Creature* creature) const OVERRIDE { - // I could not found any spell casted for this - for (uint8 i = 0; i < 4; ++i) - me->SummonCreature(NPC_SKELETON, SkeletonSpawnPoint[0][0], SkeletonSpawnPoint[0][1], SKELETONSPAWN_Z, 0); + return GetUtgardeKeepAI<boss_kelesethAI>(creature); } - private: - bool onTheRocks; - }; }; class npc_vrykul_skeleton : public CreatureScript { -public: - npc_vrykul_skeleton() : CreatureScript("npc_vrykul_skeleton") {} - - CreatureAI* GetAI(Creature* creature) const OVERRIDE - { - return new npc_vrykul_skeletonAI(creature); - } - - struct npc_vrykul_skeletonAI : public ScriptedAI - { - npc_vrykul_skeletonAI(Creature* creature) : ScriptedAI(creature) {} + public: + npc_vrykul_skeleton() : CreatureScript("npc_vrykul_skeleton") { } - void Reset() OVERRIDE + struct npc_vrykul_skeletonAI : public ScriptedAI { - events.Reset(); - events.ScheduleEvent(EVENT_DECREPIFY, urand(4, 6)*IN_MILLISECONDS); - - } + npc_vrykul_skeletonAI(Creature* creature) : ScriptedAI(creature) { } - void DamageTaken(Unit* /*done_by*/, uint32 &damage) OVERRIDE - { - if (damage >= me->GetHealth()) + void Reset() OVERRIDE { - damage = 0; + events.Reset(); + events.ScheduleEvent(EVENT_DECREPIFY, urand(4, 6) * IN_MILLISECONDS); + } - // There are some issues with pets - // they will still attack. I would say it is a PetAI bug - if (!me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE)) + void DamageTaken(Unit* /*doneBy*/, uint32& damage) OVERRIDE + { + if (damage >= me->GetHealth()) { - // from sniffs - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_BYTES_1, UNIT_STAND_STATE_DEAD); + damage = 0; - events.Reset(); - events.ScheduleEvent(EVENT_RESURRECT, urand(18, 22)*IN_MILLISECONDS); + // There are some issues with pets + // they will still attack. I would say it is a PetAI bug + if (!me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE)) + { + // from sniffs + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetFlag(UNIT_FIELD_BYTES_1, UNIT_STAND_STATE_DEAD); + + events.Reset(); + events.ScheduleEvent(EVENT_RESURRECT, urand(18, 22) * IN_MILLISECONDS); - me->GetMotionMaster()->MovementExpired(false); - me->GetMotionMaster()->MoveIdle(); + me->GetMotionMaster()->MovementExpired(false); + me->GetMotionMaster()->MoveIdle(); + } } } - } - void UpdateAI(uint32 diff) OVERRIDE - { - if (!UpdateVictim()) - return; + void UpdateAI(uint32 diff) OVERRIDE + { + if (!UpdateVictim()) + return; - events.Update(diff); + events.Update(diff); - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; - while (uint32 eventId = events.ExecuteEvent()) - { - switch (eventId) + while (uint32 eventId = events.ExecuteEvent()) { - case EVENT_DECREPIFY: - DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true, -SPELL_DECREPIFY), SPELL_DECREPIFY); - events.ScheduleEvent(EVENT_DECREPIFY, urand(1, 5)*IN_MILLISECONDS); - break; - case EVENT_RESURRECT: - events.ScheduleEvent(EVENT_FULL_HEAL, 1*IN_MILLISECONDS); - events.ScheduleEvent(EVENT_SHADOW_FISSURE, 1*IN_MILLISECONDS); - break; - case EVENT_FULL_HEAL: - DoCast(me, SPELL_FULL_HEAL, true); - break; - case EVENT_SHADOW_FISSURE: - DoCast(me, SPELL_SHADOW_FISSURE, true); - if (TempSummon* temp = me->ToTempSummon()) - { - if (Unit* summoner = temp->GetSummoner()) - { - DoCast(summoner, SPELL_BONE_ARMOR); - } - } - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->RemoveFlag(UNIT_FIELD_BYTES_1, UNIT_STAND_STATE_DEAD); - me->GetMotionMaster()->MoveChase(me->GetVictim()); - events.ScheduleEvent(EVENT_DECREPIFY, urand(4, 6)*IN_MILLISECONDS); - break; + switch (eventId) + { + case EVENT_DECREPIFY: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true, -SPELL_DECREPIFY)) + DoCast(target, SPELL_DECREPIFY); + events.ScheduleEvent(EVENT_DECREPIFY, urand(1, 5)*IN_MILLISECONDS); + break; + case EVENT_RESURRECT: + events.ScheduleEvent(EVENT_FULL_HEAL, 1 * IN_MILLISECONDS); + events.ScheduleEvent(EVENT_SHADOW_FISSURE, 1 * IN_MILLISECONDS); + break; + case EVENT_FULL_HEAL: + DoCast(me, SPELL_FULL_HEAL, true); + break; + case EVENT_SHADOW_FISSURE: + DoCast(me, SPELL_SHADOW_FISSURE, true); + DoCastAOE(SPELL_BONE_ARMOR, true); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->RemoveFlag(UNIT_FIELD_BYTES_1, UNIT_STAND_STATE_DEAD); + me->GetMotionMaster()->MoveChase(me->GetVictim()); + events.ScheduleEvent(EVENT_DECREPIFY, urand(4, 6) * IN_MILLISECONDS); + break; + default: + break; + } } + + if (!me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE)) + DoMeleeAttackIfReady(); } - if (!me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE)) - DoMeleeAttackIfReady(); - } + private: + EventMap events; + }; - private: - EventMap events; - }; + CreatureAI* GetAI(Creature* creature) const OVERRIDE + { + return GetUtgardeKeepAI<npc_vrykul_skeletonAI>(creature); + } }; class spell_frost_tomb : public SpellScriptLoader @@ -347,12 +326,14 @@ class spell_frost_tomb : public SpellScriptLoader class spell_frost_tomb_AuraScript : public AuraScript { PrepareAuraScript(spell_frost_tomb_AuraScript); + void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) { if (GetTargetApplication()->GetRemoveMode() != AURA_REMOVE_BY_DEATH) if (Unit* caster = GetCaster()) - if (caster->ToCreature() && caster->IsAlive()) - caster->ToCreature()->DespawnOrUnsummon(1000); + if (caster->IsAlive()) + if (Creature* creature = caster->ToCreature()) + creature->DespawnOrUnsummon(1000); } void Register() OVERRIDE diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_skarvald_dalronn.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_skarvald_dalronn.cpp index 4ece79b0f7f..ffdd8fe232f 100644 --- a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_skarvald_dalronn.cpp +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_skarvald_dalronn.cpp @@ -58,14 +58,6 @@ enum Spells SPELL_SUMMON_DALRONN_GHOST = 48612, }; -enum Creatures -{ - NPC_SKARVALD_THE_CONSTRUCTOR = 24200, - NPC_SKARVALD_GHOST = 27390, - NPC_DALRONN_THE_CONTROLLER = 24201, - NPC_DALRONN_GHOST = 27389 -}; - class SkarvaldChargePredicate { public: @@ -82,353 +74,334 @@ class SkarvaldChargePredicate class boss_skarvald_the_constructor : public CreatureScript { -public: - boss_skarvald_the_constructor() : CreatureScript("boss_skarvald_the_constructor") { } - - CreatureAI* GetAI(Creature* creature) const OVERRIDE - { - return new boss_skarvald_the_constructorAI(creature); - } + public: + boss_skarvald_the_constructor() : CreatureScript("boss_skarvald_the_constructor") { } - struct boss_skarvald_the_constructorAI : public ScriptedAI - { - boss_skarvald_the_constructorAI(Creature* creature) : ScriptedAI(creature) + struct boss_skarvald_the_constructorAI : public BossAI { - instance = creature->GetInstanceScript(); - } + boss_skarvald_the_constructorAI(Creature* creature) : BossAI(creature, DATA_SKARVALD_DALRONN) { } - InstanceScript* instance; + bool ghost; + uint32 Charge_Timer; + uint32 StoneStrike_Timer; + uint32 Response_Timer; + uint32 Check_Timer; + bool Dalronn_isDead; + bool Enraged; - bool ghost; - uint32 Charge_Timer; - uint32 StoneStrike_Timer; - uint32 Response_Timer; - uint32 Check_Timer; - bool Dalronn_isDead; - bool Enraged; - - void Reset() OVERRIDE - { - Charge_Timer = 5000; - StoneStrike_Timer = 10000; - Dalronn_isDead = false; - Check_Timer = 5000; - Enraged = false; - - ghost = (me->GetEntry() == NPC_SKARVALD_GHOST); - if (!ghost && instance) + void Reset() OVERRIDE { - Unit* dalronn = Unit::GetUnit(*me, instance->GetData64(DATA_DALRONN)); - if (dalronn && dalronn->isDead()) - dalronn->ToCreature()->Respawn(); - - instance->SetData(DATA_SKARVALD_DALRONN_EVENT, NOT_STARTED); + Charge_Timer = 5000; + StoneStrike_Timer = 10000; + Dalronn_isDead = false; + Response_Timer = 0; + Check_Timer = 5000; + Enraged = false; + + ghost = me->GetEntry() == NPC_SKARVALD_GHOST; + if (!ghost) + _Reset(); } - } - void EnterCombat(Unit* who) OVERRIDE - { - if (!ghost && instance) + void EnterCombat(Unit* /*who*/) OVERRIDE { - Talk(YELL_SKARVALD_AGGRO); - - Unit* dalronn = Unit::GetUnit(*me, instance->GetData64(DATA_DALRONN)); - if (dalronn && dalronn->IsAlive() && !dalronn->GetVictim()) - dalronn->getThreatManager().addThreat(who, 0.0f); + if (!ghost) + { + _EnterCombat(); + Talk(YELL_SKARVALD_AGGRO); + } + } - instance->SetData(DATA_SKARVALD_DALRONN_EVENT, IN_PROGRESS); + void DamageTaken(Unit* /*attacker*/, uint32& damage) OVERRIDE + { + if (!Enraged && !ghost && me->HealthBelowPctDamaged(15, damage)) + { + Enraged = true; + DoCast(me, SPELL_ENRAGE); + } } - } - void DamageTaken(Unit* /*attacker*/, uint32& damage) OVERRIDE - { - if (!Enraged && !ghost && me->HealthBelowPctDamaged(15, damage)) + void DoAction(int32 /*actionId*/) { - Enraged = true; - DoCast(me, SPELL_ENRAGE); + summons.DespawnAll(); } - } - void JustDied(Unit* killer) OVERRIDE - { - if (!ghost && instance) + void JustDied(Unit* killer) OVERRIDE { - Unit* dalronn = Unit::GetUnit(*me, instance->GetData64(DATA_DALRONN)); - if (dalronn) + if (!ghost) { - if (dalronn->isDead()) + if (Creature* dalronn = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_DALRONN))) { - Talk(YELL_SKARVALD_DAL_DIED); + if (dalronn->IsAlive()) + { + Talk(YELL_SKARVALD_SKA_DIEDFIRST); - instance->SetData(DATA_SKARVALD_DALRONN_EVENT, DONE); - } - else - { - Talk(YELL_SKARVALD_SKA_DIEDFIRST); + me->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); - me->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); - //DoCast(me, SPELL_SUMMON_SKARVALD_GHOST, true); - Creature* temp = me->SummonCreature(NPC_SKARVALD_GHOST, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0, TEMPSUMMON_CORPSE_DESPAWN, 5000); - if (temp) + //DoCast(me, SPELL_SUMMON_SKARVALD_GHOST, true); + if (Creature* temp = me->SummonCreature(NPC_SKARVALD_GHOST, *me, TEMPSUMMON_CORPSE_DESPAWN, 5000)) + { + temp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + temp->AI()->AttackStart(killer); + } + } + else { - temp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - temp->AI()->AttackStart(killer); + dalronn->AI()->DoAction(0); + _JustDied(); + Talk(YELL_SKARVALD_DAL_DIED); } } } } - } - void KilledUnit(Unit* /*victim*/) OVERRIDE - { - if (!ghost) + void KilledUnit(Unit* who) OVERRIDE { - Talk(YELL_SKARVALD_KILL); + if (!ghost && who->GetTypeId() == TYPEID_PLAYER) + Talk(YELL_SKARVALD_KILL); } - } - void UpdateAI(uint32 diff) OVERRIDE - { - if (ghost) + void UpdateAI(uint32 diff) OVERRIDE { - if (instance && instance->GetData(DATA_SKARVALD_DALRONN_EVENT) != IN_PROGRESS) - me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - } - - if (!UpdateVictim()) - return; + if (!UpdateVictim()) + return; - if (!ghost) - { - if (Check_Timer) + if (!ghost) { - if (Check_Timer <= diff) + if (Check_Timer) { - Check_Timer = 5000; - Unit* dalronn = Unit::GetUnit(*me, instance ? instance->GetData64(DATA_DALRONN) : 0); - if (dalronn && dalronn->isDead()) + if (Check_Timer <= diff) { - Dalronn_isDead = true; - Response_Timer = 2000; - Check_Timer = 0; + Check_Timer = 5000; + Creature* dalronn = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_DALRONN)); + if (dalronn && dalronn->isDead()) + { + Dalronn_isDead = true; + Response_Timer = 2000; + Check_Timer = 0; + } } - } else Check_Timer -= diff; - } - if (Response_Timer && Dalronn_isDead) - { - if (Response_Timer <= diff) + else + Check_Timer -= diff; + } + if (Response_Timer && Dalronn_isDead) { - Talk(YELL_SKARVALD_DAL_DIEDFIRST); + if (Response_Timer <= diff) + { + Talk(YELL_SKARVALD_DAL_DIEDFIRST); - Response_Timer = 0; - } else Response_Timer -= diff; + Response_Timer = 0; + } + else + Response_Timer -= diff; + } } - } - if (Charge_Timer <= diff) - { - DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0, SkarvaldChargePredicate(me)), SPELL_CHARGE); - Charge_Timer = 5000+rand()%5000; - } else Charge_Timer -= diff; + if (Charge_Timer <= diff) + { + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, SkarvaldChargePredicate(me))) + DoCast(target, SPELL_CHARGE); + Charge_Timer = 5000+rand()%5000; + } + else + Charge_Timer -= diff; - if (StoneStrike_Timer <= diff) - { - DoCastVictim(SPELL_STONE_STRIKE); - StoneStrike_Timer = 5000+rand()%5000; - } else StoneStrike_Timer -= diff; + if (StoneStrike_Timer <= diff) + { + DoCastVictim(SPELL_STONE_STRIKE); + StoneStrike_Timer = 5000+rand()%5000; + } + else + StoneStrike_Timer -= diff; - if (!me->HasUnitState(UNIT_STATE_CASTING)) - DoMeleeAttackIfReady(); - } - }; + if (!me->HasUnitState(UNIT_STATE_CASTING)) + DoMeleeAttackIfReady(); + } + }; + CreatureAI* GetAI(Creature* creature) const OVERRIDE + { + return GetUtgardeKeepAI<boss_skarvald_the_constructorAI>(creature); + } }; class boss_dalronn_the_controller : public CreatureScript { -public: - boss_dalronn_the_controller() : CreatureScript("boss_dalronn_the_controller") { } - - CreatureAI* GetAI(Creature* creature) const OVERRIDE - { - return new boss_dalronn_the_controllerAI(creature); - } + public: + boss_dalronn_the_controller() : CreatureScript("boss_dalronn_the_controller") { } - struct boss_dalronn_the_controllerAI : public ScriptedAI - { - boss_dalronn_the_controllerAI(Creature* creature) : ScriptedAI(creature) + struct boss_dalronn_the_controllerAI : public BossAI { - instance = creature->GetInstanceScript(); - } + boss_dalronn_the_controllerAI(Creature* creature) : BossAI(creature, DATA_SKARVALD_DALRONN) { } - InstanceScript* instance; + bool ghost; + uint32 ShadowBolt_Timer; + uint32 Debilitate_Timer; + uint32 Summon_Timer; - bool ghost; - uint32 ShadowBolt_Timer; - uint32 Debilitate_Timer; - uint32 Summon_Timer; + uint32 Response_Timer; + uint32 Check_Timer; + uint32 AggroYell_Timer; + bool Skarvald_isDead; - uint32 Response_Timer; - uint32 Check_Timer; - uint32 AggroYell_Timer; - bool Skarvald_isDead; - - void Reset() OVERRIDE - { - ShadowBolt_Timer = 1000; - Debilitate_Timer = 5000; - Summon_Timer = 10000; - Check_Timer = 5000; - Skarvald_isDead = false; - AggroYell_Timer = 0; - - ghost = me->GetEntry() == NPC_DALRONN_GHOST; - if (!ghost && instance) + void Reset() OVERRIDE { - Unit* skarvald = Unit::GetUnit(*me, instance->GetData64(DATA_SKARVALD)); - if (skarvald && skarvald->isDead()) - skarvald->ToCreature()->Respawn(); - - instance->SetData(DATA_SKARVALD_DALRONN_EVENT, NOT_STARTED); + ShadowBolt_Timer = 1000; + Debilitate_Timer = 5000; + Summon_Timer = 10000; + Check_Timer = 5000; + Skarvald_isDead = false; + Response_Timer = 0; + AggroYell_Timer = 0; + + ghost = me->GetEntry() == NPC_DALRONN_GHOST; + if (!ghost) + _Reset(); } - } - void EnterCombat(Unit* who) OVERRIDE - { - if (!ghost && instance) + void EnterCombat(Unit* /*who*/) OVERRIDE { - Unit* skarvald = Unit::GetUnit(*me, instance->GetData64(DATA_SKARVALD)); - if (skarvald && skarvald->IsAlive() && !skarvald->GetVictim()) - skarvald->getThreatManager().addThreat(who, 0.0f); - - AggroYell_Timer = 5000; + if (!ghost) + { + _EnterCombat(); + AggroYell_Timer = 5000; + } + } - if (instance) - instance->SetData(DATA_SKARVALD_DALRONN_EVENT, IN_PROGRESS); + void DoAction(int32 /*actionId*/) + { + summons.DespawnAll(); } - } - void JustDied(Unit* killer) OVERRIDE - { - if (!ghost && instance) + void JustDied(Unit* killer) OVERRIDE { - Unit* skarvald = Unit::GetUnit(*me, instance->GetData64(DATA_SKARVALD)); - if (skarvald) + if (!ghost) { - if (skarvald->isDead()) + if (Creature* skarvald = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_SKARVALD))) { - Talk(YELL_DALRONN_SKA_DIED); + if (skarvald->IsAlive()) + { + Talk(YELL_DALRONN_DAL_DIEDFIRST); - if (instance) - instance->SetData(DATA_SKARVALD_DALRONN_EVENT, DONE); - } - else - { - Talk(YELL_DALRONN_DAL_DIEDFIRST); + me->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); - me->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); - //DoCast(me, SPELL_SUMMON_DALRONN_GHOST, true); - Creature* temp = me->SummonCreature(NPC_DALRONN_GHOST, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0, TEMPSUMMON_CORPSE_DESPAWN, 5000); - if (temp) + //DoCast(me, SPELL_SUMMON_DALRONN_GHOST, true); + if (Creature* temp = me->SummonCreature(NPC_DALRONN_GHOST, *me, TEMPSUMMON_CORPSE_DESPAWN, 5000)) + { + temp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + temp->AI()->AttackStart(killer); + } + } + else { - temp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - temp->AI()->AttackStart(killer); + skarvald->AI()->DoAction(0); + _JustDied(); + Talk(YELL_DALRONN_SKA_DIED); } } } } - } - void KilledUnit(Unit* /*victim*/) OVERRIDE - { - if (!ghost) + void KilledUnit(Unit* who) OVERRIDE { - Talk(YELL_DALRONN_KILL); + if (!ghost && who->GetTypeId() == TYPEID_PLAYER) + Talk(YELL_DALRONN_KILL); } - } - void UpdateAI(uint32 diff) OVERRIDE - { - if (ghost) + void UpdateAI(uint32 diff) OVERRIDE { - if (instance && instance->GetData(DATA_SKARVALD_DALRONN_EVENT) != IN_PROGRESS) - me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - } + if (!UpdateVictim()) + return; - if (!UpdateVictim()) - return; - - if (AggroYell_Timer) - { - if (AggroYell_Timer <= diff) + if (AggroYell_Timer) { - Talk(YELL_DALRONN_AGGRO); + if (AggroYell_Timer <= diff) + { + Talk(YELL_DALRONN_AGGRO); - AggroYell_Timer = 0; - } else AggroYell_Timer -= diff; - } + AggroYell_Timer = 0; + } + else + AggroYell_Timer -= diff; + } - if (!ghost) - { - if (Check_Timer) + if (!ghost) { - if (Check_Timer <= diff) + if (Check_Timer) { - Check_Timer = 5000; - Unit* skarvald = Unit::GetUnit(*me, instance ? instance->GetData64(DATA_SKARVALD) : 0); - if (skarvald && skarvald->isDead()) + if (Check_Timer <= diff) { - Skarvald_isDead = true; - Response_Timer = 2000; - Check_Timer = 0; + Check_Timer = 5000; + Creature* skarvald = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_SKARVALD)); + if (skarvald && skarvald->isDead()) + { + Skarvald_isDead = true; + Response_Timer = 2000; + Check_Timer = 0; + } } - } else Check_Timer -= diff; - } + else + Check_Timer -= diff; + } - if (Response_Timer && Skarvald_isDead) - { - if (Response_Timer <= diff) + if (Response_Timer && Skarvald_isDead) { - Talk(YELL_DALRONN_SKA_DIEDFIRST); - Response_Timer = 0; - } else Response_Timer -= diff; + if (Response_Timer <= diff) + { + Talk(YELL_DALRONN_SKA_DIEDFIRST); + Response_Timer = 0; + } + else + Response_Timer -= diff; + } } - } - if (ShadowBolt_Timer <= diff) - { - if (!me->IsNonMeleeSpellCasted(false)) + if (ShadowBolt_Timer <= diff) { - DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0), SPELL_SHADOW_BOLT); - ShadowBolt_Timer = 2100;//give a 100ms pause to try cast other spells + if (!me->IsNonMeleeSpellCasted(false)) + { + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true)) + DoCast(target, SPELL_SHADOW_BOLT); + ShadowBolt_Timer = 2100;//give a 100ms pause to try cast other spells + } } - } else ShadowBolt_Timer -= diff; + else + ShadowBolt_Timer -= diff; - if (Debilitate_Timer <= diff) - { - if (!me->IsNonMeleeSpellCasted(false)) + if (Debilitate_Timer <= diff) { - DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0), SPELL_DEBILITATE); - Debilitate_Timer = 5000+rand()%5000; + if (!me->IsNonMeleeSpellCasted(false)) + { + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true)) + DoCast(target, SPELL_DEBILITATE); + Debilitate_Timer = 5000+rand()%5000; + } } - } else Debilitate_Timer -= diff; + else + Debilitate_Timer -= diff; - if (IsHeroic()) - { - if (Summon_Timer <= diff) + if (IsHeroic()) { - if (!me->IsNonMeleeSpellCasted(false)) + if (Summon_Timer <= diff) { - DoCast(me, H_SPELL_SUMMON_SKELETONS); - Summon_Timer = (rand()%10000) + 20000; + if (!me->IsNonMeleeSpellCasted(false)) + { + DoCast(me, H_SPELL_SUMMON_SKELETONS); + Summon_Timer = (rand()%10000) + 20000; + } } - } else Summon_Timer -= diff; + else + Summon_Timer -= diff; + } + + DoMeleeAttackIfReady(); } + }; - DoMeleeAttackIfReady(); + CreatureAI* GetAI(Creature* creature) const OVERRIDE + { + return GetUtgardeKeepAI<boss_dalronn_the_controllerAI>(creature); } - }; - }; void AddSC_boss_skarvald_dalronn() diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/instance_utgarde_keep.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/instance_utgarde_keep.cpp index 92857ce06db..c4e7416f855 100644 --- a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/instance_utgarde_keep.cpp +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/instance_utgarde_keep.cpp @@ -15,300 +15,244 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -/* ScriptData -SDName: Instance_Utgarde_Keep -SD%Complete: 90 -SDComment: Instance Data Scripts and functions to acquire mobs and set encounter status for use in various Utgarde Keep Scripts -SDCategory: Utgarde Keep -EndScriptData */ - #include "ScriptMgr.h" #include "InstanceScript.h" #include "utgarde_keep.h" -#include "Player.h" - -#define MAX_ENCOUNTER 3 - -#define ENTRY_BELLOW_1 186688 -#define ENTRY_BELLOW_2 186689 -#define ENTRY_BELLOW_3 186690 - -#define ENTRY_FORGEFIRE_1 186692 -#define ENTRY_FORGEFIRE_2 186693 -#define ENTRY_FORGEFIRE_3 186691 - -#define ENTRY_GLOWING_ANVIL_1 186609 -#define ENTRY_GLOWING_ANVIL_2 186610 -#define ENTRY_GLOWING_ANVIL_3 186611 -#define ENTRY_GIANT_PORTCULLIS_1 186756 -#define ENTRY_GIANT_PORTCULLIS_2 186694 +DoorData const doorData[] = +{ + { GO_GIANT_PORTCULLIS_1, DATA_INGVAR, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, + { GO_GIANT_PORTCULLIS_2, DATA_INGVAR, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, + { 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE } // END +}; -/* Utgarde Keep encounters: -0 - Prince Keleseth -1 - Skarvald Dalronn -2 - Ingvar the Plunderer -*/ +MinionData const minionData[] = +{ + { NPC_SKARVALD, DATA_SKARVALD_DALRONN }, + { NPC_DALRONN, DATA_SKARVALD_DALRONN } +}; class instance_utgarde_keep : public InstanceMapScript { -public: - instance_utgarde_keep() : InstanceMapScript("instance_utgarde_keep", 574) { } + public: + instance_utgarde_keep() : InstanceMapScript(UKScriptName, 574) { } - InstanceScript* GetInstanceScript(InstanceMap* map) const OVERRIDE - { - return new instance_utgarde_keep_InstanceMapScript(map); - } - - struct instance_utgarde_keep_InstanceMapScript : public InstanceScript - { - instance_utgarde_keep_InstanceMapScript(Map* map) : InstanceScript(map) {} - - uint64 Keleseth; - uint64 Skarvald; - uint64 Dalronn; - uint64 Ingvar; - - uint64 forge_bellow[3]; - uint64 forge_fire[3]; - uint64 forge_anvil[3]; - uint64 portcullis[2]; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - uint32 forge_event[3]; - std::string str_data; - - void Initialize() OVERRIDE - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - Keleseth = 0; - Skarvald = 0; - Dalronn = 0; - Ingvar = 0; - - for (uint8 i = 0; i < 3; ++i) + struct instance_utgarde_keep_InstanceMapScript : public InstanceScript + { + instance_utgarde_keep_InstanceMapScript(Map* map) : InstanceScript(map) { - forge_bellow[i] = 0; - forge_fire[i] = 0; - forge_anvil[i] = 0; - forge_event[i] = NOT_STARTED; + SetBossNumber(EncounterCount); + LoadDoorData(doorData); + LoadMinionData(minionData); + + PrinceKelesethGUID = 0; + SkarvaldGUID = 0; + DalronnGUID = 0; + IngvarGUID = 0; } - portcullis[0] = 0; - portcullis[1] = 0; - } - - bool IsEncounterInProgress() const OVERRIDE - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - return true; - - return false; - } - - Player* GetPlayerInMap() - { - Map::PlayerList const& players = instance->GetPlayers(); - - if (!players.isEmpty()) + void OnCreatureCreate(Creature* creature) OVERRIDE { - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + switch (creature->GetEntry()) { - if (Player* player = itr->GetSource()) - return player; + case NPC_PRINCE_KELESETH: + PrinceKelesethGUID = creature->GetGUID(); + break; + case NPC_SKARVALD: + SkarvaldGUID = creature->GetGUID(); + AddMinion(creature, true); + break; + case NPC_DALRONN: + DalronnGUID = creature->GetGUID(); + AddMinion(creature, true); + break; + case NPC_INGVAR: + IngvarGUID = creature->GetGUID(); + break; + default: + break; } } - TC_LOG_DEBUG(LOG_FILTER_TSCR, "Instance Utgarde Keep: GetPlayerInMap, but PlayerList is empty!"); - return NULL; - } - - void OnCreatureCreate(Creature* creature) OVERRIDE - { - switch (creature->GetEntry()) + void OnCreatureRemove(Creature* creature) OVERRIDE { - case 23953: Keleseth = creature->GetGUID(); break; - case 24201: Dalronn = creature->GetGUID(); break; - case 24200: Skarvald = creature->GetGUID(); break; - case 23954: Ingvar = creature->GetGUID(); break; + switch (creature->GetEntry()) + { + case NPC_SKARVALD: + case NPC_DALRONN: + AddMinion(creature, false); + break; + default: + break; + } } - } - void OnGameObjectCreate(GameObject* go) OVERRIDE - { - switch (go->GetEntry()) + void OnGameObjectCreate(GameObject* go) OVERRIDE { - //door and object id - case ENTRY_BELLOW_1: forge_bellow[0] = go->GetGUID(); - if (forge_event[0] != NOT_STARTED)HandleGameObject(0, true, go);break; - case ENTRY_BELLOW_2: forge_bellow[1] = go->GetGUID(); - if (forge_event[1] != NOT_STARTED)HandleGameObject(0, true, go);break; - case ENTRY_BELLOW_3: forge_bellow[2] = go->GetGUID(); - if (forge_event[2] != NOT_STARTED)HandleGameObject(0, true, go);break; - case ENTRY_FORGEFIRE_1: forge_fire[0] = go->GetGUID(); - if (forge_event[0] != NOT_STARTED)HandleGameObject(0, true, go);break; - case ENTRY_FORGEFIRE_2: forge_fire[1] = go->GetGUID(); - if (forge_event[1] != NOT_STARTED)HandleGameObject(0, true, go);break; - case ENTRY_FORGEFIRE_3: forge_fire[2] = go->GetGUID(); - if (forge_event[2] != NOT_STARTED)HandleGameObject(0, true, go);break; - case ENTRY_GLOWING_ANVIL_1: forge_anvil[0] = go->GetGUID(); - if (forge_event[0] != NOT_STARTED)HandleGameObject(0, true, go);break; - case ENTRY_GLOWING_ANVIL_2: forge_anvil[1] = go->GetGUID(); - if (forge_event[1] != NOT_STARTED)HandleGameObject(0, true, go);break; - case ENTRY_GLOWING_ANVIL_3: forge_anvil[2] = go->GetGUID(); - if (forge_event[2] != NOT_STARTED)HandleGameObject(0, true, go);break; - case ENTRY_GIANT_PORTCULLIS_1: portcullis[0] = go->GetGUID(); - if (m_auiEncounter[2] == DONE)HandleGameObject(0, true, go);break; - case ENTRY_GIANT_PORTCULLIS_2: portcullis[1] = go->GetGUID(); - if (m_auiEncounter[2] == DONE)HandleGameObject(0, true, go);break; + switch (go->GetEntry()) + { + case GO_BELLOW_1: + Forges[0].BellowGUID = go->GetGUID(); + HandleGameObject(0, Forges[0].Event != NOT_STARTED, go); + break; + case GO_BELLOW_2: + Forges[1].BellowGUID = go->GetGUID(); + HandleGameObject(0, Forges[1].Event != NOT_STARTED, go); + break; + case GO_BELLOW_3: + Forges[2].BellowGUID = go->GetGUID(); + HandleGameObject(0, Forges[2].Event != NOT_STARTED, go); + break; + case GO_FORGEFIRE_1: + Forges[0].FireGUID = go->GetGUID(); + HandleGameObject(0, Forges[0].Event != NOT_STARTED, go); + break; + case GO_FORGEFIRE_2: + Forges[1].FireGUID = go->GetGUID(); + HandleGameObject(0, Forges[1].Event != NOT_STARTED, go); + break; + case GO_FORGEFIRE_3: + Forges[2].FireGUID = go->GetGUID(); + HandleGameObject(0, Forges[2].Event != NOT_STARTED, go); + break; + case GO_GLOWING_ANVIL_1: + Forges[0].AnvilGUID = go->GetGUID(); + HandleGameObject(0, Forges[0].Event != NOT_STARTED, go); + break; + case GO_GLOWING_ANVIL_2: + Forges[1].AnvilGUID = go->GetGUID(); + HandleGameObject(0, Forges[1].Event != NOT_STARTED, go); + break; + case GO_GLOWING_ANVIL_3: + Forges[2].AnvilGUID = go->GetGUID(); + HandleGameObject(0, Forges[2].Event != NOT_STARTED, go); + break; + case GO_GIANT_PORTCULLIS_1: + case GO_GIANT_PORTCULLIS_2: + AddDoor(go, true); + break; + default: + break; + } } - } - uint64 GetData64(uint32 identifier) const OVERRIDE - { - switch (identifier) + void OnGameObjectRemove(GameObject* go) OVERRIDE { - case DATA_PRINCEKELESETH: return Keleseth; - case DATA_DALRONN: return Dalronn; - case DATA_SKARVALD: return Skarvald; - case DATA_INGVAR: return Ingvar; + switch (go->GetEntry()) + { + case GO_GIANT_PORTCULLIS_1: + case GO_GIANT_PORTCULLIS_2: + AddDoor(go, false); + break; + default: + break; + } } - return 0; - } - - void SetData(uint32 type, uint32 data) OVERRIDE - { - switch (type) + uint64 GetData64(uint32 type) const OVERRIDE { - case DATA_PRINCEKELESETH_EVENT: - m_auiEncounter[0] = data; - break; - case DATA_SKARVALD_DALRONN_EVENT: - m_auiEncounter[1] = data; - break; - case DATA_INGVAR_EVENT: - if (data == DONE) - { - HandleGameObject(portcullis[0], true); - HandleGameObject(portcullis[1], true); - } - m_auiEncounter[2] = data; - break; - case EVENT_FORGE_1: - if (data == NOT_STARTED) - { - HandleGameObject(forge_bellow[0], false); - HandleGameObject(forge_fire[0], false); - HandleGameObject(forge_anvil[0], false); - }else - { - HandleGameObject(forge_bellow[0], true); - HandleGameObject(forge_fire[0], true); - HandleGameObject(forge_anvil[0], true); - } - forge_event[0] = data; - break; - case EVENT_FORGE_2: - if (data == NOT_STARTED) - { - HandleGameObject(forge_bellow[1], false); - HandleGameObject(forge_fire[1], false); - HandleGameObject(forge_anvil[1], false); - }else - { - HandleGameObject(forge_bellow[1], true); - HandleGameObject(forge_fire[1], true); - HandleGameObject(forge_anvil[1], true); - } - forge_event[1] = data; - break; - case EVENT_FORGE_3: - if (data == NOT_STARTED) - { - HandleGameObject(forge_bellow[2], false); - HandleGameObject(forge_fire[2], false); - HandleGameObject(forge_anvil[2], false); - }else + switch (type) { - HandleGameObject(forge_bellow[2], true); - HandleGameObject(forge_fire[2], true); - HandleGameObject(forge_anvil[2], true); + case DATA_PRINCE_KELESETH: + return PrinceKelesethGUID; + case DATA_SKARVALD: + return SkarvaldGUID; + case DATA_DALRONN: + return DalronnGUID; + case DATA_INGVAR: + return IngvarGUID; + default: + break; } - forge_event[2] = data; - break; - } - if (data == DONE) - { - SaveToDB(); + return 0; } - } - uint32 GetData(uint32 type) const OVERRIDE - { - switch (type) + void SetData(uint32 type, uint32 data) OVERRIDE { - case DATA_PRINCEKELESETH_EVENT: return m_auiEncounter[0]; - case DATA_SKARVALD_DALRONN_EVENT: return m_auiEncounter[1]; - case DATA_INGVAR_EVENT: return m_auiEncounter[2]; + switch (type) + { + case DATA_FORGE_1: + case DATA_FORGE_2: + case DATA_FORGE_3: + { + uint8 i = type - DATA_FORGE_1; + HandleGameObject(Forges[i].AnvilGUID, data != NOT_STARTED); + HandleGameObject(Forges[i].BellowGUID, data != NOT_STARTED); + HandleGameObject(Forges[i].FireGUID, data != NOT_STARTED); + Forges[i].Event = data; + + if (data == DONE) + SaveToDB(); + break; + } + default: + break; + } } - return 0; - } - - std::string GetSaveData() OVERRIDE - { - OUT_SAVE_INST_DATA; + std::string GetSaveData() OVERRIDE + { + OUT_SAVE_INST_DATA; - std::ostringstream saveStream; - saveStream << "U K " << m_auiEncounter[0] << ' ' << m_auiEncounter[1] << ' ' - << m_auiEncounter[2] << ' ' << forge_event[0] << ' ' << forge_event[1] << ' ' << forge_event[2]; + std::ostringstream saveStream; + saveStream << "U K " << GetBossSaveData(); - str_data = saveStream.str(); + for (uint8 i = 0; i < 3; ++i) + saveStream << Forges[i].Event << ' '; - OUT_SAVE_INST_DATA_COMPLETE; - return str_data; - } + OUT_SAVE_INST_DATA_COMPLETE; + return saveStream.str(); + } - void Load(const char* in) OVERRIDE - { - if (!in) + void Load(char const* str) OVERRIDE { - OUT_LOAD_INST_DATA_FAIL; - return; - } + if (!str) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } - OUT_LOAD_INST_DATA(in); + OUT_LOAD_INST_DATA(str); - char dataHead1, dataHead2; - uint16 data0, data1, data2, data3, data4, data5; + char dataHead1, dataHead2; - std::istringstream loadStream(in); - loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3 >> data4 >> data5; + std::istringstream loadStream(str); + loadStream >> dataHead1 >> dataHead2; - if (dataHead1 == 'U' && dataHead2 == 'K') - { - m_auiEncounter[0] = data0; - m_auiEncounter[1] = data1; - m_auiEncounter[2] = data2; + if (dataHead1 == 'U' && dataHead2 == 'K') + { + for (uint32 i = 0; i < EncounterCount; ++i) + { + uint32 tmpState; + loadStream >> tmpState; + if (tmpState == IN_PROGRESS || tmpState > SPECIAL) + tmpState = NOT_STARTED; + SetBossState(i, EncounterState(tmpState)); + } + + for (uint8 i = 0; i < 3; ++i) + loadStream >> Forges[i].Event; + } + else + OUT_LOAD_INST_DATA_FAIL; - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - m_auiEncounter[i] = NOT_STARTED; + OUT_LOAD_INST_DATA_COMPLETE; + } - forge_event[0] = data3; - forge_event[1] = data4; - forge_event[2] = data5; + protected: + ForgeInfo Forges[3]; - } else OUT_LOAD_INST_DATA_FAIL; + uint64 PrinceKelesethGUID; + uint64 SkarvaldGUID; + uint64 DalronnGUID; + uint64 IngvarGUID; + }; - OUT_LOAD_INST_DATA_COMPLETE; + InstanceScript* GetInstanceScript(InstanceMap* map) const OVERRIDE + { + return new instance_utgarde_keep_InstanceMapScript(map); } - }; - }; void AddSC_instance_utgarde_keep() diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/utgarde_keep.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/utgarde_keep.cpp index 2de21278953..c1470519f63 100644 --- a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/utgarde_keep.cpp +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/utgarde_keep.cpp @@ -26,142 +26,97 @@ enum Spells SPELL_UK_SECOUND_WIND_TRIGGER = 42771 }; -uint32 entry_search[3] = +uint32 ForgeSearch[3] = { - 186609, - 186610, - 186611 + GO_GLOWING_ANVIL_1, + GO_GLOWING_ANVIL_2, + GO_GLOWING_ANVIL_3 }; class npc_dragonflayer_forge_master : public CreatureScript { -public: - npc_dragonflayer_forge_master() : CreatureScript("npc_dragonflayer_forge_master") { } - - CreatureAI* GetAI(Creature* creature) const OVERRIDE - { - return new npc_dragonflayer_forge_masterAI(creature); - } + public: + npc_dragonflayer_forge_master() : CreatureScript("npc_dragonflayer_forge_master") { } - struct npc_dragonflayer_forge_masterAI : public ScriptedAI - { - npc_dragonflayer_forge_masterAI(Creature* creature) : ScriptedAI(creature) + struct npc_dragonflayer_forge_masterAI : public ScriptedAI { - instance = creature->GetInstanceScript(); - fm_Type = 0; - } + npc_dragonflayer_forge_masterAI(Creature* creature) : ScriptedAI(creature) + { + _instance = creature->GetInstanceScript(); + _forgeId = 0; + } - InstanceScript* instance; - uint8 fm_Type; + void Reset() OVERRIDE + { + if (!_forgeId) + _forgeId = GetForgeMasterType(); - void Reset() OVERRIDE - { - if (fm_Type == 0) - fm_Type = GetForgeMasterType(); + if (!me->IsAlive()) + return; - CheckForge(); - } + if (_forgeId) + _instance->SetData(DATA_FORGE_1 + _forgeId - 1, NOT_STARTED); + } - void CheckForge() - { - if (instance) + void JustDied(Unit* /*killer*/) OVERRIDE { - switch (fm_Type) - { - case 1: - instance->SetData(EVENT_FORGE_1, me->IsAlive() ? NOT_STARTED : DONE); - break; - - case 2: - instance->SetData(EVENT_FORGE_2, me->IsAlive() ? NOT_STARTED : DONE); - break; + if (!_forgeId) + _forgeId = GetForgeMasterType(); - case 3: - instance->SetData(EVENT_FORGE_3, me->IsAlive() ? NOT_STARTED : DONE); - break; - } + if (_forgeId) + _instance->SetData(DATA_FORGE_1 + _forgeId - 1, DONE); } - } - - void JustDied(Unit* /*killer*/) OVERRIDE - { - if (fm_Type == 0) - fm_Type = GetForgeMasterType(); - if (instance) + void EnterCombat(Unit* /*who*/) OVERRIDE { - switch (fm_Type) - { - case 1: - instance->SetData(EVENT_FORGE_1, DONE); - break; + if (!_forgeId) + _forgeId = GetForgeMasterType(); - case 2: - instance->SetData(EVENT_FORGE_2, DONE); - break; + if (_forgeId) + _instance->SetData(DATA_FORGE_1 + _forgeId - 1, IN_PROGRESS); - case 3: - instance->SetData(EVENT_FORGE_3, DONE); - break; - } + me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE); } - } - - void EnterCombat(Unit* /*who*/) OVERRIDE - { - if (fm_Type == 0) - fm_Type = GetForgeMasterType(); - if (instance) + void UpdateAI(uint32 /*diff*/) OVERRIDE { - switch (fm_Type) - { - case 1: - instance->SetData(EVENT_FORGE_1, IN_PROGRESS); - break; + if (!_forgeId) + _forgeId = GetForgeMasterType(); - case 2: - instance->SetData(EVENT_FORGE_2, IN_PROGRESS); - break; + if (!UpdateVictim()) + return; - case 3: - instance->SetData(EVENT_FORGE_3, IN_PROGRESS); - break; - } + DoMeleeAttackIfReady(); } - me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE); - } - uint8 GetForgeMasterType() - { - float diff = 30.0f; - uint8 near_f = 0; - - for (uint8 i = 0; i < 3; ++i) + private: + uint8 GetForgeMasterType() { - if (GameObject* go = me->FindNearestGameObject(entry_search[i], 30)) + float diff = 30.0f; + uint8 id = 0; + + for (uint8 i = 0; i < 3; ++i) { - if (me->IsWithinDist(go, diff, false)) + if (GameObject* go = me->FindNearestGameObject(ForgeSearch[i], 30)) { - near_f = i + 1; - diff = me->GetDistance2d(go); + if (me->IsWithinDist(go, diff, false)) + { + id = i + 1; + diff = me->GetDistance2d(go); + } } } + return id > 0 && id < 4 ? id : 0; } - return near_f > 0 && near_f < 4 ? near_f : 0; - } - void UpdateAI(uint32 /* diff */) OVERRIDE - { - if (fm_Type == 0) - fm_Type = GetForgeMasterType(); - - if (!UpdateVictim()) - return; + InstanceScript* _instance; + uint8 _forgeId; + }; - DoMeleeAttackIfReady(); + CreatureAI* GetAI(Creature* creature) const OVERRIDE + { + return GetUtgardeKeepAI<npc_dragonflayer_forge_masterAI>(creature); } - }; }; enum TickingTimeBomb @@ -188,9 +143,7 @@ class spell_ticking_time_bomb : public SpellScriptLoader void HandleOnEffectRemove(AuraEffect const* /* aurEff */, AuraEffectHandleModes /* mode */) { if (GetCaster() == GetTarget()) - { GetTarget()->CastSpell(GetTarget(), SPELL_TICKING_TIME_BOMB_EXPLODE, true); - } } void Register() OVERRIDE @@ -209,6 +162,7 @@ enum Fixate { SPELL_FIXATE_TRIGGER = 40415 }; + class spell_fixate : public SpellScriptLoader { public: @@ -227,8 +181,7 @@ class spell_fixate : public SpellScriptLoader void HandleScriptEffect(SpellEffIndex /*effIndex*/) { - // The unit has to cast the taunt on hisself, but we need the original caster for SPELL_AURA_MOD_TAUNT - GetCaster()->CastSpell(GetCaster(), SPELL_FIXATE_TRIGGER, true, 0, 0, GetHitUnit()->GetGUID()); + GetHitUnit()->CastSpell(GetCaster(), SPELL_FIXATE_TRIGGER, true); } void Register() OVERRIDE @@ -265,86 +218,86 @@ const Position protodrakeCheckPos = {206.24f, -190.28f, 200.11f, 0.f}; class npc_enslaved_proto_drake : public CreatureScript { -public: - npc_enslaved_proto_drake() : CreatureScript("npc_enslaved_proto_drake") { } + public: + npc_enslaved_proto_drake() : CreatureScript("npc_enslaved_proto_drake") { } - struct npc_enslaved_proto_drakeAI : public ScriptedAI - { - npc_enslaved_proto_drakeAI(Creature* creature) : ScriptedAI(creature) + struct npc_enslaved_proto_drakeAI : public ScriptedAI { - _setData = false; - } + npc_enslaved_proto_drakeAI(Creature* creature) : ScriptedAI(creature) + { + _setData = false; + } - void Reset() OVERRIDE - { - _events.Reset(); - _events.ScheduleEvent(EVENT_REND, urand(2000, 3000)); - _events.ScheduleEvent(EVENT_FLAME_BREATH, urand(5500, 7000)); - _events.ScheduleEvent(EVENT_KNOCKAWAY, urand(3500, 6000)); - } + void Reset() OVERRIDE + { + _events.Reset(); + _events.ScheduleEvent(EVENT_REND, urand(2000, 3000)); + _events.ScheduleEvent(EVENT_FLAME_BREATH, urand(5500, 7000)); + _events.ScheduleEvent(EVENT_KNOCKAWAY, urand(3500, 6000)); + } - void MovementInform(uint32 type, uint32 id) OVERRIDE - { - if (type == WAYPOINT_MOTION_TYPE && id == POINT_LAST) + void MovementInform(uint32 type, uint32 id) OVERRIDE { - me->RemoveByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER); + if (type == WAYPOINT_MOTION_TYPE && id == POINT_LAST) + { + me->RemoveByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER); + } } - } - void SetData(uint32 type, uint32 data) OVERRIDE - { - if (type == TYPE_PROTODRAKE_AT && data == DATA_PROTODRAKE_MOVE && !_setData && me->GetDistance(protodrakeCheckPos) < 5.0f) + void SetData(uint32 type, uint32 data) OVERRIDE { - _setData = true; - me->SetByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER); - me->GetMotionMaster()->MovePath(PATH_PROTODRAKE, false); + if (type == TYPE_PROTODRAKE_AT && data == DATA_PROTODRAKE_MOVE && !_setData && me->GetDistance(protodrakeCheckPos) < 5.0f) + { + _setData = true; + me->SetByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER); + me->GetMotionMaster()->MovePath(PATH_PROTODRAKE, false); + } } - } - void UpdateAI(uint32 diff) OVERRIDE - { - if (!UpdateVictim()) - return; + void UpdateAI(uint32 diff) OVERRIDE + { + if (!UpdateVictim()) + return; - _events.Update(diff); + _events.Update(diff); - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; - while (uint32 eventid = _events.ExecuteEvent()) - { - switch (eventid) + while (uint32 eventid = _events.ExecuteEvent()) { - case EVENT_REND: - DoCast(SPELL_REND); - _events.ScheduleEvent(EVENT_REND, urand(15000, 20000)); - break; - case EVENT_FLAME_BREATH: - DoCast(SPELL_FLAME_BREATH); - _events.ScheduleEvent(EVENT_FLAME_BREATH, urand(11000, 12000)); - break; - case EVENT_KNOCKAWAY: - DoCast(SPELL_KNOCK_AWAY); - _events.ScheduleEvent(EVENT_KNOCKAWAY, urand(7000, 8500)); - break; - default: - break; + switch (eventid) + { + case EVENT_REND: + DoCast(SPELL_REND); + _events.ScheduleEvent(EVENT_REND, urand(15000, 20000)); + break; + case EVENT_FLAME_BREATH: + DoCast(SPELL_FLAME_BREATH); + _events.ScheduleEvent(EVENT_FLAME_BREATH, urand(11000, 12000)); + break; + case EVENT_KNOCKAWAY: + DoCast(SPELL_KNOCK_AWAY); + _events.ScheduleEvent(EVENT_KNOCKAWAY, urand(7000, 8500)); + break; + default: + break; + } } - } - DoMeleeAttackIfReady(); - } + DoMeleeAttackIfReady(); + } - private: - bool _setData; - EventMap _events; + private: + bool _setData; + EventMap _events; - }; + }; - CreatureAI* GetAI(Creature* creature) const OVERRIDE - { - return new npc_enslaved_proto_drakeAI(creature); - } + CreatureAI* GetAI(Creature* creature) const OVERRIDE + { + return new npc_enslaved_proto_drakeAI(creature); + } }; class spell_uk_second_wind_proc : public SpellScriptLoader diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/utgarde_keep.h b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/utgarde_keep.h index b0d9d702db5..873c5d634fa 100644 --- a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/utgarde_keep.h +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/utgarde_keep.h @@ -15,23 +15,79 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef DEF_UTGARDE_KEEP_H -#define DEF_UTGARDE_KEEP_H +#ifndef UTGARDE_KEEP_H_ +#define UTGARDE_KEEP_H_ + +#define UKScriptName "instance_utgarde_keep" + +uint32 const EncounterCount = 3; enum DataTypes { - DATA_PRINCEKELESETH = 1, - DATA_SKARVALD = 3, - DATA_DALRONN = 4, - DATA_INGVAR = 6, - - DATA_PRINCEKELESETH_EVENT = 2, - DATA_SKARVALD_DALRONN_EVENT = 5, - DATA_INGVAR_EVENT = 7, - - EVENT_FORGE_1 = 8, - EVENT_FORGE_2 = 9, - EVENT_FORGE_3 = 10 + // Encounter States/Boss GUIDs + DATA_PRINCE_KELESETH = 0, + DATA_SKARVALD_DALRONN = 1, + DATA_INGVAR = 2, + + // Additional Data + DATA_SKARVALD = 3, + DATA_DALRONN = 4, + + DATA_FORGE_1 = 5, + DATA_FORGE_2 = 6, + DATA_FORGE_3 = 7 +}; + +enum CreatureIds +{ + NPC_PRINCE_KELESETH = 23953, + NPC_SKARVALD = 24200, + NPC_DALRONN = 24201, + NPC_INGVAR = 23954, + + // Skarvald - Dalronn + NPC_DALRONN_GHOST = 27389, + NPC_SKARVALD_GHOST = 27390, + + // Ingvar the Plunderer + NPC_INGVAR_UNDEAD = 23980, + NPC_THROW_TARGET = 23996, + NPC_ANNHYLDE_THE_CALLER = 24068 +}; + +enum GameObjectIds +{ + GO_BELLOW_1 = 186688, + GO_BELLOW_2 = 186689, + GO_BELLOW_3 = 186690, + + GO_FORGEFIRE_1 = 186692, + GO_FORGEFIRE_2 = 186693, + GO_FORGEFIRE_3 = 186691, + + GO_GLOWING_ANVIL_1 = 186609, + GO_GLOWING_ANVIL_2 = 186610, + GO_GLOWING_ANVIL_3 = 186611, + + GO_GIANT_PORTCULLIS_1 = 186756, + GO_GIANT_PORTCULLIS_2 = 186694 }; -#endif +struct ForgeInfo +{ + ForgeInfo() : AnvilGUID(0), BellowGUID(0), FireGUID(0), Event(NOT_STARTED) { }; + + uint64 AnvilGUID; + uint64 BellowGUID; + uint64 FireGUID; + + uint32 Event; +}; + +template<class AI> +AI* GetUtgardeKeepAI(Creature* creature) +{ + return GetInstanceAI<AI>(creature, UKScriptName); +} + +#endif // UTGARDE_KEEP_H_ diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_ymiron.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_ymiron.cpp index a54a1b6bec7..f592a4b2bb2 100644 --- a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_ymiron.cpp +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_ymiron.cpp @@ -159,6 +159,7 @@ public: void Reset() OVERRIDE { + m_bIsWalking = false; m_bIsPause = false; m_bIsActiveWithBJORN = false; m_bIsActiveWithHALDOR = false; diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/instance_pinnacle.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/instance_utgarde_pinnacle.cpp index 0277c21cb83..0277c21cb83 100644 --- a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/instance_pinnacle.cpp +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/instance_utgarde_pinnacle.cpp diff --git a/src/server/scripts/Northrend/VaultOfArchavon/boss_archavon.cpp b/src/server/scripts/Northrend/VaultOfArchavon/boss_archavon.cpp index e44e0ab0539..7d3d149f0ff 100644 --- a/src/server/scripts/Northrend/VaultOfArchavon/boss_archavon.cpp +++ b/src/server/scripts/Northrend/VaultOfArchavon/boss_archavon.cpp @@ -17,6 +17,7 @@ #include "ScriptMgr.h" #include "ScriptedCreature.h" +#include "SpellScript.h" #include "vault_of_archavon.h" enum Emotes @@ -27,9 +28,12 @@ enum Emotes enum Spells { - // Spells Archavon SPELL_ROCK_SHARDS = 58678, + SPELL_ROCK_SHARDS_VISUAL_L = 58689, + SPELL_ROCK_SHARDS_VISUAL_R = 58692, + SPELL_ROCK_SHARDS_DAMAGE_L = 58695, + SPELL_ROCK_SHARDS_DAMAGE_R = 58696, SPELL_CRUSHING_LEAP = 58960, SPELL_STOMP = 58663, SPELL_IMPALE = 58666, @@ -205,8 +209,55 @@ class npc_archavon_warder : public CreatureScript } }; +// 58941 - Rock Shards +class spell_archavon_rock_shards : public SpellScriptLoader +{ + public: + spell_archavon_rock_shards() : SpellScriptLoader("spell_archavon_rock_shards") { } + + class spell_archavon_rock_shards_SpellScript : public SpellScript + { + PrepareSpellScript(spell_archavon_rock_shards_SpellScript); + + bool Validate(SpellInfo const* /*spellInfo*/) OVERRIDE + { + if (!sSpellMgr->GetSpellInfo(SPELL_ROCK_SHARDS_VISUAL_L) + || !sSpellMgr->GetSpellInfo(SPELL_ROCK_SHARDS_VISUAL_R) + || !sSpellMgr->GetSpellInfo(SPELL_ROCK_SHARDS_DAMAGE_L) + || !sSpellMgr->GetSpellInfo(SPELL_ROCK_SHARDS_DAMAGE_R)) + return false; + return true; + } + + void HandleScript(SpellEffIndex /*effIndex*/) + { + Unit* caster = GetCaster(); + + for (uint8 i = 0; i < 3; ++i) + { + caster->CastSpell((Unit*)NULL, SPELL_ROCK_SHARDS_VISUAL_L, true); + caster->CastSpell((Unit*)NULL, SPELL_ROCK_SHARDS_VISUAL_R, true); + } + + caster->CastSpell((Unit*)NULL, SPELL_ROCK_SHARDS_DAMAGE_L, true); + caster->CastSpell((Unit*)NULL, SPELL_ROCK_SHARDS_DAMAGE_R, true); + } + + void Register() OVERRIDE + { + OnEffectHit += SpellEffectFn(spell_archavon_rock_shards_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const OVERRIDE + { + return new spell_archavon_rock_shards_SpellScript(); + } +}; + void AddSC_boss_archavon() { new boss_archavon(); new npc_archavon_warder(); + new spell_archavon_rock_shards(); } diff --git a/src/server/scripts/Northrend/VaultOfArchavon/instance_vault_of_archavon.cpp b/src/server/scripts/Northrend/VaultOfArchavon/instance_vault_of_archavon.cpp index 77fc0877056..c6e3894a722 100644 --- a/src/server/scripts/Northrend/VaultOfArchavon/instance_vault_of_archavon.cpp +++ b/src/server/scripts/Northrend/VaultOfArchavon/instance_vault_of_archavon.cpp @@ -26,14 +26,14 @@ 4 - Toravon the Ice Watcher event */ -class instance_archavon : public InstanceMapScript +class instance_vault_of_archavon : public InstanceMapScript { public: - instance_archavon() : InstanceMapScript("instance_archavon", 624) { } + instance_vault_of_archavon() : InstanceMapScript("instance_vault_of_archavon", 624) { } - struct instance_archavon_InstanceMapScript : public InstanceScript + struct instance_vault_of_archavon_InstanceMapScript : public InstanceScript { - instance_archavon_InstanceMapScript(Map* map) : InstanceScript(map) + instance_vault_of_archavon_InstanceMapScript(Map* map) : InstanceScript(map) { SetBossNumber(EncounterCount); @@ -135,11 +135,11 @@ class instance_archavon : public InstanceMapScript InstanceScript* GetInstanceScript(InstanceMap* map) const OVERRIDE { - return new instance_archavon_InstanceMapScript(map); + return new instance_vault_of_archavon_InstanceMapScript(map); } }; -void AddSC_instance_archavon() +void AddSC_instance_vault_of_archavon() { - new instance_archavon(); + new instance_vault_of_archavon(); } diff --git a/src/server/scripts/Northrend/VioletHold/instance_violet_hold.cpp b/src/server/scripts/Northrend/VioletHold/instance_violet_hold.cpp index 025e93ac8d9..60d7570b96f 100644 --- a/src/server/scripts/Northrend/VioletHold/instance_violet_hold.cpp +++ b/src/server/scripts/Northrend/VioletHold/instance_violet_hold.cpp @@ -608,6 +608,7 @@ public: if (GameObject* pMainDoor = instance->GetGameObject(uiMainDoor)) pMainDoor->SetGoState(GO_STATE_READY); DoUpdateWorldState(WORLD_STATE_VH_PRISON_STATE, 100); + // no break } default: SpawnPortal(); diff --git a/src/server/scripts/Northrend/zone_borean_tundra.cpp b/src/server/scripts/Northrend/zone_borean_tundra.cpp index 6d2a48910fe..2b5508272d9 100644 --- a/src/server/scripts/Northrend/zone_borean_tundra.cpp +++ b/src/server/scripts/Northrend/zone_borean_tundra.cpp @@ -90,7 +90,7 @@ public: } } - void EnterCombat(Unit* /*who*/)OVERRIDE {} + void EnterCombat(Unit* /*who*/) OVERRIDE {} void UpdateAI(uint32 diff) OVERRIDE { @@ -119,7 +119,8 @@ public: case 3: DoCast(me, SPELL_EXPLODE_CART, true); phaseTimer = 2000; - phase = 4; + phase = 5; // @fixme: phase 4 is missing... + break; case 5: DoCast(me, SPELL_SUMMON_WORM, true); if (Unit* worm = me->FindNearestCreature(26250, 3)) @@ -142,7 +143,7 @@ public: break; case 7: DoCast(me, SPELL_EXPLODE_CART, true); - if (Player* caster = Unit::GetPlayer(*me, casterGuid)) + if (Player* caster = ObjectAccessor::GetPlayer(*me, casterGuid)) caster->KilledMonster(me->GetCreatureTemplate(), me->GetGUID()); phaseTimer = 5000; phase = 8; @@ -857,7 +858,7 @@ public: { if (me->IsWithinDistInMap(who, INTERACTION_DISTANCE)) { - if (Player* pHarpooner = Unit::GetPlayer(*me, HarpoonerGUID)) + if (Player* pHarpooner = ObjectAccessor::GetPlayer(*me, HarpoonerGUID)) { pHarpooner->KilledMonsterCredit(26175, 0); pHarpooner->RemoveAura(SPELL_DRAKE_HATCHLING_SUBDUED); @@ -873,7 +874,7 @@ public: { if (WithRedDragonBlood && HarpoonerGUID && !me->HasAura(SPELL_RED_DRAGONBLOOD)) { - if (Player* pHarpooner = Unit::GetPlayer(*me, HarpoonerGUID)) + if (Player* pHarpooner = ObjectAccessor::GetPlayer(*me, HarpoonerGUID)) { EnterEvadeMode(); StartFollow(pHarpooner, 35, NULL); @@ -1718,7 +1719,7 @@ public: void GotStinged(uint64 casterGUID) { - if (Player* caster = Player::GetPlayer(*me, casterGUID)) + if (Player* caster = ObjectAccessor::GetPlayer(*me, casterGUID)) { uint32 step = caster->GetAuraCount(SPELL_NEURAL_NEEDLE) + 1; switch (step) @@ -2378,7 +2379,7 @@ public: { me->StopMoving(); me->SetUInt32Value(UNIT_NPC_FLAGS, 0); - if (Player* player = me->GetPlayer(*me, uiPlayerGUID)) + if (Player* player = ObjectAccessor::GetPlayer(*me, uiPlayerGUID)) me->SetFacingToObject(player); uiEventTimer = 3000; uiEventPhase = 1; @@ -2392,7 +2393,7 @@ public: void AttackPlayer() { me->setFaction(14); - if (Player* player = me->GetPlayer(*me, uiPlayerGUID)) + if (Player* player = ObjectAccessor::GetPlayer(*me, uiPlayerGUID)) me->AI()->AttackStart(player); } @@ -2428,7 +2429,7 @@ public: { case NPC_SALTY_JOHN_THORPE: Talk(SAY_HIDDEN_CULTIST_4); - if (Player* player = me->GetPlayer(*me, uiPlayerGUID)) + if (Player* player = ObjectAccessor::GetPlayer(*me, uiPlayerGUID)) me->SetFacingToObject(player); uiEventTimer = 3000; uiEventPhase = 3; diff --git a/src/server/scripts/Northrend/zone_grizzly_hills.cpp b/src/server/scripts/Northrend/zone_grizzly_hills.cpp index 9b68b37507b..1a080824136 100644 --- a/src/server/scripts/Northrend/zone_grizzly_hills.cpp +++ b/src/server/scripts/Northrend/zone_grizzly_hills.cpp @@ -638,7 +638,7 @@ public: switch (eventId) { case EVENT_STRAGGLER_1: - if (Player* player = Unit::GetPlayer(*me, _playerGUID)) + if (Player* player = ObjectAccessor::GetPlayer(*me, _playerGUID)) DoCast(player, SPELL_VENTURE_STRAGGLER_CREDIT); me->GetMotionMaster()->MovePoint(0, me->GetPositionX()-7, me->GetPositionY()+7, me->GetPositionZ()); _events.ScheduleEvent(EVENT_STRAGGLER_2, 2500); diff --git a/src/server/scripts/Northrend/zone_howling_fjord.cpp b/src/server/scripts/Northrend/zone_howling_fjord.cpp index 15273088940..4626ffabd79 100644 --- a/src/server/scripts/Northrend/zone_howling_fjord.cpp +++ b/src/server/scripts/Northrend/zone_howling_fjord.cpp @@ -338,7 +338,7 @@ public: void JustSummoned(Creature* summon) OVERRIDE { - if (Player* player = me->GetPlayer(*me, uiPlayerGUID)) + if (Player* player = ObjectAccessor::GetPlayer(*me, uiPlayerGUID)) { if (player->IsAlive()) { diff --git a/src/server/scripts/Northrend/zone_sholazar_basin.cpp b/src/server/scripts/Northrend/zone_sholazar_basin.cpp index c1bca1dae76..bf284c5138b 100644 --- a/src/server/scripts/Northrend/zone_sholazar_basin.cpp +++ b/src/server/scripts/Northrend/zone_sholazar_basin.cpp @@ -465,23 +465,18 @@ public: #####*/ #define SAY_OFFER "Care to try Grimbooze Thunderbrew's new jungle punch?" -#define SAY_HEMET_1 "Aye, I'll try it." -#define SAY_HEMET_2 "That's exactly what I needed!" -#define SAY_HEMET_3 "It's got my vote! That'll put hair on your chest like nothing else will." -#define SAY_HADRIUS_1 "I'm always up for something of Grimbooze's." -#define SAY_HADRIUS_2 "Well, so far, it tastes like something my wife would drink..." -#define SAY_HADRIUS_3 "Now, there's the kick I've come to expect from Grimbooze's drinks! I like it!" -#define SAY_TAMARA_1 "Sure!" -#define SAY_TAMARA_2 "Oh my..." -#define SAY_TAMARA_3 "Tastes like I'm drinking... engine degreaser!" - -enum utils + +enum JunglePunch { - NPC_HEMET = 27986, - NPC_HADRIUS = 28047, - NPC_TAMARA = 28568, SPELL_OFFER = 51962, - QUEST_ENTRY = 12645, + QUEST_TASTE_TEST = 12645, + + SAY_HEMET_HADRIUS_TAMARA_1 = 0, + SAY_HEMET_HADRIUS_TAMARA_2 = 1, + SAY_HEMET_HADRIUS_TAMARA_3 = 2, + + SAY_HEMET_4 = 3, // unused + SAY_HEMET_5 = 4 // unused }; enum NesingwaryChildrensWeek @@ -492,12 +487,12 @@ enum NesingwaryChildrensWeek ORPHAN_WOLVAR = 33532, + TEXT_NESINGWARY_1 = 5, + TEXT_WOLVAR_ORPHAN_6 = 6, TEXT_WOLVAR_ORPHAN_7 = 7, TEXT_WOLVAR_ORPHAN_8 = 8, - TEXT_WOLVAR_ORPHAN_9 = 9, - - TEXT_NESINGWARY_1 = 1, + TEXT_WOLVAR_ORPHAN_9 = 9 }; class npc_jungle_punch_target : public CreatureScript @@ -520,7 +515,6 @@ public: } void MoveInLineOfSight(Unit* who) OVERRIDE - { if (!phase && who && who->GetDistance2d(me) < 10.0f) if (Player* player = who->ToPlayer()) @@ -540,8 +534,8 @@ public: { if (timer <= diff) { - Player* player = Player::GetPlayer(*me, playerGUID); - Creature* orphan = Creature::GetCreature(*me, orphanGUID); + Player* player = ObjectAccessor::GetPlayer(*me, playerGUID); + Creature* orphan = ObjectAccessor::GetCreature(*me, orphanGUID); if (!orphan || !player) { @@ -585,99 +579,55 @@ public: timer -= diff; } - void UpdateAI(uint32 uiDiff) OVERRIDE + void UpdateAI(uint32 diff) OVERRIDE { if (phase) - proceedCwEvent(uiDiff); + proceedCwEvent(diff); if (!sayStep) return; - if (sayTimer < uiDiff) + if (sayTimer < diff) { - switch (sayStep) - { - case 0: - { - switch (me->GetEntry()) - { - case NPC_HEMET: me->MonsterSay(SAY_HEMET_1, LANG_UNIVERSAL, 0); break; - case NPC_HADRIUS: me->MonsterSay(SAY_HADRIUS_1, LANG_UNIVERSAL, 0); break; - case NPC_TAMARA: me->MonsterSay(SAY_TAMARA_1, LANG_UNIVERSAL, 0); break; - } - sayTimer = 3000; - sayStep++; - break; - } - case 1: - { - switch (me->GetEntry()) - { - case NPC_HEMET: me->MonsterSay(SAY_HEMET_2, LANG_UNIVERSAL, 0); break; - case NPC_HADRIUS: me->MonsterSay(SAY_HADRIUS_2, LANG_UNIVERSAL, 0); break; - case NPC_TAMARA: me->MonsterSay(SAY_TAMARA_2, LANG_UNIVERSAL, 0); break; - } - sayTimer = 3000; - sayStep++; - break; - } - case 2: - { - switch (me->GetEntry()) - { - case NPC_HEMET: me->MonsterSay(SAY_HEMET_3, LANG_UNIVERSAL, 0); break; - case NPC_HADRIUS: me->MonsterSay(SAY_HADRIUS_3, LANG_UNIVERSAL, 0); break; - case NPC_TAMARA: me->MonsterSay(SAY_TAMARA_3, LANG_UNIVERSAL, 0); break; - } - sayTimer = 3000; - sayStep = 0; - break; - } - } + Talk(SAY_HEMET_HADRIUS_TAMARA_1 + sayStep - 1); + sayTimer = 3000; + sayStep++; + + if (sayStep > 3) // end + sayStep = 0; } else - sayTimer -= uiDiff; + sayTimer -= diff; } - void SpellHit(Unit* caster, const SpellInfo* proto) OVERRIDE + void SpellHit(Unit* caster, SpellInfo const* spellInfo) OVERRIDE { - if (!proto || proto->Id != SPELL_OFFER) + if (spellInfo->Id != SPELL_OFFER) return; - if (!caster->ToPlayer()) + Player* player = caster->ToPlayer(); + if (!player) + return; + + Quest const* quest = sObjectMgr->GetQuestTemplate(QUEST_TASTE_TEST); + if (!quest) return; - QuestStatusMap::const_iterator itr = caster->ToPlayer()->getQuestStatusMap().find(QUEST_ENTRY); + QuestStatusMap::const_iterator itr = player->getQuestStatusMap().find(QUEST_TASTE_TEST); if (itr->second.Status != QUEST_STATUS_INCOMPLETE) return; - for (uint8 i=0; i<3; i++) + for (uint8 i = 0; i < 3; ++i) { - switch (i) - { - case 0: - if (NPC_HEMET != me->GetEntry()) - continue; - else - break; - case 1: - if (NPC_HADRIUS != me->GetEntry()) - continue; - else - break; - case 2: - if (NPC_TAMARA != me->GetEntry()) - continue; - else - break; - } + if (uint32(quest->RequiredNpcOrGo[i]) != me->GetEntry()) + continue; if (itr->second.CreatureOrGOCount[i] != 0) continue; - caster->ToPlayer()->KilledMonsterCredit(me->GetEntry(), 0); - caster->ToPlayer()->Say(SAY_OFFER, LANG_UNIVERSAL); - sayStep = 0; + player->KilledMonsterCredit(me->GetEntry(), 0); + player->Say(SAY_OFFER, LANG_UNIVERSAL); + sayStep = 1; break; } } diff --git a/src/server/scripts/Northrend/zone_wintergrasp.cpp b/src/server/scripts/Northrend/zone_wintergrasp.cpp index 0b9c319bf56..a27ce0324ff 100644 --- a/src/server/scripts/Northrend/zone_wintergrasp.cpp +++ b/src/server/scripts/Northrend/zone_wintergrasp.cpp @@ -334,13 +334,19 @@ class npc_wg_quest_giver : public CreatureScript bool OnGossipHello(Player* player, Creature* creature) OVERRIDE { - if (creature->IsQuestGiver()) - player->PrepareQuestMenu(creature->GetGUID()); - Battlefield* wintergrasp = sBattlefieldMgr->GetBattlefieldByBattleId(BATTLEFIELD_BATTLEID_WG); if (!wintergrasp) return true; + if (creature->IsVendor()) + { + player->ADD_GOSSIP_ITEM_DB(Player::GetDefaultGossipMenuForSource(creature), 0, GOSSIP_SENDER_MAIN, GOSSIP_OPTION_VENDOR); + player->PlayerTalkClass->GetGossipMenu().AddGossipMenuItemData(0, 0, 0); + } + + /// @todo: move this to conditions or something else + + // Player::PrepareQuestMenu(guid) if (creature->IsQuestGiver()) { QuestRelationBounds objectQR = sObjectMgr->GetCreatureQuestRelationBounds(creature->GetEntry()); @@ -368,6 +374,9 @@ class npc_wg_quest_giver : public CreatureScript if (!quest) continue; + if (!player->CanTakeQuest(quest, false)) + continue; + switch (questId) { // Horde attacker @@ -377,15 +386,8 @@ class npc_wg_quest_giver : public CreatureScript case QUEST_FUELING_THE_DEMOLISHERS_HORDE_ATT: case QUEST_HEALING_WITH_ROSES_HORDE_ATT: case QUEST_DEFEND_THE_SIEGE_HORDE_ATT: - if (wintergrasp->GetAttackerTeam() == TEAM_HORDE) - { - QuestStatus status = player->GetQuestStatus(questId); - - if (quest->IsAutoComplete() && player->CanTakeQuest(quest, false)) - qm.AddMenuItem(questId, 4); - else if (status == QUEST_STATUS_NONE && player->CanTakeQuest(quest, false)) - qm.AddMenuItem(questId, 2); - } + if (wintergrasp->GetAttackerTeam() != TEAM_HORDE) + continue; break; // Horde defender case QUEST_BONES_AND_ARROWS_HORDE_DEF: @@ -395,15 +397,8 @@ class npc_wg_quest_giver : public CreatureScript case QUEST_HEALING_WITH_ROSES_HORDE_DEF: case QUEST_TOPPLING_THE_TOWERS_HORDE_DEF: case QUEST_STOP_THE_SIEGE_HORDE_DEF: - if (wintergrasp->GetDefenderTeam() == TEAM_HORDE) - { - QuestStatus status = player->GetQuestStatus(questId); - - if (quest->IsAutoComplete() && player->CanTakeQuest(quest, false)) - qm.AddMenuItem(questId, 4); - else if (status == QUEST_STATUS_NONE && player->CanTakeQuest(quest, false)) - qm.AddMenuItem(questId, 2); - } + if (wintergrasp->GetDefenderTeam() != TEAM_HORDE) + continue; break; // Alliance attacker case QUEST_BONES_AND_ARROWS_ALLIANCE_ATT: @@ -411,15 +406,8 @@ class npc_wg_quest_giver : public CreatureScript case QUEST_NO_MERCY_FOR_THE_MERCILESS_ALLIANCE_ATT: case QUEST_DEFEND_THE_SIEGE_ALLIANCE_ATT: case QUEST_A_RARE_HERB_ALLIANCE_ATT: - if (wintergrasp->GetAttackerTeam() == TEAM_ALLIANCE) - { - QuestStatus status = player->GetQuestStatus(questId); - - if (quest->IsAutoComplete() && player->CanTakeQuest(quest, false)) - qm.AddMenuItem(questId, 4); - else if (status == QUEST_STATUS_NONE && player->CanTakeQuest(quest, false)) - qm.AddMenuItem(questId, 2); - } + if (wintergrasp->GetAttackerTeam() != TEAM_ALLIANCE) + continue; break; // Alliance defender case QUEST_BONES_AND_ARROWS_ALLIANCE_DEF: @@ -428,27 +416,20 @@ class npc_wg_quest_giver : public CreatureScript case QUEST_SHOUTHERN_SABOTAGE_ALLIANCE_DEF: case QUEST_STOP_THE_SIEGE_ALLIANCE_DEF: case QUEST_A_RARE_HERB_ALLIANCE_DEF: - if (wintergrasp->GetDefenderTeam() == TEAM_ALLIANCE) - { - QuestStatus status = player->GetQuestStatus(questId); - - if (quest->IsAutoComplete() && player->CanTakeQuest(quest, false)) - qm.AddMenuItem(questId, 4); - else if (status == QUEST_STATUS_NONE && player->CanTakeQuest(quest, false)) - qm.AddMenuItem(questId, 2); - } + if (wintergrasp->GetDefenderTeam() != TEAM_ALLIANCE) + continue; break; default: - QuestStatus status = player->GetQuestStatus(questId); - - if (quest->IsAutoComplete() && player->CanTakeQuest(quest, false)) - qm.AddMenuItem(questId, 4); - else if (status == QUEST_STATUS_NONE && player->CanTakeQuest(quest, false)) - qm.AddMenuItem(questId, 2); break; } + + if (quest->IsAutoComplete()) + qm.AddMenuItem(questId, 4); + else if (player->GetQuestStatus(questId) == QUEST_STATUS_NONE) + qm.AddMenuItem(questId, 2); } } + player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID()); return true; } diff --git a/src/server/scripts/Northrend/zone_zuldrak.cpp b/src/server/scripts/Northrend/zone_zuldrak.cpp index 7281c8a5b1e..63ba44f19e8 100644 --- a/src/server/scripts/Northrend/zone_zuldrak.cpp +++ b/src/server/scripts/Northrend/zone_zuldrak.cpp @@ -198,6 +198,9 @@ enum Gurgthock EMOTE_YGGDRAS_SPAWN = 4, SAY_STINKBEARD_SPAWN = 5, SAY_GURGTHOCK_ELEMENTAL_SPAWN = 6, + SAY_GURGTHOCK_7 = 7, + SAY_QUEST_AMPHITHEATER_ANGUISH_YGGDRAS = 8, + SAY_GURGTHOCK_9 = 9, SAY_CALL_FOR_HELP = 0, SAY_RECRUIT = 0, @@ -319,9 +322,9 @@ public: uiTimer = 2000; uiPhase = 12; break; - } - break; - } + } + break; + } } void UpdateAI(uint32 diff) OVERRIDE @@ -341,8 +344,6 @@ public: if (uiPhase) { - Player* player = me->GetPlayer(*me, _playerGUID); - if (uiTimer <= diff) { switch (uiPhase) @@ -371,27 +372,14 @@ public: uiPhase = 0; break; case 6: - { - if (!player) - return; - - std::string sText = ("The grand Amphitheater of Anguish awaits, " + std::string(player->GetName()) + ". Remember, once a battle starts you have to stay in the area. WIN OR DIE!"); - - me->MonsterSay(sText.c_str(), LANG_UNIVERSAL, 0); - uiTimer = 5000; - uiPhase = 9; - } + Talk(SAY_GURGTHOCK_7, _playerGUID); + uiTimer = 5000; + uiPhase = 9; break; case 7: - { - if (!player) - return; - - std::string sText = ("Prepare to make you stand, " + std::string(player->GetName()) + "! Get in the Amphitheater and stand ready! Remember, you and your opponent must stay in the arena at all times or you will be disqualified!"); - me->MonsterSay(sText.c_str(), LANG_UNIVERSAL, 0); - uiTimer = 3000; - uiPhase = 8; - } + Talk(SAY_GURGTHOCK_9, _playerGUID); + uiTimer = 3000; + uiPhase = 8; break; case 8: Talk(SAY_QUEST_ACCEPT_MAGNATAUR); @@ -399,15 +387,9 @@ public: uiPhase = 11; break; case 9: - { - if (!player) - return; - - std::string sText = ("Here we are once again, ladies and gentlemen. The epic struggle between life and death in the Amphitheater of Anguish! For this round we have " + std::string(player->GetName()) + " versus the hulking jormungar, Yg... Yggd? Yggdoze? Who comes up with these names?! " + std::string(player->GetName()) + " versus big worm!"); - me->MonsterYell(sText.c_str(), LANG_UNIVERSAL, 0); - uiTimer = 10000; - uiPhase = 10; - } + Talk(SAY_QUEST_AMPHITHEATER_ANGUISH_YGGDRAS, _playerGUID); + uiTimer = 10000; + uiPhase = 10; break; case 10: me->SummonCreature(NPC_YGGDRAS, SpawnPosition[1], TEMPSUMMON_CORPSE_DESPAWN, 1000); @@ -420,16 +402,10 @@ public: uiPhase = 0; break; case 12: - { - if (!player) - return; - - std::string sText = ("Prepare to make you stand, " + std::string(player->GetName()) + "! Get in the Amphitheater and stand ready! Remember, you and your opponent must stay in the arena at all times or you will be disqualified!"); - me->MonsterSay(sText.c_str(), LANG_UNIVERSAL, 0); + Talk(SAY_GURGTHOCK_9, _playerGUID); uiTimer = 5000; uiPhase = 13; - } - break; + break; case 13: Talk(SAY_GURGTHOCK_ELEMENTAL_SPAWN); uiTimer = 3000; @@ -443,7 +419,8 @@ public: break; } } - else uiTimer -= diff; + else + uiTimer -= diff; } } @@ -1502,7 +1479,7 @@ public: _events.ScheduleEvent(EVENT_TURN_TO_POT, urand(25000, 41000)); break; case EVENT_EASY_123: - if (Player* player = Unit::GetPlayer(*me, _playerGUID)) + if (Player* player = ObjectAccessor::GetPlayer(*me, _playerGUID)) { Talk(SAY_EASY_123, _playerGUID); DoCast(player, SPELL_RANDOM_INGREDIENT_EASY_AURA); @@ -1510,7 +1487,7 @@ public: } break; case EVENT_MEDIUM_4: - if (Player* player = Unit::GetPlayer(*me, _playerGUID)) + if (Player* player = ObjectAccessor::GetPlayer(*me, _playerGUID)) { Talk(SAY_MEDIUM_4, _playerGUID); DoCast(player, SPELL_RANDOM_INGREDIENT_MEDIUM_AURA); @@ -1518,7 +1495,7 @@ public: } break; case EVENT_MEDIUM_5: - if (Player* player = Unit::GetPlayer(*me, _playerGUID)) + if (Player* player = ObjectAccessor::GetPlayer(*me, _playerGUID)) { Talk(SAY_MEDIUM_5, _playerGUID); DoCast(player, SPELL_RANDOM_INGREDIENT_MEDIUM_AURA); @@ -1526,7 +1503,7 @@ public: } break; case EVENT_HARD_6: - if (Player* player = Unit::GetPlayer(*me, _playerGUID)) + if (Player* player = ObjectAccessor::GetPlayer(*me, _playerGUID)) { Talk(SAY_HARD_6, _playerGUID); DoCast(player, SPELL_RANDOM_INGREDIENT_HARD_AURA); diff --git a/src/server/scripts/OutdoorPvP/OutdoorPvPNA.cpp b/src/server/scripts/OutdoorPvP/OutdoorPvPNA.cpp index 32a819e2e0d..c77d05e1150 100644 --- a/src/server/scripts/OutdoorPvP/OutdoorPvPNA.cpp +++ b/src/server/scripts/OutdoorPvP/OutdoorPvPNA.cpp @@ -215,8 +215,6 @@ bool OutdoorPvPNA::SetupOutdoorPvP() // halaa m_obj = new OPvPCapturePointNA(this); - if (!m_obj) - return false; AddCapturePoint(m_obj); return true; diff --git a/src/server/scripts/Outland/Auchindoun/AuchenaiCrypts/auchenai_crypts.h b/src/server/scripts/Outland/Auchindoun/AuchenaiCrypts/auchenai_crypts.h new file mode 100644 index 00000000000..21e82a1702d --- /dev/null +++ b/src/server/scripts/Outland/Auchindoun/AuchenaiCrypts/auchenai_crypts.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2008-2013 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 AUCHENAI_CRYPTS_H_ +#define AUCHENAI_CRYPTS_H_ + +#define ACScriptName "instance_auchenai_crypts" + +uint32 const EncounterCount = 2; + +enum DataTypes +{ + // Encounter States/Boss GUIDs + DATA_SHIRRAK_THE_DEAD_WATCHER = 0, + DATA_EXARCH_MALADAAR = 1 +}; + +enum CreatureIds +{ +}; + +enum GameObjectIds +{ +}; + +template<class AI> +AI* GetAuchenaiCryptsAI(Creature* creature) +{ + return GetInstanceAI<AI>(creature, ACScriptName); +} + +#endif // AUCHENAI_CRYPTS_H_ diff --git a/src/server/scripts/Outland/Auchindoun/AuchenaiCrypts/instance_auchenai_crypts.cpp b/src/server/scripts/Outland/Auchindoun/AuchenaiCrypts/instance_auchenai_crypts.cpp new file mode 100644 index 00000000000..56279f20e4c --- /dev/null +++ b/src/server/scripts/Outland/Auchindoun/AuchenaiCrypts/instance_auchenai_crypts.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2008-2013 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 "InstanceScript.h" +#include "auchenai_crypts.h" + +class instance_auchenai_crypts : public InstanceMapScript +{ + public: + instance_auchenai_crypts() : InstanceMapScript(ACScriptName, 558) { } + + struct instance_auchenai_crypts_InstanceMapScript : public InstanceScript + { + instance_auchenai_crypts_InstanceMapScript(Map* map) : InstanceScript(map) + { + SetBossNumber(EncounterCount); + } + }; + + InstanceScript* GetInstanceScript(InstanceMap* map) const OVERRIDE + { + return new instance_auchenai_crypts_InstanceMapScript(map); + } +}; + +void AddSC_instance_auchenai_crypts() +{ + new instance_auchenai_crypts(); +} diff --git a/src/server/scripts/Outland/Auchindoun/ManaTombs/instance_mana_tombs.cpp b/src/server/scripts/Outland/Auchindoun/ManaTombs/instance_mana_tombs.cpp new file mode 100644 index 00000000000..77a5841cb39 --- /dev/null +++ b/src/server/scripts/Outland/Auchindoun/ManaTombs/instance_mana_tombs.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2008-2013 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 "InstanceScript.h" +#include "mana_tombs.h" + +class instance_mana_tombs : public InstanceMapScript +{ + public: + instance_mana_tombs() : InstanceMapScript(MTScriptName, 557) { } + + struct instance_mana_tombs_InstanceMapScript : public InstanceScript + { + instance_mana_tombs_InstanceMapScript(Map* map) : InstanceScript(map) + { + SetBossNumber(EncounterCount); + } + }; + + InstanceScript* GetInstanceScript(InstanceMap* map) const OVERRIDE + { + return new instance_mana_tombs_InstanceMapScript(map); + } +}; + +void AddSC_instance_mana_tombs() +{ + new instance_mana_tombs(); +} diff --git a/src/server/scripts/Outland/Auchindoun/ManaTombs/mana_tombs.h b/src/server/scripts/Outland/Auchindoun/ManaTombs/mana_tombs.h new file mode 100644 index 00000000000..9199ef1945b --- /dev/null +++ b/src/server/scripts/Outland/Auchindoun/ManaTombs/mana_tombs.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2008-2013 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 MANA_TOMBS_H_ +#define MANA_TOMBS_H_ + +#define MTScriptName "instance_mana_tombs" + +uint32 const EncounterCount = 4; + +enum DataTypes +{ + // Encounter States/Boss GUIDs + DATA_PANDEMONIUS = 0, + DATA_TAVAROK = 1, + DATA_NEXUSPRINCE_SHAFFAR = 2, + DATA_YOR = 3 +}; + +enum CreatureIds +{ +}; + +enum GameObjectIds +{ +}; + +template<class AI> +AI* GetManaTombsAI(Creature* creature) +{ + return GetInstanceAI<AI>(creature, MTScriptName); +} + +#endif // MANA_TOMBS_H_ diff --git a/src/server/scripts/Outland/Auchindoun/SethekkHalls/boss_anzu.cpp b/src/server/scripts/Outland/Auchindoun/SethekkHalls/boss_anzu.cpp index 05ee3993a15..af8a4390d96 100644 --- a/src/server/scripts/Outland/Auchindoun/SethekkHalls/boss_anzu.cpp +++ b/src/server/scripts/Outland/Auchindoun/SethekkHalls/boss_anzu.cpp @@ -57,113 +57,110 @@ Position const PosSummonBrood[7] = { -69.25543f, 303.0768f, 97.84479f, 5.532694f }, { -87.59662f, 263.5181f, 92.70478f, 1.658063f }, { -73.54323f, 276.6267f, 94.25807f, 2.802979f }, - { -81.70527f, 280.8776f, 44.58830f, 0.526849f }, + { -81.70527f, 280.8776f, 44.58830f, 0.526849f } }; class boss_anzu : public CreatureScript { -public: - boss_anzu() : CreatureScript("boss_anzu") { } + public: + boss_anzu() : CreatureScript("boss_anzu") { } - struct boss_anzuAI : public BossAI - { - boss_anzuAI(Creature* creature) : BossAI(creature, DATA_ANZU) { } - - void Reset() OVERRIDE + struct boss_anzuAI : public BossAI { - summon66 = false; - summon33 = false; - } + boss_anzuAI(Creature* creature) : BossAI(creature, DATA_ANZU) { } - void EnterCombat(Unit* /*who*/) OVERRIDE - { - events.ScheduleEvent(EVENT_PARALYZING_SCREECH, 14000); - events.ScheduleEvent(EVENT_CYCLONE_OF_FEATHERS, 5000); - } + void Reset() OVERRIDE + { + //_Reset(); + events.Reset(); + _under33Percent = false; + _under66Percent = false; + } - void JustDied(Unit* /*killer*/) OVERRIDE - { - if (instance) - instance->SetData(DATA_ANZU, DONE); - } + void EnterCombat(Unit* /*who*/) OVERRIDE + { + _EnterCombat(); + events.ScheduleEvent(EVENT_PARALYZING_SCREECH, 14000); + events.ScheduleEvent(EVENT_CYCLONE_OF_FEATHERS, 5000); + } - void KilledUnit(Unit* /*victim*/) OVERRIDE {} + void JustDied(Unit* /*killer*/) OVERRIDE + { + _JustDied(); + } - void UpdateAI(uint32 diff) OVERRIDE - { - if (!UpdateVictim()) - return; + void DamageTaken(Unit* /*killer*/, uint32 &damage) OVERRIDE + { + if (me->HealthBelowPctDamaged(33, damage) && !_under33Percent) + { + _under33Percent = true; + Talk(SAY_SUMMON_BROOD); + events.ScheduleEvent(EVENT_SUMMON, 3000); + } - events.Update(diff); + if (me->HealthBelowPctDamaged(66, damage) && !_under66Percent) + { + _under66Percent = true; + Talk(SAY_SUMMON_BROOD); + events.ScheduleEvent(EVENT_SUMMON, 3000); + } + } - while (uint32 eventId = events.ExecuteEvent()) + void UpdateAI(uint32 diff) OVERRIDE { - switch (eventId) + if (!UpdateVictim()) + return; + + events.Update(diff); + + while (uint32 eventId = events.ExecuteEvent()) { - case EVENT_PARALYZING_SCREECH: + switch (eventId) + { + case EVENT_PARALYZING_SCREECH: DoCastVictim(SPELL_PARALYZING_SCREECH); - events.ScheduleEvent(EVENT_PARALYZING_SCREECH, 26000); - break; - - case EVENT_CYCLONE_OF_FEATHERS: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) - DoCast(target, SPELL_CYCLONE_OF_FEATHERS); - events.ScheduleEvent(EVENT_CYCLONE_OF_FEATHERS, 21000); - break; - case EVENT_SUMMON: - // TODO: Add pathing for Brood of Anzu - me->SummonCreature(NPC_BROOD_OF_ANZU, PosSummonBrood[0], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 46000); - me->SummonCreature(NPC_BROOD_OF_ANZU, PosSummonBrood[1], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 46000); - me->SummonCreature(NPC_BROOD_OF_ANZU, PosSummonBrood[2], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 46000); - me->SummonCreature(NPC_BROOD_OF_ANZU, PosSummonBrood[3], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 46000); - me->SummonCreature(NPC_BROOD_OF_ANZU, PosSummonBrood[4], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 46000); - me->SummonCreature(NPC_BROOD_OF_ANZU, PosSummonBrood[5], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 46000); - me->SummonCreature(NPC_BROOD_OF_ANZU, PosSummonBrood[6], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 46000); - DoCast(me, SPELL_BANISH_SELF); - events.ScheduleEvent(EVENT_SPELL_BOMB, 12000); - break; - case EVENT_SPELL_BOMB: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) - { - if (target->getPowerType() == POWER_MANA) + events.ScheduleEvent(EVENT_PARALYZING_SCREECH, 26000); + break; + case EVENT_CYCLONE_OF_FEATHERS: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) + DoCast(target, SPELL_CYCLONE_OF_FEATHERS); + events.ScheduleEvent(EVENT_CYCLONE_OF_FEATHERS, 21000); + break; + case EVENT_SUMMON: + // TODO: Add pathing for Brood of Anzu + for (uint8 i = 0; i < 7; i++) + me->SummonCreature(NPC_BROOD_OF_ANZU, PosSummonBrood[i], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 46000); + + DoCast(me, SPELL_BANISH_SELF); + events.ScheduleEvent(EVENT_SPELL_BOMB, 12000); + break; + case EVENT_SPELL_BOMB: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) { - DoCast(target, SPELL_SPELL_BOMB); - Talk(SAY_SPELL_BOMB, target->GetGUID()); + if (target->getPowerType() == POWER_MANA) + { + DoCast(target, SPELL_SPELL_BOMB); + Talk(SAY_SPELL_BOMB, target->GetGUID()); + } } - } - break; - default: - break; + break; + default: + break; + } } - } - if (HealthBelowPct(66) && !summon66) - { - summon66 = true; - Talk(SAY_SUMMON_BROOD); - events.ScheduleEvent(EVENT_SUMMON, 3000); + DoMeleeAttackIfReady(); } - if (HealthBelowPct(33) && !summon33) - { - summon33 = true; - Talk(SAY_SUMMON_BROOD); - events.ScheduleEvent(EVENT_SUMMON, 3000); - } + private: + bool _under33Percent; + bool _under66Percent; + }; - DoMeleeAttackIfReady(); + CreatureAI* GetAI(Creature* creature) const OVERRIDE + { + return GetSethekkHallsAI<boss_anzuAI>(creature); } - - private: - bool summon66; - bool summon33; - - }; - - CreatureAI* GetAI(Creature* creature) const OVERRIDE - { - return new boss_anzuAI(creature); - } }; void AddSC_boss_anzu() diff --git a/src/server/scripts/Outland/Auchindoun/SethekkHalls/boss_darkweaver_syth.cpp b/src/server/scripts/Outland/Auchindoun/SethekkHalls/boss_darkweaver_syth.cpp index 782db325496..be3a109b9f0 100644 --- a/src/server/scripts/Outland/Auchindoun/SethekkHalls/boss_darkweaver_syth.cpp +++ b/src/server/scripts/Outland/Auchindoun/SethekkHalls/boss_darkweaver_syth.cpp @@ -75,6 +75,7 @@ public: void Reset() OVERRIDE { + _Reset(); summon90 = false; summon50 = false; summon10 = false; @@ -82,6 +83,7 @@ public: void EnterCombat(Unit* /*who*/) OVERRIDE { + _EnterCombat(); events.ScheduleEvent(EVENT_FLAME_SHOCK, 2000); events.ScheduleEvent(EVENT_ARCANE_SHOCK, 4000); events.ScheduleEvent(EVENT_FROST_SHOCK, 6000); @@ -93,18 +95,14 @@ public: void JustDied(Unit* /*killer*/) OVERRIDE { + _JustDied(); Talk(SAY_DEATH); - - if (instance) - instance->SetData(DATA_DARKWEAVER_SYTH, DONE); } - void KilledUnit(Unit* /*victim*/) OVERRIDE + void KilledUnit(Unit* who) OVERRIDE { - if (rand()%2) - return; - - Talk(SAY_SLAY); + if (who->GetTypeId() == TYPEID_PLAYER) + Talk(SAY_SLAY); } void JustSummoned(Creature* summoned) OVERRIDE @@ -196,7 +194,7 @@ public: CreatureAI* GetAI(Creature* creature) const OVERRIDE { - return new boss_darkweaver_sythAI(creature); + return GetSethekkHallsAI<boss_darkweaver_sythAI>(creature); } }; diff --git a/src/server/scripts/Outland/Auchindoun/SethekkHalls/boss_tailonking_ikiss.cpp b/src/server/scripts/Outland/Auchindoun/SethekkHalls/boss_tailonking_ikiss.cpp index 9d3aa623011..022ac3e9e4d 100644 --- a/src/server/scripts/Outland/Auchindoun/SethekkHalls/boss_tailonking_ikiss.cpp +++ b/src/server/scripts/Outland/Auchindoun/SethekkHalls/boss_tailonking_ikiss.cpp @@ -62,6 +62,7 @@ public: void Reset() OVERRIDE { + _Reset(); ArcaneVolley_Timer = 5000; Sheep_Timer = 8000; Blink_Timer = 35000; @@ -72,7 +73,6 @@ public: } void MoveInLineOfSight(Unit* who) OVERRIDE - { if (!me->GetVictim() && me->CanCreatureAttack(who)) { @@ -96,20 +96,20 @@ public: void EnterCombat(Unit* /*who*/) OVERRIDE { + _EnterCombat(); Talk(SAY_AGGRO); } void JustDied(Unit* /*killer*/) OVERRIDE { + _JustDied(); Talk(SAY_DEATH); - - if (instance) - instance->SetData(DATA_TALON_KING_IKISS, DONE); } - void KilledUnit(Unit* /*victim*/) OVERRIDE + void KilledUnit(Unit* who) OVERRIDE { - Talk(SAY_SLAY); + if (who->GetTypeId() == TYPEID_PLAYER) + Talk(SAY_SLAY); } void UpdateAI(uint32 diff) OVERRIDE @@ -202,7 +202,7 @@ public: CreatureAI* GetAI(Creature* creature) const OVERRIDE { - return new boss_talon_king_ikissAI(creature); + return GetSethekkHallsAI<boss_talon_king_ikissAI>(creature); } }; diff --git a/src/server/scripts/Outland/Auchindoun/SethekkHalls/instance_sethekk_halls.cpp b/src/server/scripts/Outland/Auchindoun/SethekkHalls/instance_sethekk_halls.cpp index f380914506e..08cefb83c96 100644 --- a/src/server/scripts/Outland/Auchindoun/SethekkHalls/instance_sethekk_halls.cpp +++ b/src/server/scripts/Outland/Auchindoun/SethekkHalls/instance_sethekk_halls.cpp @@ -1,6 +1,5 @@ /* * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/> * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -16,125 +15,100 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -/* ScriptData -SDName: Instance - Sethekk Halls -SD%Complete: 50 -SDComment: Instance Data for Sethekk Halls instance -SDCategory: Auchindoun, Sethekk Halls -EndScriptData */ - #include "ScriptMgr.h" #include "InstanceScript.h" #include "sethekk_halls.h" -class instance_sethekk_halls : public InstanceMapScript +DoorData const doorData[] = { -public: - instance_sethekk_halls() : InstanceMapScript("instance_sethekk_halls", 556) { } - - InstanceScript* GetInstanceScript(InstanceMap* map) const OVERRIDE - { - return new instance_sethekk_halls_InstanceMapScript(map); - } - - struct instance_sethekk_halls_InstanceMapScript : public InstanceScript - { - instance_sethekk_halls_InstanceMapScript(Map* map) : InstanceScript(map) - { - SetBossNumber(EncounterCount); - } + { GO_IKISS_DOOR, DATA_TALON_KING_IKISS, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, + { 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE } // END +}; - void Initialize() OVERRIDE - { - SetBossState(DATA_ANZU, NOT_STARTED); - iIkissDoorGUID = 0; - } +class instance_sethekk_halls : public InstanceMapScript +{ + public: + instance_sethekk_halls() : InstanceMapScript(SHScriptName, 556) { } - void OnCreatureCreate(Creature* creature) OVERRIDE + struct instance_sethekk_halls_InstanceMapScript : public InstanceScript { - if (creature->GetEntry() == NPC_ANZU) + instance_sethekk_halls_InstanceMapScript(Map* map) : InstanceScript(map) { - if (GetBossState(DATA_ANZU) == DONE) - creature->DisappearAndDie(); - else - SetBossState(DATA_ANZU, IN_PROGRESS); + SetBossNumber(EncounterCount); + LoadDoorData(doorData); } - } - void OnGameObjectCreate(GameObject* go) OVERRIDE - { - if (go->GetEntry() == GO_IKISS_DOOR) - iIkissDoorGUID = go->GetGUID(); - } - - bool SetBossState(uint32 type, EncounterState state) OVERRIDE - { - if (!InstanceScript::SetBossState(type, state)) - return false; + void OnCreatureCreate(Creature* creature) OVERRIDE + { + if (creature->GetEntry() == NPC_ANZU) + { + if (GetBossState(DATA_ANZU) == DONE) + creature->DisappearAndDie(); + else + SetBossState(DATA_ANZU, IN_PROGRESS); + } + } - switch (type) + void OnGameObjectCreate(GameObject* go) OVERRIDE { - case DATA_DARKWEAVER_SYTH: - break; - case DATA_TALON_KING_IKISS: - if (state == DONE) - DoUseDoorOrButton(iIkissDoorGUID, DAY*IN_MILLISECONDS); - break; - case DATA_ANZU: - break; - default: - break; + if (go->GetEntry() == GO_IKISS_DOOR) + AddDoor(go, true); } - return true; - } + void OnGameObjectRemove(GameObject* go) OVERRIDE + { + if (go->GetEntry() == GO_IKISS_DOOR) + AddDoor(go, false); + } - std::string GetSaveData() OVERRIDE - { - OUT_SAVE_INST_DATA; + std::string GetSaveData() OVERRIDE + { + OUT_SAVE_INST_DATA; - std::ostringstream saveStream; - saveStream << "S H " << GetBossSaveData(); + std::ostringstream saveStream; + saveStream << "S H " << GetBossSaveData(); - OUT_SAVE_INST_DATA_COMPLETE; - return saveStream.str(); - } + OUT_SAVE_INST_DATA_COMPLETE; + return saveStream.str(); + } - void Load(const char* str) OVERRIDE - { - if (!str) + void Load(char const* str) OVERRIDE { - OUT_LOAD_INST_DATA_FAIL; - return; - } + if (!str) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } - OUT_LOAD_INST_DATA(str); + OUT_LOAD_INST_DATA(str); - char dataHead1, dataHead2; + char dataHead1, dataHead2; - std::istringstream loadStream(str); - loadStream >> dataHead1 >> dataHead2; + std::istringstream loadStream(str); + loadStream >> dataHead1 >> dataHead2; - if (dataHead1 == 'S' && dataHead2 == 'H') - { - for (uint32 i = 0; i < EncounterCount; ++i) + if (dataHead1 == 'S' && dataHead2 == 'H') { - uint32 tmpState; - loadStream >> tmpState; - if (tmpState == IN_PROGRESS || tmpState > SPECIAL) - tmpState = NOT_STARTED; - SetBossState(i, EncounterState(tmpState)); + for (uint32 i = 0; i < EncounterCount; ++i) + { + uint32 tmpState; + loadStream >> tmpState; + if (tmpState == IN_PROGRESS || tmpState > SPECIAL) + tmpState = NOT_STARTED; + SetBossState(i, EncounterState(tmpState)); + } } + else + OUT_LOAD_INST_DATA_FAIL; + + OUT_LOAD_INST_DATA_COMPLETE; } - else - OUT_LOAD_INST_DATA_FAIL; + }; - OUT_LOAD_INST_DATA_COMPLETE; + InstanceScript* GetInstanceScript(InstanceMap* map) const OVERRIDE + { + return new instance_sethekk_halls_InstanceMapScript(map); } - - protected: - uint64 iIkissDoorGUID; - }; }; void AddSC_instance_sethekk_halls() diff --git a/src/server/scripts/Outland/Auchindoun/SethekkHalls/sethekk_halls.h b/src/server/scripts/Outland/Auchindoun/SethekkHalls/sethekk_halls.h index 86789e9982f..58b8d4d157c 100644 --- a/src/server/scripts/Outland/Auchindoun/SethekkHalls/sethekk_halls.h +++ b/src/server/scripts/Outland/Auchindoun/SethekkHalls/sethekk_halls.h @@ -15,13 +15,16 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef DEF_SETHEKK_HALLS_H -#define DEF_SETHEKK_HALLS_H +#ifndef SETHEKK_HALLS_H_ +#define SETHEKK_HALLS_H_ + +#define SHScriptName "instance_sethekk_halls" uint32 const EncounterCount = 3; enum DataTypes { + // Encounter States/Boss GUIDs DATA_DARKWEAVER_SYTH = 0, DATA_TALON_KING_IKISS = 1, DATA_ANZU = 2 @@ -38,4 +41,10 @@ enum GameObjectIds GO_IKISS_DOOR = 177203 }; -#endif +template<class AI> +AI* GetSethekkHallsAI(Creature* creature) +{ + return GetInstanceAI<AI>(creature, SHScriptName); +} + +#endif // SETHEKK_HALLS_H_ diff --git a/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_ambassador_hellmaw.cpp b/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_ambassador_hellmaw.cpp index ffadfccecfe..1fa589af3a1 100644 --- a/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_ambassador_hellmaw.cpp +++ b/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_ambassador_hellmaw.cpp @@ -45,165 +45,146 @@ enum Spells SPELL_ENRAGE = 34970 }; -class boss_ambassador_hellmaw : public CreatureScript +enum Events { -public: - boss_ambassador_hellmaw() : CreatureScript("boss_ambassador_hellmaw") { } - - CreatureAI* GetAI(Creature* creature) const OVERRIDE - { - return new boss_ambassador_hellmawAI(creature); - } - - struct boss_ambassador_hellmawAI : public npc_escortAI - { - boss_ambassador_hellmawAI(Creature* creature) : npc_escortAI(creature) - { - instance = creature->GetInstanceScript(); - } - - InstanceScript* instance; + EVENT_CORROSIVE_ACID = 1, + EVENT_FEAR, + EVENT_BERSERK +}; - uint32 EventCheck_Timer; - uint32 CorrosiveAcid_Timer; - uint32 Fear_Timer; - uint32 Enrage_Timer; - bool Intro; - bool IsBanished; - bool Enraged; +class boss_ambassador_hellmaw : public CreatureScript +{ + public: + boss_ambassador_hellmaw() : CreatureScript("boss_ambassador_hellmaw") { } - void Reset() OVERRIDE + struct boss_ambassador_hellmawAI : public npc_escortAI { - EventCheck_Timer = 5000; - CorrosiveAcid_Timer = urand(5000, 10000); - Fear_Timer = urand(25000, 30000); - Enrage_Timer = 180000; - Intro = false; - IsBanished = true; - Enraged = false; - - if (instance && me->IsAlive()) + boss_ambassador_hellmawAI(Creature* creature) : npc_escortAI(creature) { - if (instance->GetData(TYPE_OVERSEER) != DONE) - DoCast(me, SPELL_BANISH, true); + _instance = creature->GetInstanceScript(); + _intro = false; } - } - void JustReachedHome() OVERRIDE - { - if (instance) - instance->SetData(TYPE_HELLMAW, FAIL); - } + void Reset() OVERRIDE + { + if (!me->IsAlive()) + return; - void MoveInLineOfSight(Unit* who) OVERRIDE + _events.Reset(); + _instance->SetBossState(DATA_AMBASSADOR_HELLMAW, NOT_STARTED); - { - if (me->HasAura(SPELL_BANISH)) - return; + _events.ScheduleEvent(EVENT_CORROSIVE_ACID, urand(5000, 10000)); + _events.ScheduleEvent(EVENT_FEAR, urand(25000, 30000)); + if (IsHeroic()) + _events.ScheduleEvent(EVENT_BERSERK, 180000); - npc_escortAI::MoveInLineOfSight(who); - } + DoAction(ACTION_AMBASSADOR_HELLMAW_BANISH); + } - void WaypointReached(uint32 /*waypointId*/) OVERRIDE - { - } + void MoveInLineOfSight(Unit* who) OVERRIDE + { + if (me->HasAura(SPELL_BANISH)) + return; - void DoIntro() - { - if (me->HasAura(SPELL_BANISH)) - me->RemoveAurasDueToSpell(SPELL_BANISH); + npc_escortAI::MoveInLineOfSight(who); + } - IsBanished = false; - Intro = true; + void WaypointReached(uint32 /*waypointId*/) OVERRIDE + { + } - if (instance) + void DoAction(int32 actionId) { - if (instance->GetData(TYPE_HELLMAW) != FAIL) + if (actionId == ACTION_AMBASSADOR_HELLMAW_INTRO) + DoIntro(); + else if (actionId == ACTION_AMBASSADOR_HELLMAW_BANISH) { - Talk(SAY_INTRO); - Start(true, false, 0, NULL, false, true); + if (_instance->GetData(DATA_FEL_OVERSEER) && me->HasAura(SPELL_BANISH)) + DoCast(me, SPELL_BANISH, true); // this will not work, because he is immune to banish } - - instance->SetData(TYPE_HELLMAW, IN_PROGRESS); } - } - void EnterCombat(Unit* /*who*/) OVERRIDE - { - Talk(SAY_AGGRO); - } + void DoIntro() + { + if (_intro) + return; - void KilledUnit(Unit* /*victim*/) OVERRIDE - { - Talk(SAY_SLAY); - } + _intro = true; - void JustDied(Unit* /*killer*/) OVERRIDE - { - Talk(SAY_DEATH); + if (me->HasAura(SPELL_BANISH)) + me->RemoveAurasDueToSpell(SPELL_BANISH); - if (instance) - instance->SetData(TYPE_HELLMAW, DONE); - } + Talk(SAY_INTRO); + Start(true, false, 0, NULL, false, true); + } - void UpdateAI(uint32 diff) OVERRIDE - { - if (!Intro && !HasEscortState(STATE_ESCORT_ESCORTING)) + void EnterCombat(Unit* /*who*/) OVERRIDE { - if (EventCheck_Timer <= diff) - { - if (instance) - { - if (instance->GetData(TYPE_OVERSEER) == DONE) - { - DoIntro(); - return; - } - } - EventCheck_Timer = 5000; - return; - } - else - { - EventCheck_Timer -= diff; - return; - } + _instance->SetBossState(DATA_AMBASSADOR_HELLMAW, IN_PROGRESS); + Talk(SAY_AGGRO); } - npc_escortAI::UpdateAI(diff); - - if (!UpdateVictim()) - return; - - if (me->HasAura(SPELL_BANISH, 0)) + void KilledUnit(Unit* who) OVERRIDE { - EnterEvadeMode(); - return; + if (who->GetTypeId() == TYPEID_PLAYER) + Talk(SAY_SLAY); } - if (CorrosiveAcid_Timer <= diff) + void JustDied(Unit* /*killer*/) OVERRIDE { - DoCastVictim(SPELL_CORROSIVE_ACID); - CorrosiveAcid_Timer = urand(15000, 25000); - } else CorrosiveAcid_Timer -= diff; + _instance->SetBossState(DATA_AMBASSADOR_HELLMAW, DONE); + Talk(SAY_DEATH); + } - if (Fear_Timer <= diff) + void UpdateEscortAI(uint32 const diff) OVERRIDE { - DoCast(me, SPELL_FEAR); - Fear_Timer = urand(20000, 35000); - } else Fear_Timer -= diff; + if (!UpdateVictim()) + return; - if (IsHeroic()) - { - if (!Enraged && Enrage_Timer <= diff) + if (me->HasAura(SPELL_BANISH)) + { + EnterEvadeMode(); + return; + } + + _events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + while (uint32 eventId = _events.ExecuteEvent()) { - DoCast(me, SPELL_ENRAGE); - Enraged = true; - } else Enrage_Timer -= diff; + switch (eventId) + { + case EVENT_CORROSIVE_ACID: + DoCastVictim(SPELL_CORROSIVE_ACID); + _events.ScheduleEvent(EVENT_CORROSIVE_ACID, urand(15000, 25000)); + break; + case EVENT_FEAR: + DoCastAOE(SPELL_FEAR); + _events.ScheduleEvent(EVENT_FEAR, urand(20000, 35000)); + break; + case EVENT_BERSERK: + DoCast(me, SPELL_ENRAGE, true); + break; + default: + break; + } + } + + DoMeleeAttackIfReady(); } - } - }; + private: + InstanceScript* _instance; + EventMap _events; + bool _intro; + }; + + CreatureAI* GetAI(Creature* creature) const OVERRIDE + { + return GetShadowLabyrinthAI<boss_ambassador_hellmawAI>(creature); + } }; void AddSC_boss_ambassador_hellmaw() diff --git a/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_blackheart_the_inciter.cpp b/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_blackheart_the_inciter.cpp index 573acfce5c2..ec3465a0bfc 100644 --- a/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_blackheart_the_inciter.cpp +++ b/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_blackheart_the_inciter.cpp @@ -50,112 +50,97 @@ enum BlackheartTheInciter enum Events { - EVENT_INCITE_CHAOS_WAIT = 1, - EVENT_INCITE_CHAOS = 2, - EVENT_CHARGE_ATTACK = 3, - EVENT_WAR_STOMP = 4 + EVENT_INCITE_CHAOS = 1, + EVENT_CHARGE_ATTACK = 2, + EVENT_WAR_STOMP = 3 }; class boss_blackheart_the_inciter : public CreatureScript { -public: - boss_blackheart_the_inciter() : CreatureScript("boss_blackheart_the_inciter") { } + public: + boss_blackheart_the_inciter() : CreatureScript("boss_blackheart_the_inciter") { } - struct boss_blackheart_the_inciterAI : public BossAI - { - boss_blackheart_the_inciterAI(Creature* creature) : BossAI(creature, DATA_BLACKHEARTTHEINCITEREVENT) { } - - void Reset() OVERRIDE + struct boss_blackheart_the_inciterAI : public BossAI { - InciteChaos = false; - - if (instance) - instance->SetData(DATA_BLACKHEARTTHEINCITEREVENT, NOT_STARTED); - } + boss_blackheart_the_inciterAI(Creature* creature) : BossAI(creature, DATA_BLACKHEART_THE_INCITER) { } - void KilledUnit(Unit* /*victim*/) OVERRIDE - { - Talk(SAY_SLAY); - } - - void JustDied(Unit* /*killer*/) OVERRIDE - { - Talk(SAY_DEATH); + void Reset() OVERRIDE + { + _Reset(); + } - if (instance) - instance->SetData(DATA_BLACKHEARTTHEINCITEREVENT, DONE); - } + void EnterCombat(Unit* /*who*/) OVERRIDE + { + _EnterCombat(); + events.ScheduleEvent(EVENT_INCITE_CHAOS, 20000); + events.ScheduleEvent(EVENT_CHARGE_ATTACK, 5000); + events.ScheduleEvent(EVENT_WAR_STOMP, 15000); - void EnterCombat(Unit* /*who*/) OVERRIDE - { - events.ScheduleEvent(EVENT_INCITE_CHAOS_WAIT, 15000); - events.ScheduleEvent(EVENT_INCITE_CHAOS, 20000); - events.ScheduleEvent(EVENT_CHARGE_ATTACK, 5000); - events.ScheduleEvent(EVENT_WAR_STOMP, 15000); + Talk(SAY_AGGRO); + } - Talk(SAY_AGGRO); + void KilledUnit(Unit* who) OVERRIDE + { + if (who->GetTypeId() == TYPEID_PLAYER) + Talk(SAY_SLAY); + } - if (instance) - instance->SetData(DATA_BLACKHEARTTHEINCITEREVENT, IN_PROGRESS); - } + void JustDied(Unit* /*killer*/) OVERRIDE + { + _JustDied(); + Talk(SAY_DEATH); + } - void UpdateAI(uint32 diff) OVERRIDE - { - if (!UpdateVictim()) - return; + void UpdateAI(uint32 diff) OVERRIDE + { + if (!UpdateVictim()) + return; - events.Update(diff); + events.Update(diff); - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; - while (uint32 eventId = events.ExecuteEvent()) - { - switch (eventId) + while (uint32 eventId = events.ExecuteEvent()) { - case EVENT_INCITE_CHAOS_WAIT: - InciteChaos = false; - events.ScheduleEvent(EVENT_INCITE_CHAOS_WAIT, 15000); - break; - case EVENT_INCITE_CHAOS: + switch (eventId) { - DoCast(me, SPELL_INCITE_CHAOS); - - std::list<HostileReference*> t_list = me->getThreatManager().getThreatList(); - for (std::list<HostileReference*>::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) + case EVENT_INCITE_CHAOS: { - Unit* target = Unit::GetUnit(*me, (*itr)->getUnitGuid()); - if (target && target->GetTypeId() == TYPEID_PLAYER) - me->CastSpell(target, SPELL_INCITE_CHAOS_B, true); + DoCast(me, SPELL_INCITE_CHAOS); + + std::list<HostileReference*> t_list = me->getThreatManager().getThreatList(); + for (std::list<HostileReference*>::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) + { + if (Unit* target = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid())) + if (target->GetTypeId() == TYPEID_PLAYER) + me->CastSpell(target, SPELL_INCITE_CHAOS_B, true); + } + + DoResetThreat(); + events.ScheduleEvent(EVENT_INCITE_CHAOS, 40000); + break; } - - DoResetThreat(); - InciteChaos = true; - events.ScheduleEvent(EVENT_INCITE_CHAOS, 40000); - break; + case EVENT_CHARGE_ATTACK: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) + DoCast(target, SPELL_CHARGE); + events.ScheduleEvent(EVENT_CHARGE, urand(15000, 25000)); + break; + case EVENT_WAR_STOMP: + DoCast(me, SPELL_WAR_STOMP); + events.ScheduleEvent(EVENT_WAR_STOMP, urand(18000, 24000)); + break; } - case EVENT_CHARGE_ATTACK: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) - DoCast(target, SPELL_CHARGE); - events.ScheduleEvent(EVENT_CHARGE, urand(15000, 25000)); - break; - case EVENT_WAR_STOMP: - DoCast(me, SPELL_WAR_STOMP); - events.ScheduleEvent(EVENT_WAR_STOMP, urand(18000, 24000)); - break; } - } - DoMeleeAttackIfReady(); - } - private: - bool InciteChaos; - }; + DoMeleeAttackIfReady(); + } + }; - CreatureAI* GetAI(Creature* creature) const OVERRIDE - { - return new boss_blackheart_the_inciterAI(creature); - } + CreatureAI* GetAI(Creature* creature) const OVERRIDE + { + return GetShadowLabyrinthAI<boss_blackheart_the_inciterAI>(creature); + } }; void AddSC_boss_blackheart_the_inciter() diff --git a/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_grandmaster_vorpil.cpp b/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_grandmaster_vorpil.cpp index 088913b13d2..44ef5e8e42c 100644 --- a/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_grandmaster_vorpil.cpp +++ b/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_grandmaster_vorpil.cpp @@ -43,16 +43,23 @@ enum GrandmasterVorpil SPELL_BANISH = 38791, NPC_VOID_TRAVELER = 19226, + SPELL_SUMMON_VOID_TRAVELER_A = 33582, + SPELL_SUMMON_VOID_TRAVELER_B = 33583, + SPELL_SUMMON_VOID_TRAVELER_C = 33584, + SPELL_SUMMON_VOID_TRAVELER_D = 33585, + SPELL_SUMMON_VOID_TRAVELER_E = 33586, + SPELL_SACRIFICE = 33587, SPELL_SHADOW_NOVA = 33846, SPELL_EMPOWERING_SHADOWS = 33783, H_SPELL_EMPOWERING_SHADOWS = 39364, NPC_VOID_PORTAL = 19224, + SPELL_SUMMON_PORTAL = 33566, SPELL_VOID_PORTAL_VISUAL = 33569 }; -float VorpilPosition[3] = {-252.8820f, -264.3030f, 17.1f}; +Position const VorpilPosition = { -252.8820f, -264.3030f, 17.1f, 0.0f }; float VoidPortalCoords[5][3] = { @@ -71,254 +78,202 @@ enum Events EVENT_SUMMON_TRAVELER = 4 }; -class npc_voidtraveler : public CreatureScript +class boss_grandmaster_vorpil : public CreatureScript { -public: - npc_voidtraveler() : CreatureScript("npc_voidtraveler") { } + public: + boss_grandmaster_vorpil() : CreatureScript("boss_grandmaster_vorpil") { } - struct npc_voidtravelerAI : public ScriptedAI - { - npc_voidtravelerAI(Creature* creature) : ScriptedAI(creature) {} - - uint64 VorpilGUID; - uint32 move; - bool sacrificed; - - void Reset() OVERRIDE + struct boss_grandmaster_vorpilAI : public BossAI { - VorpilGUID = 0; - move = 0; - sacrificed = false; - } - - void EnterCombat(Unit* /*who*/)OVERRIDE {} + boss_grandmaster_vorpilAI(Creature* creature) : BossAI(creature, DATA_GRANDMASTER_VORPIL) + { + _intro = false; + } - void UpdateAI(uint32 diff) OVERRIDE - { - if (!VorpilGUID) + void Reset() OVERRIDE { - me->Kill(me); - return; + _Reset(); + _helpYell = false; } - if (move <= diff) + + void SummonPortals() { - Creature* Vorpil = Unit::GetCreature(*me, VorpilGUID); - if (!Vorpil) - { - VorpilGUID = 0; - return; - } + for (uint8 i = 0; i < 5; ++i) + if (Creature* portal = me->SummonCreature(NPC_VOID_PORTAL, VoidPortalCoords[i][0], VoidPortalCoords[i][1], VoidPortalCoords[i][2], 0, TEMPSUMMON_CORPSE_DESPAWN, 3000000)) + portal->CastSpell(portal, SPELL_VOID_PORTAL_VISUAL, true); - if (sacrificed) - { - me->AddAura(DUNGEON_MODE(SPELL_EMPOWERING_SHADOWS, H_SPELL_EMPOWERING_SHADOWS), Vorpil); - Vorpil->ModifyHealth(int32(Vorpil->CountPctFromMaxHealth(4))); - DoCast(me, SPELL_SHADOW_NOVA, true); - me->Kill(me); - return; - } - me->GetMotionMaster()->MoveFollow(Vorpil, 0, 0); - if (me->IsWithinDist(Vorpil, 3)) - { - DoCast(me, SPELL_SACRIFICE, false); - sacrificed = true; - move = 500; - return; - } - if (!Vorpil->IsInCombat() || Vorpil->isDead()) + events.ScheduleEvent(EVENT_SUMMON_TRAVELER, 5000); + } + + void spawnVoidTraveler() + { + uint8 pos = urand(0, 4); + me->SummonCreature(NPC_VOID_TRAVELER, VoidPortalCoords[pos][0], VoidPortalCoords[pos][1], VoidPortalCoords[pos][2], 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 5000); + if (!_helpYell) { - me->Kill(me); - return; + Talk(SAY_HELP); + _helpYell = true; } - move = 1000; - } else move -= diff; - } - }; - - CreatureAI* GetAI(Creature* creature) const OVERRIDE - { - return new npc_voidtravelerAI(creature); - } -}; - -class boss_grandmaster_vorpil : public CreatureScript -{ -public: - boss_grandmaster_vorpil() : CreatureScript("boss_grandmaster_vorpil") { } - - struct boss_grandmaster_vorpilAI : public BossAI - { - boss_grandmaster_vorpilAI(Creature* creature) : BossAI(creature, DATA_GRANDMASTERVORPIL) - { - Intro = false; - } + } - void Reset() OVERRIDE - { - HelpYell = false; - sumportals = false; - destroyPortals(); + void KilledUnit(Unit* who) OVERRIDE + { + if (who->GetTypeId() == TYPEID_PLAYER) + Talk(SAY_SLAY); + } - if (instance) - instance->SetData(DATA_GRANDMASTERVORPILEVENT, NOT_STARTED); - } + void JustDied(Unit* /*killer*/) OVERRIDE + { + _JustDied(); + Talk(SAY_DEATH); + } - void summonPortals() - { - if (!sumportals) + void EnterCombat(Unit* /*who*/) OVERRIDE { - for (uint8 i = 0; i < 5; ++i) - { - Creature* Portal = NULL; - Portal = me->SummonCreature(NPC_VOID_PORTAL, VoidPortalCoords[i][0], VoidPortalCoords[i][1], VoidPortalCoords[i][2], 0, TEMPSUMMON_CORPSE_DESPAWN, 3000000); - if (Portal) - { - PortalsGuid[i] = Portal->GetGUID(); - Portal->CastSpell(Portal, SPELL_VOID_PORTAL_VISUAL, false); - } - } - sumportals = true; - events.ScheduleEvent(EVENT_SUMMON_TRAVELER, 5000); + _EnterCombat(); + events.ScheduleEvent(EVENT_SHADOWBOLT_VOLLEY, urand(7000, 14000)); + if (IsHeroic()) + events.ScheduleEvent(EVENT_BANISH, 17000); + events.ScheduleEvent(EVENT_DRAW_SHADOWS, 45000); + events.ScheduleEvent(EVENT_SUMMON_TRAVELER, 90000); + + Talk(SAY_AGGRO); + SummonPortals(); } - } - void destroyPortals() - { - if (sumportals) + void MoveInLineOfSight(Unit* who) OVERRIDE { - for (uint8 i = 0; i < 5; ++i) + BossAI::MoveInLineOfSight(who); + + if (!_intro && me->IsWithinLOSInMap(who) && me->IsWithinDistInMap(who, 100) && me->IsValidAttackTarget(who)) { - Unit* Portal = Unit::GetUnit(*me, PortalsGuid[i]); - if (Portal && Portal->IsAlive()) - Portal->DealDamage(Portal, Portal->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - PortalsGuid[i] = 0; + Talk(SAY_INTRO); + _intro = true; } - sumportals = false; } - } - void spawnVoidTraveler() - { - int pos = urand(0, 4); - me->SummonCreature(NPC_VOID_TRAVELER, VoidPortalCoords[pos][0], VoidPortalCoords[pos][1], VoidPortalCoords[pos][2], 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 5000); - if (!HelpYell) + void UpdateAI(uint32 diff) OVERRIDE { - Talk(SAY_HELP); - HelpYell = true; - } - } + if (!UpdateVictim()) + return; - void JustSummoned(Creature* summoned) OVERRIDE - { - if (summoned && summoned->GetEntry() == NPC_VOID_TRAVELER) - CAST_AI(npc_voidtraveler::npc_voidtravelerAI, summoned->AI())->VorpilGUID = me->GetGUID(); - } + events.Update(diff); - void KilledUnit(Unit* /*victim*/) OVERRIDE - { - Talk(SAY_SLAY); - } + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; - void JustDied(Unit* /*killer*/) OVERRIDE - { - Talk(SAY_DEATH); - destroyPortals(); + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_SHADOWBOLT_VOLLEY: + DoCast(me, SPELL_SHADOWBOLT_VOLLEY); + events.ScheduleEvent(EVENT_SHADOWBOLT_VOLLEY, urand(15000, 30000)); + break; + case EVENT_BANISH: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 30.0f, false)) + DoCast(target, SPELL_BANISH); + events.ScheduleEvent(EVENT_BANISH, 16000); + break; + case EVENT_DRAW_SHADOWS: + { + Map* map = me->GetMap(); + 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() && !i_pl->HasAura(SPELL_BANISH)) + i_pl->TeleportTo(me->GetMapId(), VorpilPosition.GetPositionX(), VorpilPosition.GetPositionY(), VorpilPosition.GetPositionZ(), VorpilPosition.GetOrientation(), TELE_TO_NOT_LEAVE_COMBAT); + + me->SetPosition(VorpilPosition); + DoCast(me, SPELL_DRAW_SHADOWS, true); + DoCast(me, SPELL_RAIN_OF_FIRE); + events.ScheduleEvent(EVENT_SHADOWBOLT_VOLLEY, 6000); + events.ScheduleEvent(EVENT_DRAW_SHADOWS, 30000); + break; + } + case EVENT_SUMMON_TRAVELER: + spawnVoidTraveler(); + events.ScheduleEvent(EVENT_SUMMON_TRAVELER, 10000); + // enrage at 20% + if (HealthBelowPct(20)) + events.ScheduleEvent(EVENT_SUMMON_TRAVELER, 5000); + break; + } + } - if (instance) - instance->SetData(DATA_GRANDMASTERVORPILEVENT, DONE); - } + DoMeleeAttackIfReady(); + } + + private: + bool _intro; + bool _helpYell; + }; - void EnterCombat(Unit* /*who*/) OVERRIDE + CreatureAI* GetAI(Creature* creature) const OVERRIDE { - events.ScheduleEvent(EVENT_SHADOWBOLT_VOLLEY, urand(7000, 14000)); - if (IsHeroic()) - events.ScheduleEvent(EVENT_BANISH, 17000); - events.ScheduleEvent(EVENT_DRAW_SHADOWS, 45000); - events.ScheduleEvent(EVENT_SUMMON_TRAVELER, 90000); - - Talk(SAY_AGGRO); - summonPortals(); - - if (instance) - instance->SetData(DATA_GRANDMASTERVORPILEVENT, IN_PROGRESS); - _EnterCombat(); + return GetShadowLabyrinthAI<boss_grandmaster_vorpilAI>(creature); } +}; - void MoveInLineOfSight(Unit* who) OVERRIDE +class npc_voidtraveler : public CreatureScript +{ + public: + npc_voidtraveler() : CreatureScript("npc_voidtraveler") { } + struct npc_voidtravelerAI : public ScriptedAI { - ScriptedAI::MoveInLineOfSight(who); - - if (!Intro && me->IsWithinLOSInMap(who)&& me->IsWithinDistInMap(who, 100) && me->IsValidAttackTarget(who)) + npc_voidtravelerAI(Creature* creature) : ScriptedAI(creature) { - Talk(SAY_INTRO); - Intro = true; + _instance = creature->GetInstanceScript(); } - } - - void UpdateAI(uint32 diff) OVERRIDE - { - if (!UpdateVictim()) - return; - events.Update(diff); + void Reset() OVERRIDE + { + _moveTimer = 0; + _sacrificed = false; + } - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; + void EnterCombat(Unit* /*who*/) OVERRIDE { } - while (uint32 eventId = events.ExecuteEvent()) + void UpdateAI(uint32 diff) OVERRIDE { - switch (eventId) + if (_moveTimer <= diff) { - case EVENT_SHADOWBOLT_VOLLEY: - DoCast(me, SPELL_SHADOWBOLT_VOLLEY); - events.ScheduleEvent(EVENT_SHADOWBOLT_VOLLEY, urand(15000, 30000)); - break; - case EVENT_BANISH: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 30, false)) - DoCast(target, SPELL_BANISH); - events.ScheduleEvent(EVENT_BANISH, 16000); - break; - case EVENT_DRAW_SHADOWS: - { - Map* map = me->GetMap(); - 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() && !i_pl->HasAura(SPELL_BANISH)) - i_pl->TeleportTo(me->GetMapId(), VorpilPosition[0], VorpilPosition[1], VorpilPosition[2], 0, TELE_TO_NOT_LEAVE_COMBAT); - - me->SetPosition(VorpilPosition[0], VorpilPosition[1], VorpilPosition[2], 0.0f); - DoCast(me, SPELL_DRAW_SHADOWS, true); - DoCast(me, SPELL_RAIN_OF_FIRE); - events.ScheduleEvent(EVENT_SHADOWBOLT_VOLLEY, 6000); - events.ScheduleEvent(EVENT_DRAW_SHADOWS, 30000); - break; - } - case EVENT_SUMMON_TRAVELER: - spawnVoidTraveler(); - events.ScheduleEvent(EVENT_SUMMON_TRAVELER, 10000); - //enrage at 20% - if (HealthBelowPct(20)) - events.ScheduleEvent(EVENT_SUMMON_TRAVELER, 5000); - break; + Creature* Vorpil = ObjectAccessor::GetCreature(*me, _instance->GetData64(DATA_GRANDMASTER_VORPIL)); + if (!Vorpil) + return; + + if (_sacrificed) + { + DoCastAOE(DUNGEON_MODE(SPELL_EMPOWERING_SHADOWS, H_SPELL_EMPOWERING_SHADOWS), true); + DoCast(me, SPELL_SHADOW_NOVA, true); + me->Kill(me); + return; + } + me->GetMotionMaster()->MoveFollow(Vorpil, 0, 0); + if (me->IsWithinDist(Vorpil, 3)) + { + DoCast(me, SPELL_SACRIFICE, false); + _sacrificed = true; + _moveTimer = 500; + return; + } + _moveTimer = 1000; } + else + _moveTimer -= diff; } - DoMeleeAttackIfReady(); - } private: - bool Intro, HelpYell; - bool sumportals; - uint64 PortalsGuid[5]; - + InstanceScript* _instance; + uint32 _moveTimer; + bool _sacrificed; + }; - }; - - CreatureAI* GetAI(Creature* creature) const OVERRIDE - { - return new boss_grandmaster_vorpilAI(creature); - } + CreatureAI* GetAI(Creature* creature) const OVERRIDE + { + return GetShadowLabyrinthAI<npc_voidtravelerAI>(creature); + } }; void AddSC_boss_grandmaster_vorpil() diff --git a/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_murmur.cpp b/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_murmur.cpp index 99078b3b15d..38c14292289 100644 --- a/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_murmur.cpp +++ b/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_murmur.cpp @@ -25,8 +25,8 @@ EndScriptData */ #include "ScriptMgr.h" #include "ScriptedCreature.h" +#include "SpellScript.h" #include "shadow_labyrinth.h" -#include "SpellInfo.h" enum Murmur { @@ -54,149 +54,233 @@ enum Events class boss_murmur : public CreatureScript { -public: - boss_murmur() : CreatureScript("boss_murmur") { } + public: + boss_murmur() : CreatureScript("boss_murmur") { } - struct boss_murmurAI : public BossAI - { - boss_murmurAI(Creature* creature) : BossAI(creature, DATA_MURMUREVENT) + struct boss_murmurAI : public BossAI { - SetCombatMovement(false); - } - - void Reset() OVERRIDE - { - events.ScheduleEvent(EVENT_SONIC_BOOM, 30000); - events.ScheduleEvent(EVENT_MURMURS_TOUCH, urand(8000, 20000)); - events.ScheduleEvent(EVENT_RESONANCE, 5000); - events.ScheduleEvent(EVENT_MAGNETIC_PULL, urand(15000, 30000)); - if (IsHeroic()) + boss_murmurAI(Creature* creature) : BossAI(creature, DATA_MURMUR) { - events.ScheduleEvent(EVENT_THUNDERING_STORM, 15000); - events.ScheduleEvent(EVENT_SONIC_SHOCK, 10000); + SetCombatMovement(false); } - //database should have `RegenHealth`=0 to prevent regen - uint32 hp = me->CountPctFromMaxHealth(40); - if (hp) me->SetHealth(hp); - me->ResetPlayerDamageReq(); - } + void Reset() OVERRIDE + { + _Reset(); + events.ScheduleEvent(EVENT_SONIC_BOOM, 30000); + events.ScheduleEvent(EVENT_MURMURS_TOUCH, urand(8000, 20000)); + events.ScheduleEvent(EVENT_RESONANCE, 5000); + events.ScheduleEvent(EVENT_MAGNETIC_PULL, urand(15000, 30000)); + if (IsHeroic()) + { + events.ScheduleEvent(EVENT_THUNDERING_STORM, 15000); + events.ScheduleEvent(EVENT_SONIC_SHOCK, 10000); + } - void SonicBoomEffect() - { - ThreatContainer::StorageType const &t_list = me->getThreatManager().getThreatList(); - for (ThreatContainer::StorageType::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) + // database should have `RegenHealth`=0 to prevent regen + uint32 hp = me->CountPctFromMaxHealth(40); + if (hp) + me->SetHealth(hp); + me->ResetPlayerDamageReq(); + } + + void EnterCombat(Unit* /*who*/) OVERRIDE { - Unit* target = Unit::GetUnit(*me, (*itr)->getUnitGuid()); - if (target && target->GetTypeId() == TYPEID_PLAYER) - { - //Not do anything without aura, spell can be resisted! - if (target->HasAura(SPELL_SONIC_BOOM_CAST) && me->IsWithinDistInMap(target, 34.0f)) - { - //This will be wrong calculation. Also, comments suggest it must deal damage - target->SetHealth(target->CountPctFromMaxHealth(20)); - } - } + _EnterCombat(); } - } - void EnterCombat(Unit* /*who*/) OVERRIDE {} + void JustDied(Unit* /*killer*/) OVERRIDE + { + _JustDied(); + } - // Sonic Boom instant damage (needs core fix instead of this) - void SpellHitTarget(Unit* target, const SpellInfo* spell) OVERRIDE - { - if (target && target->IsAlive() && spell && spell->Id == uint32(SPELL_SONIC_BOOM_EFFECT)) - me->DealDamage(target, (target->GetHealth()*90)/100, NULL, SPELL_DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NATURE, spell); - } + void UpdateAI(uint32 diff) OVERRIDE + { + if (!UpdateVictim()) + return; - void UpdateAI(uint32 diff) OVERRIDE - { - //Return since we have no target or casting - if (!UpdateVictim() || me->IsNonMeleeSpellCasted(false)) - return; + events.Update(diff); - events.Update(diff); + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; - while (uint32 eventId = events.ExecuteEvent()) - { - switch (eventId) + while (uint32 eventId = events.ExecuteEvent()) { - case EVENT_SONIC_BOOM: - Talk(EMOTE_SONIC_BOOM); - DoCast(me, SPELL_SONIC_BOOM_CAST); - DoCast(me, SPELL_SONIC_BOOM_EFFECT, true); - SonicBoomEffect(); - events.ScheduleEvent(EVENT_SONIC_BOOM, 30000); - events.ScheduleEvent(EVENT_RESONANCE, 1500); - break; - case EVENT_MURMURS_TOUCH: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 80, true)) - DoCast(target, SPELL_MURMURS_TOUCH); - events.ScheduleEvent(EVENT_MURMURS_TOUCH, urand(25000, 35000)); - break; - case EVENT_RESONANCE: - if (!(me->IsWithinMeleeRange(me->GetVictim()))) - { - DoCast(me, SPELL_RESONANCE); - events.ScheduleEvent(EVENT_RESONANCE, 5000); - } - break; - case EVENT_MAGNETIC_PULL: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) - if (target->GetTypeId() == TYPEID_PLAYER && target->IsAlive()) + switch (eventId) + { + case EVENT_SONIC_BOOM: + Talk(EMOTE_SONIC_BOOM); + DoCast(me, SPELL_SONIC_BOOM_CAST); + events.ScheduleEvent(EVENT_SONIC_BOOM, 30000); + events.ScheduleEvent(EVENT_RESONANCE, 1500); + break; + case EVENT_MURMURS_TOUCH: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 80.0f, true)) + DoCast(target, SPELL_MURMURS_TOUCH); + events.ScheduleEvent(EVENT_MURMURS_TOUCH, urand(25000, 35000)); + break; + case EVENT_RESONANCE: + if (!(me->IsWithinMeleeRange(me->GetVictim()))) + { + DoCast(me, SPELL_RESONANCE); + events.ScheduleEvent(EVENT_RESONANCE, 5000); + } + break; + case EVENT_MAGNETIC_PULL: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true)) { DoCast(target, SPELL_MAGNETIC_PULL); - events.ScheduleEvent(EVENT_MAGNETIC_PULL, 15000+rand()%15000); + events.ScheduleEvent(EVENT_MAGNETIC_PULL, urand(15000, 30000)); break; } - events.ScheduleEvent(EVENT_MAGNETIC_PULL, 500); - break; - case EVENT_THUNDERING_STORM: - { - ThreatContainer::StorageType threatlist = me->getThreatManager().getThreatList(); - for (ThreatContainer::StorageType::const_iterator i = threatlist.begin(); i != threatlist.end(); ++i) - if (Unit* target = Unit::GetUnit(*me, (*i)->getUnitGuid())) - if (target->IsAlive() && !me->IsWithinDist(target, 35, false)) - DoCast(target, SPELL_THUNDERING_STORM, true); - events.ScheduleEvent(EVENT_THUNDERING_STORM, 15000); - break; - } - case EVENT_SONIC_SHOCK: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 20, false)) - if (target->IsAlive()) + events.ScheduleEvent(EVENT_MAGNETIC_PULL, 500); + break; + case EVENT_THUNDERING_STORM: + DoCastAOE(SPELL_THUNDERING_STORM, true); + events.ScheduleEvent(EVENT_THUNDERING_STORM, 15000); + break; + case EVENT_SONIC_SHOCK: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 20.0f, false)) DoCast(target, SPELL_SONIC_SHOCK); - events.ScheduleEvent(EVENT_SONIC_SHOCK, 10000+rand()%10000); - break; + events.ScheduleEvent(EVENT_SONIC_SHOCK, urand(10000, 20000)); + break; + } + } + + // Select nearest most aggro target if top aggro too far + if (!me->isAttackReady()) + return; + + if (!me->IsWithinMeleeRange(me->GetVictim())) + { + ThreatContainer::StorageType threatlist = me->getThreatManager().getThreatList(); + for (ThreatContainer::StorageType::const_iterator i = threatlist.begin(); i != threatlist.end(); ++i) + if (Unit* target = ObjectAccessor::GetUnit(*me, (*i)->getUnitGuid())) + if (me->IsWithinMeleeRange(target)) + { + me->TauntApply(target); + break; + } } + + DoMeleeAttackIfReady(); } + }; - // Select nearest most aggro target if top aggro too far - if (!me->isAttackReady()) - return; + CreatureAI* GetAI(Creature* creature) const OVERRIDE + { + return GetShadowLabyrinthAI<boss_murmurAI>(creature); + } +}; - if (!me->IsWithinMeleeRange(me->GetVictim())) +// 33923, 38796 - Sonic Boom +class spell_murmur_sonic_boom : public SpellScriptLoader +{ + public: + spell_murmur_sonic_boom() : SpellScriptLoader("spell_murmur_sonic_boom") { } + + class spell_murmur_sonic_boom_SpellScript : public SpellScript + { + PrepareSpellScript(spell_murmur_sonic_boom_SpellScript); + + bool Validate(SpellInfo const* /*spellInfo*/) OVERRIDE { - ThreatContainer::StorageType threatlist = me->getThreatManager().getThreatList(); - for (ThreatContainer::StorageType::const_iterator i = threatlist.begin(); i != threatlist.end(); ++i) - if (Unit* target = Unit::GetUnit(*me, (*i)->getUnitGuid())) - if (target->IsAlive() && me->IsWithinMeleeRange(target)) - { - me->TauntApply(target); - break; - } + if (!sSpellMgr->GetSpellInfo(SPELL_SONIC_BOOM_EFFECT)) + return false; + return true; + } + + void HandleEffect(SpellEffIndex /*effIndex*/) + { + GetCaster()->CastSpell((Unit*)NULL, SPELL_SONIC_BOOM_EFFECT, true); } - DoMeleeAttackIfReady(); + void Register() OVERRIDE + { + OnEffectHit += SpellEffectFn(spell_murmur_sonic_boom_SpellScript::HandleEffect, EFFECT_0, SPELL_EFFECT_DUMMY); + } + }; + + SpellScript* GetSpellScript() const OVERRIDE + { + return new spell_murmur_sonic_boom_SpellScript(); } - }; +}; + +// 33666, 38795 - Sonic Boom Effect +class spell_murmur_sonic_boom_effect : public SpellScriptLoader +{ + public: + spell_murmur_sonic_boom_effect() : SpellScriptLoader("spell_murmur_sonic_boom_effect") { } + + class spell_murmur_sonic_boom_effect_SpellScript : public SpellScript + { + PrepareSpellScript(spell_murmur_sonic_boom_effect_SpellScript); + + void CalcDamage() + { + if (Unit* target = GetHitUnit()) + SetHitDamage(target->CountPctFromMaxHealth(80)); /// @todo: find correct value + } - CreatureAI* GetAI(Creature* creature) const OVERRIDE - { - return new boss_murmurAI(creature); - } + void Register() OVERRIDE + { + OnHit += SpellHitFn(spell_murmur_sonic_boom_effect_SpellScript::CalcDamage); + } + }; + + SpellScript* GetSpellScript() const OVERRIDE + { + return new spell_murmur_sonic_boom_effect_SpellScript(); + } +}; + +class ThunderingStormCheck +{ + public: + ThunderingStormCheck(WorldObject* source) : _source(source) { } + + bool operator()(WorldObject* obj) + { + float distSq = _source->GetExactDist2dSq(obj); + return distSq < (25.0f * 25.0f) || distSq > (100.0f * 100.0f); + } + + private: + WorldObject const* _source; +}; + +// 39365 - Thundering Storm +class spell_murmur_thundering_storm : public SpellScriptLoader +{ + public: + spell_murmur_thundering_storm() : SpellScriptLoader("spell_murmur_thundering_storm") { } + + class spell_murmur_thundering_storm_SpellScript : public SpellScript + { + PrepareSpellScript(spell_murmur_thundering_storm_SpellScript); + + void FilterTarget(std::list<WorldObject*>& targets) + { + targets.remove_if(ThunderingStormCheck(GetCaster())); + } + + void Register() OVERRIDE + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_murmur_thundering_storm_SpellScript::FilterTarget, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + } + }; + + SpellScript* GetSpellScript() const OVERRIDE + { + return new spell_murmur_thundering_storm_SpellScript(); + } }; void AddSC_boss_murmur() { new boss_murmur(); + new spell_murmur_sonic_boom(); + new spell_murmur_sonic_boom_effect(); + new spell_murmur_thundering_storm(); } diff --git a/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/instance_shadow_labyrinth.cpp b/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/instance_shadow_labyrinth.cpp index 9a507979d8d..a401a74273f 100644 --- a/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/instance_shadow_labyrinth.cpp +++ b/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/instance_shadow_labyrinth.cpp @@ -1,6 +1,5 @@ /* * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/> * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -16,210 +15,178 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -/* ScriptData -SDName: Instance_Shadow_Labyrinth -SD%Complete: 85 -SDComment: Some cleanup left along with save -SDCategory: Auchindoun, Shadow Labyrinth -EndScriptData */ - #include "ScriptMgr.h" #include "InstanceScript.h" +#include "ScriptedCreature.h" #include "shadow_labyrinth.h" -/* Shadow Labyrinth encounters: -1 - Ambassador Hellmaw event -2 - Blackheart the Inciter event -3 - Grandmaster Vorpil event -4 - Murmur event -*/ +DoorData const doorData[] = +{ + { GO_REFECTORY_DOOR, DATA_BLACKHEART_THE_INCITER, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, + { GO_SCREAMING_HALL_DOOR, DATA_GRANDMASTER_VORPIL, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, + { 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE } // END +}; class instance_shadow_labyrinth : public InstanceMapScript { -public: - instance_shadow_labyrinth() : InstanceMapScript("instance_shadow_labyrinth", 555) { } - - InstanceScript* GetInstanceScript(InstanceMap* map) const OVERRIDE - { - return new instance_shadow_labyrinth_InstanceMapScript(map); - } - - struct instance_shadow_labyrinth_InstanceMapScript : public InstanceScript - { - instance_shadow_labyrinth_InstanceMapScript(Map* map) : InstanceScript(map) {} - - uint32 m_auiEncounter[EncounterCount]; - std::string str_data; - - uint64 m_uiRefectoryDoorGUID; - uint64 m_uiScreamingHallDoorGUID; - - uint64 m_uiGrandmasterVorpil; - uint32 m_uiFelOverseerCount; + public: + instance_shadow_labyrinth() : InstanceMapScript(SLScriptName, 555) { } - void Initialize() OVERRIDE + struct instance_shadow_labyrinth_InstanceMapScript : public InstanceScript { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - m_uiRefectoryDoorGUID = 0; - m_uiScreamingHallDoorGUID = 0; - - m_uiGrandmasterVorpil = 0; - m_uiFelOverseerCount = 0; - } + instance_shadow_labyrinth_InstanceMapScript(Map* map) : InstanceScript(map) + { + SetBossNumber(EncounterCount); + LoadDoorData(doorData); - bool IsEncounterInProgress() const OVERRIDE - { - for (uint8 i = 0; i < EncounterCount; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - return true; + AmbassadorHellmawGUID = 0; + GrandmasterVorpilGUID = 0; + FelOverseerCount = 0; + } - return false; - } + void OnCreatureCreate(Creature* creature) OVERRIDE + { + switch (creature->GetEntry()) + { + case NPC_AMBASSADOR_HELLMAW: + AmbassadorHellmawGUID = creature->GetGUID(); + break; + case NPC_GRANDMASTER_VORPIL: + GrandmasterVorpilGUID = creature->GetGUID(); + break; + case NPC_FEL_OVERSEER: + if (creature->IsAlive()) + { + ++FelOverseerCount; + if (Creature* hellmaw = instance->GetCreature(AmbassadorHellmawGUID)) + hellmaw->AI()->DoAction(ACTION_AMBASSADOR_HELLMAW_BANISH); + } + break; + default: + break; + } + } - void OnGameObjectCreate(GameObject* go) OVERRIDE - { - switch (go->GetEntry()) + void OnGameObjectCreate(GameObject* go) OVERRIDE { - case REFECTORY_DOOR: - m_uiRefectoryDoorGUID = go->GetGUID(); - if (m_auiEncounter[2] == DONE) - go->SetGoState(GO_STATE_ACTIVE); - break; - case SCREAMING_HALL_DOOR: - m_uiScreamingHallDoorGUID = go->GetGUID(); - if (m_auiEncounter[3] == DONE) - go->SetGoState(GO_STATE_ACTIVE); - break; + switch (go->GetEntry()) + { + case GO_REFECTORY_DOOR: + case GO_SCREAMING_HALL_DOOR: + AddDoor(go, true); + break; + default: + break; + } } - } - void OnCreatureCreate(Creature* creature) OVERRIDE - { - switch (creature->GetEntry()) + void OnGameObjectRemove(GameObject* go) OVERRIDE { - case 18732: - m_uiGrandmasterVorpil = creature->GetGUID(); - break; - case 18796: - if (creature->IsAlive()) - { - ++m_uiFelOverseerCount; - TC_LOG_DEBUG(LOG_FILTER_TSCR, "Shadow Labyrinth: counting %u Fel Overseers.", m_uiFelOverseerCount); - } - break; + switch (go->GetEntry()) + { + case GO_REFECTORY_DOOR: + case GO_SCREAMING_HALL_DOOR: + AddDoor(go, false); + break; + default: + break; + } } - } - void SetData(uint32 type, uint32 uiData) OVERRIDE - { - switch (type) + void OnUnitDeath(Unit* unit) { - case TYPE_HELLMAW: - m_auiEncounter[0] = uiData; - break; + Creature* creature = unit->ToCreature(); + if (!creature) + return; - case TYPE_OVERSEER: - if (uiData != DONE) - { - TC_LOG_ERROR(LOG_FILTER_TSCR, "Shadow Labyrinth: TYPE_OVERSEER did not expect other data than DONE"); - return; - } - if (m_uiFelOverseerCount) - { - --m_uiFelOverseerCount; + if (creature->GetEntry() == NPC_FEL_OVERSEER) + { + if (FelOverseerCount) + --FelOverseerCount; - if (m_uiFelOverseerCount) - TC_LOG_DEBUG(LOG_FILTER_TSCR, "Shadow Labyrinth: %u Fel Overseers left to kill.", m_uiFelOverseerCount); - else - { - m_auiEncounter[1] = DONE; - TC_LOG_DEBUG(LOG_FILTER_TSCR, "Shadow Labyrinth: TYPE_OVERSEER == DONE"); - } - } - break; - - case DATA_BLACKHEARTTHEINCITEREVENT: - if (uiData == DONE) - DoUseDoorOrButton(m_uiRefectoryDoorGUID); - m_auiEncounter[2] = uiData; - break; - - case DATA_GRANDMASTERVORPILEVENT: - if (uiData == DONE) - DoUseDoorOrButton(m_uiScreamingHallDoorGUID); - m_auiEncounter[3] = uiData; - break; - - case DATA_MURMUREVENT: - m_auiEncounter[4] = uiData; - break; + if (!FelOverseerCount) + if (Creature* hellmaw = instance->GetCreature(AmbassadorHellmawGUID)) + hellmaw->AI()->DoAction(ACTION_AMBASSADOR_HELLMAW_INTRO); + } } - if (uiData == DONE) + uint32 GetData(uint32 type) const OVERRIDE { - if (type == TYPE_OVERSEER && m_uiFelOverseerCount != 0) - return; + switch (type) + { + case DATA_FEL_OVERSEER: + return !FelOverseerCount ? 1 : 0; + default: + break; + } + return 0; + } + uint64 GetData64(uint32 type) const OVERRIDE + { + switch (type) + { + case DATA_GRANDMASTER_VORPIL: + return GrandmasterVorpilGUID; + default: + break; + } + return 0; + } + + std::string GetSaveData() OVERRIDE + { OUT_SAVE_INST_DATA; std::ostringstream saveStream; - saveStream << m_auiEncounter[0] << ' ' << m_auiEncounter[1] << ' ' - << m_auiEncounter[2] << ' ' << m_auiEncounter[3] << ' ' << m_auiEncounter[4]; + saveStream << "S L " << GetBossSaveData(); - str_data = saveStream.str(); - - SaveToDB(); OUT_SAVE_INST_DATA_COMPLETE; + return saveStream.str(); } - } - uint32 GetData(uint32 type) const OVERRIDE - { - switch (type) + void Load(char const* str) OVERRIDE { - case TYPE_HELLMAW: return m_auiEncounter[0]; - case TYPE_OVERSEER: return m_auiEncounter[1]; - case DATA_GRANDMASTERVORPILEVENT: return m_auiEncounter[3]; - case DATA_MURMUREVENT: return m_auiEncounter[4]; - } - return false; - } + if (!str) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } - uint64 GetData64(uint32 identifier) const OVERRIDE - { - if (identifier == DATA_GRANDMASTERVORPIL) - return m_uiGrandmasterVorpil; + OUT_LOAD_INST_DATA(str); - return 0; - } + char dataHead1, dataHead2; - std::string GetSaveData() OVERRIDE - { - return str_data; - } - - void Load(const char* in) OVERRIDE - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } + std::istringstream loadStream(str); + loadStream >> dataHead1 >> dataHead2; - OUT_LOAD_INST_DATA(in); + if (dataHead1 == 'S' && dataHead2 == 'L') + { + for (uint32 i = 0; i < EncounterCount; ++i) + { + uint32 tmpState; + loadStream >> tmpState; + if (tmpState == IN_PROGRESS || tmpState > SPECIAL) + tmpState = NOT_STARTED; + SetBossState(i, EncounterState(tmpState)); + } + } + else + OUT_LOAD_INST_DATA_FAIL; - std::istringstream loadStream(in); - loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3] >> m_auiEncounter[4]; + OUT_LOAD_INST_DATA_COMPLETE; + } - for (uint8 i = 0; i < EncounterCount; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - m_auiEncounter[i] = NOT_STARTED; + protected: + uint64 AmbassadorHellmawGUID; + uint64 GrandmasterVorpilGUID; + uint32 FelOverseerCount; + }; - OUT_LOAD_INST_DATA_COMPLETE; + InstanceScript* GetInstanceScript(InstanceMap* map) const OVERRIDE + { + return new instance_shadow_labyrinth_InstanceMapScript(map); } - }; - }; void AddSC_instance_shadow_labyrinth() diff --git a/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/shadow_labyrinth.h b/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/shadow_labyrinth.h index 8fdb60b32a6..fd073903748 100644 --- a/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/shadow_labyrinth.h +++ b/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/shadow_labyrinth.h @@ -1,6 +1,5 @@ /* * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/> * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -16,26 +15,49 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef DEF_SHADOW_LABYRINTH_H -#define DEF_SHADOW_LABYRINTH_H +#ifndef SHADOW_LABYRINTH_H_ +#define SHADOW_LABYRINTH_H_ -uint32 const EncounterCount = 5; +#define SLScriptName "instance_shadow_labyrinth" + +uint32 const EncounterCount = 4; enum DataTypes { - TYPE_HELLMAW = 1, - TYPE_OVERSEER = 2, - DATA_BLACKHEARTTHEINCITEREVENT = 3, - DATA_GRANDMASTERVORPILEVENT = 4, - DATA_MURMUREVENT = 5, - DATA_GRANDMASTERVORPIL = 6 + // Encounter States/Boss GUIDs + DATA_AMBASSADOR_HELLMAW = 0, + DATA_BLACKHEART_THE_INCITER = 1, + DATA_GRANDMASTER_VORPIL = 2, + DATA_MURMUR = 3, + + // Additional Data + DATA_FEL_OVERSEER = 4 +}; + +enum CreatureIds +{ + NPC_AMBASSADOR_HELLMAW = 18731, + NPC_GRANDMASTER_VORPIL = 18732, + NPC_FEL_OVERSEER = 18796 }; -enum Objects +enum GameObjectIds { - REFECTORY_DOOR = 183296, // door opened when blackheart the inciter dies - SCREAMING_HALL_DOOR = 183295 // door opened when grandmaster vorpil dies + GO_REFECTORY_DOOR = 183296, // door opened when blackheart the inciter dies + GO_SCREAMING_HALL_DOOR = 183295 // door opened when grandmaster vorpil dies }; -#endif +enum Misc +{ + ACTION_AMBASSADOR_HELLMAW_INTRO = 1, + ACTION_AMBASSADOR_HELLMAW_BANISH = 2, +}; + +template<class AI> +AI* GetShadowLabyrinthAI(Creature* creature) +{ + return GetInstanceAI<AI>(creature, SLScriptName); +} + +#endif // SHADOW_LABYRINTH_H_ diff --git a/src/server/scripts/Outland/BlackTemple/black_temple.h b/src/server/scripts/Outland/BlackTemple/black_temple.h index 971cc36d7ba..fb529a6b522 100644 --- a/src/server/scripts/Outland/BlackTemple/black_temple.h +++ b/src/server/scripts/Outland/BlackTemple/black_temple.h @@ -1,6 +1,5 @@ /* * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/> * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -19,36 +18,77 @@ #ifndef BLACK_TEMPLE_H_ #define BLACK_TEMPLE_H_ +#define BTScriptName "instance_black_temple" + uint32 const EncounterCount = 9; enum DataTypes { - DATA_AKAMA = 1, - DATA_AKAMA_SHADE = 2, - DATA_GURTOGGBLOODBOILEVENT = 3, - DATA_HIGHWARLORDNAJENTUS = 4, - DATA_HIGHWARLORDNAJENTUSEVENT = 5, - DATA_ILLIDANSTORMRAGE = 6, - DATA_ILLIDANSTORMRAGEEVENT = 7, - DATA_ILLIDARICOUNCILEVENT = 8, - DATA_ILLIDARICOUNCIL = 9, - DATA_LADYMALANDE = 10, - DATA_HIGHNETHERMANCERZEREVOR = 11, - DATA_GATHIOSTHESHATTERER = 12, - DATA_VERASDARKSHADOW = 13, - DATA_MOTHERSHAHRAZEVENT = 14, - DATA_RELIQUARYOFSOULSEVENT = 15, - DATA_SHADEOFAKAMA = 16, - DATA_SHADEOFAKAMAEVENT = 17, - DATA_SUPREMUS = 18, - DATA_SUPREMUSEVENT = 19, - DATA_TERONGOREFIENDEVENT = 20, - DATA_GAMEOBJECT_NAJENTUS_GATE = 21, - DATA_GAMEOBJECT_ILLIDAN_GATE = 22, - DATA_GAMEOBJECT_ILLIDAN_DOOR_R = 23, - DATA_GAMEOBJECT_ILLIDAN_DOOR_L = 24, - DATA_GAMEOBJECT_SUPREMUS_DOORS = 25, - DATA_BLOOD_ELF_COUNCIL_VOICE = 26 + // Encounter States/Boss GUIDs + DATA_HIGH_WARLORD_NAJENTUS = 0, + DATA_SUPREMUS = 1, + DATA_SHADE_OF_AKAMA = 2, + DATA_TERON_GOREFIEND = 3, + DATA_GURTOGG_BLOODBOIL = 4, + DATA_RELIQUARY_OF_SOULS = 5, + DATA_MOTHER_SHAHRAZ = 6, + DATA_ILLIDARI_COUNCIL = 7, + DATA_ILLIDAN_STORMRAGE = 8, + + // Additional Data + DATA_AKAMA_SHADE = 9, + DATA_AKAMA = 10, + + DATA_GATHIOS_THE_SHATTERER = 11, + DATA_HIGH_NETHERMANCER_ZEREVOR = 12, + DATA_LADY_MALANDE = 13, + DATA_VERAS_DARKSHADOW = 14, + DATA_BLOOD_ELF_COUNCIL_VOICE = 15, + + DATA_GO_ILLIDAN_GATE = 16, + DATA_GO_ILLIDAN_DOOR_R = 17, + DATA_GO_ILLIDAN_DOOR_L = 18 +}; + +enum CreatureIds +{ + NPC_HIGH_WARLORD_NAJENTUS = 22887, + NPC_SUPREMUS = 22898, + NPC_SHADE_OF_AKAMA = 22841, + NPC_AKAMA_SHADE = 23191, // This is the Akama that starts the Shade of Akama encounter. + NPC_AKAMA = 23089, // This is the Akama that starts the Illidan encounter. + + NPC_GATHIOS_THE_SHATTERER = 22949, + NPC_HIGH_NETHERMANCER_ZEREVOR = 22950, + NPC_LADY_MALANDE = 22951, + NPC_VERAS_DARKSHADOW = 22952, + NPC_ILLIDARI_COUNCIL = 23426, + NPC_BLOOD_ELF_COUNCIL_VOICE = 23499, + + NPC_ILLIDAN_STORMRAGE = 22917 }; -#endif +enum GameObjectIds +{ + GO_NAJENTUS_GATE = 185483, + GO_SUPREMUS_GATE = 185882, + GO_SHADE_OF_AKAMA_DOOR = 185478, + GO_TERON_DOOR_1 = 185480, + GO_TERON_DOOR_2 = 186153, + GO_GURTOGG_DOOR = 185892, + GO_TEMPLE_DOOR = 185479, + GO_MOTHER_SHAHRAZ_DOOR = 185482, + GO_COUNCIL_DOOR_1 = 185481, + GO_COUNCIL_DOOR_2 = 186152, + GO_ILLIDAN_GATE = 185905, + GO_ILLIDAN_DOOR_R = 186261, + GO_ILLIDAN_DOOR_L = 186262 +}; + +template<class AI> +AI* GetBlackTempleAI(Creature* creature) +{ + return GetInstanceAI<AI>(creature, BTScriptName); +} + +#endif // BLACK_TEMPLE_H_ diff --git a/src/server/scripts/Outland/BlackTemple/boss_bloodboil.cpp b/src/server/scripts/Outland/BlackTemple/boss_bloodboil.cpp index 7a11044476a..3a33885144d 100644 --- a/src/server/scripts/Outland/BlackTemple/boss_bloodboil.cpp +++ b/src/server/scripts/Outland/BlackTemple/boss_bloodboil.cpp @@ -96,7 +96,7 @@ public: void Reset() OVERRIDE { if (instance) - instance->SetData(DATA_GURTOGGBLOODBOILEVENT, NOT_STARTED); + instance->SetBossState(DATA_GURTOGG_BLOODBOIL, NOT_STARTED); TargetGUID = 0; @@ -124,7 +124,7 @@ public: DoZoneInCombat(); Talk(SAY_AGGRO); if (instance) - instance->SetData(DATA_GURTOGGBLOODBOILEVENT, IN_PROGRESS); + instance->SetBossState(DATA_GURTOGG_BLOODBOIL, IN_PROGRESS); } void KilledUnit(Unit* /*victim*/) OVERRIDE @@ -135,7 +135,7 @@ public: void JustDied(Unit* /*killer*/) OVERRIDE { if (instance) - instance->SetData(DATA_GURTOGGBLOODBOILEVENT, DONE); + instance->SetBossState(DATA_GURTOGG_BLOODBOIL, DONE); Talk(SAY_DEATH); } diff --git a/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp b/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp index 2fdfe72a6f9..279a846140c 100644 --- a/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp +++ b/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp @@ -31,10 +31,6 @@ EndScriptData */ #include "Player.h" #include "SpellInfo.h" -#define GETGO(obj, guid) GameObject* obj = instance->instance->GetGameObject(guid) -#define GETUNIT(unit, guid) Unit* unit = Unit::GetUnit(*me, guid) -#define GETCRE(cre, guid) Creature* cre = Unit::GetCreature(*me, guid) - #define EMOTE_UNABLE_TO_SUMMON "%s is unable to summon Maiev Shadowsong and enter Phase 4. Resetting Encounter." // Other defines @@ -409,11 +405,11 @@ public: void EnrageCheck() { - if (GETUNIT(Glaive, GlaiveGUID)) + if (Creature* glaive = ObjectAccessor::GetCreature(*me, GlaiveGUID)) { - if (!me->IsWithinDistInMap(Glaive, FLAME_ENRAGE_DISTANCE)) + if (!me->IsWithinDistInMap(glaive, FLAME_ENRAGE_DISTANCE)) { - Glaive->InterruptNonMeleeSpells(true); + glaive->InterruptNonMeleeSpells(true); DoCast(me, SPELL_FLAME_ENRAGE, true); DoResetThreat(); if (SelectTarget(SELECT_TARGET_RANDOM, 0)) @@ -424,7 +420,7 @@ public: } else if (!me->HasAura(SPELL_AZZINOTH_CHANNEL)) { - Glaive->CastSpell(me, SPELL_AZZINOTH_CHANNEL, false); + glaive->CastSpell(me, SPELL_AZZINOTH_CHANNEL, false); me->RemoveAurasDueToSpell(SPELL_FLAME_ENRAGE); } } @@ -482,6 +478,7 @@ public: { instance = creature->GetInstanceScript(); DoCast(me, SPELL_DUAL_WIELD, true); + AkamaGUID = 0; } void Reset() OVERRIDE; @@ -547,9 +544,9 @@ public: if (!instance) return; - instance->SetData(DATA_ILLIDANSTORMRAGEEVENT, DONE); // Completed + instance->SetBossState(DATA_ILLIDAN_STORMRAGE, DONE); - for (uint8 i = DATA_GAMEOBJECT_ILLIDAN_DOOR_R; i < DATA_GAMEOBJECT_ILLIDAN_DOOR_L + 1; ++i) + for (uint8 i = DATA_GO_ILLIDAN_DOOR_R; i < DATA_GO_ILLIDAN_DOOR_L + 1; ++i) instance->HandleGameObject(instance->GetData64(i), true); } @@ -694,13 +691,14 @@ public: } if (MaievGUID) { - GETCRE(Maiev, MaievGUID); - if (Maiev && Maiev->IsAlive()) - Maiev->AI()->DoAction(NextPhase); + if (Creature* maiev = ObjectAccessor::GetCreature(*me, MaievGUID)) + if (maiev->IsAlive()) + maiev->AI()->DoAction(NextPhase); } Phase = NextPhase; Event = EVENT_NULL; } + void CastEyeBlast() { me->InterruptNonMeleeSpells(false); @@ -738,26 +736,27 @@ public: me->SetTarget(Trigger->GetGUID()); DoCast(Trigger, SPELL_EYE_BLAST); } + void SummonFlamesOfAzzinoth() { Talk(SAY_ILLIDAN_SUMMONFLAMES); for (uint8 i = 0; i < 2; ++i) { - if (GETUNIT(Glaive, GlaiveGUID[i])) + if (Creature* glaive = ObjectAccessor::GetCreature(*me, GlaiveGUID[i])) { - Creature* Flame = me->SummonCreature(FLAME_OF_AZZINOTH, GlaivePosition[i+2].x, GlaivePosition[i+2].y, GlaivePosition[i+2].z, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 5000); - if (Flame) + if (Creature* flame = me->SummonCreature(FLAME_OF_AZZINOTH, GlaivePosition[i+2].x, GlaivePosition[i+2].y, GlaivePosition[i+2].z, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 5000)) { - Flame->setFaction(me->getFaction()); // Just in case the database has it as a different faction - Flame->SetMeleeDamageSchool(SPELL_SCHOOL_FIRE); - FlameGUID[i] = Flame->GetGUID(); // Record GUID in order to check if they're dead later on to move to the next phase - CAST_AI(npc_flame_of_azzinoth::flame_of_azzinothAI, Flame->AI())->SetGlaiveGUID(GlaiveGUID[i]); - Glaive->CastSpell(Flame, SPELL_AZZINOTH_CHANNEL, false); // Glaives do some random Beam type channel on it. + flame->setFaction(me->getFaction()); // Just in case the database has it as a different faction + flame->SetMeleeDamageSchool(SPELL_SCHOOL_FIRE); + FlameGUID[i] = flame->GetGUID(); // Record GUID in order to check if they're dead later on to move to the next phase + CAST_AI(npc_flame_of_azzinoth::flame_of_azzinothAI, flame->AI())->SetGlaiveGUID(GlaiveGUID[i]); + glaive->CastSpell(flame, SPELL_AZZINOTH_CHANNEL, false); // Glaives do some random Beam type channel on it. } } } } + void SummonMaiev() { DoCast(me, SPELL_SHADOW_PRISON, true); @@ -853,11 +852,9 @@ public: { if (GlaiveGUID[i]) { - if (GETUNIT(Glaive, GlaiveGUID[i])) - { - Glaive->SetVisible(false); - Glaive->setDeathState(JUST_DIED); // Despawn the Glaive - } + if (Creature* glaive = ObjectAccessor::GetCreature(*me, GlaiveGUID[i])) + glaive->DespawnOrUnsummon(); + GlaiveGUID[i] = 0; } } @@ -1085,7 +1082,7 @@ public: { case EVENT_SHADOW_BLAST: me->GetMotionMaster()->Clear(false); - if (!me->IsWithinDistInMap(me->GetVictim(), 50)||!me->IsWithinLOSInMap(me->GetVictim())) + if (me->GetVictim() && (!me->IsWithinDistInMap(me->GetVictim(), 50) || !me->IsWithinLOSInMap(me->GetVictim()))) me->GetMotionMaster()->MoveChase(me->GetVictim(), 30); else me->GetMotionMaster()->MoveIdle(); @@ -1173,9 +1170,10 @@ public: damage = 0; else { - GETUNIT(Illidan, IllidanGUID); - if (Illidan && Illidan->GetVictim() == me) - damage = me->CountPctFromMaxHealth(10); + if (Creature* illidan = ObjectAccessor::GetCreature(*me, IllidanGUID)) + if (illidan->GetVictim() == me) + damage = me->CountPctFromMaxHealth(10); + if (damage >= me->GetHealth()) damage = 0; } @@ -1190,9 +1188,9 @@ public: AttackStartNoMove(who); else if (Phase == PHASE_DEMON || Phase == PHASE_TRANSFORM_SEQUENCE) { - GETUNIT(Illidan, IllidanGUID); - if (Illidan && me->IsWithinDistInMap(Illidan, 25)) - BlinkToPlayer();// Do not let dread aura hurt her. + if (Creature* illidan = ObjectAccessor::GetCreature(*me, IllidanGUID)) + if (me->IsWithinDistInMap(illidan, 25)) + BlinkToPlayer(); // Do not let dread aura hurt her. AttackStartNoMove(who); } else @@ -1253,11 +1251,11 @@ public: void BlinkToPlayer() { - if (GETCRE(Illidan, IllidanGUID)) + if (Creature* illidan = ObjectAccessor::GetCreature(*me, IllidanGUID)) { - Unit* target = Illidan->AI()->SelectTarget(SELECT_TARGET_RANDOM, 0); + Unit* target = illidan->AI()->SelectTarget(SELECT_TARGET_RANDOM, 0); - if (!target || !me->IsWithinDistInMap(target, 80) || Illidan->IsWithinDistInMap(target, 20)) + if (!target || !me->IsWithinDistInMap(target, 80) || illidan->IsWithinDistInMap(target, 20)) { uint8 pos = rand()%4; BlinkTo(HoverPosition[pos].x, HoverPosition[pos].y, HoverPosition[pos].z); @@ -1329,8 +1327,8 @@ public: { me->SetVisible(false); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - if (GETCRE(Illidan, IllidanGUID)) - CAST_AI(boss_illidan_stormrage::boss_illidan_stormrageAI, Illidan->AI())->DeleteFromThreatList(me->GetGUID()); + if (Creature* illidan = ObjectAccessor::GetCreature(*me, IllidanGUID)) + CAST_AI(boss_illidan_stormrage::boss_illidan_stormrageAI, illidan->AI())->DeleteFromThreatList(me->GetGUID()); me->AttackStop(); Timer[EVENT_MAIEV_STEALTH] = 60000; // reappear after 1 minute MaxTimer = 1; @@ -1372,12 +1370,12 @@ public: WalkCount = 0; if (instance) { - instance->SetData(DATA_ILLIDANSTORMRAGEEVENT, NOT_STARTED); + instance->SetBossState(DATA_ILLIDAN_STORMRAGE, NOT_STARTED); - IllidanGUID = instance->GetData64(DATA_ILLIDANSTORMRAGE); - GateGUID = instance->GetData64(DATA_GAMEOBJECT_ILLIDAN_GATE); - DoorGUID[0] = instance->GetData64(DATA_GAMEOBJECT_ILLIDAN_DOOR_R); - DoorGUID[1] = instance->GetData64(DATA_GAMEOBJECT_ILLIDAN_DOOR_L); + IllidanGUID = instance->GetData64(DATA_ILLIDAN_STORMRAGE); + GateGUID = instance->GetData64(DATA_GO_ILLIDAN_GATE); + DoorGUID[0] = instance->GetData64(DATA_GO_ILLIDAN_DOOR_R); + DoorGUID[1] = instance->GetData64(DATA_GO_ILLIDAN_DOOR_L); if (JustCreated) // close all doors at create { @@ -1466,18 +1464,18 @@ public: if (!instance) return; - instance->SetData(DATA_ILLIDANSTORMRAGEEVENT, IN_PROGRESS); + instance->SetBossState(DATA_ILLIDAN_STORMRAGE, IN_PROGRESS); for (uint8 i = 0; i < 2; ++i) instance->HandleGameObject(DoorGUID[i], false); - if (GETCRE(Illidan, IllidanGUID)) + if (Creature* illidan = ObjectAccessor::GetCreature(*me, IllidanGUID)) { - Illidan->RemoveAurasDueToSpell(SPELL_KNEEL); - me->SetInFront(Illidan); - Illidan->SetInFront(me); + illidan->RemoveAurasDueToSpell(SPELL_KNEEL); + me->SetInFront(illidan); + illidan->SetInFront(me); me->GetMotionMaster()->MoveIdle(); - Illidan->GetMotionMaster()->MoveIdle(); - CAST_AI(boss_illidan_stormrage::boss_illidan_stormrageAI, Illidan->AI())->AkamaGUID = me->GetGUID(); - CAST_AI(boss_illidan_stormrage::boss_illidan_stormrageAI, Illidan->AI())->EnterPhase(PHASE_TALK_SEQUENCE); + illidan->GetMotionMaster()->MoveIdle(); + CAST_AI(boss_illidan_stormrage::boss_illidan_stormrageAI, illidan->AI())->AkamaGUID = me->GetGUID(); + CAST_AI(boss_illidan_stormrage::boss_illidan_stormrageAI, illidan->AI())->EnterPhase(PHASE_TALK_SEQUENCE); } } @@ -1488,8 +1486,8 @@ public: if (!JustCreated) return; float x, y, z; - if (GETGO(Gate, GateGUID)) - Gate->GetPosition(x, y, z); + if (GameObject* gate = ObjectAccessor::GetGameObject(*me, GateGUID)) + gate->GetPosition(x, y, z); else return; // if door not spawned, don't crash server @@ -1531,8 +1529,8 @@ public: WalkCount = 0; else if (Phase == PHASE_TALK) { - if (GETCRE(Illidan, IllidanGUID)) - CAST_AI(boss_illidan_stormrage::boss_illidan_stormrageAI, Illidan->AI())->DeleteFromThreatList(me->GetGUID()); + if (Creature* illidan = ObjectAccessor::GetCreature(*me, IllidanGUID)) + CAST_AI(boss_illidan_stormrage::boss_illidan_stormrageAI, illidan->AI())->DeleteFromThreatList(me->GetGUID()); EnterEvadeMode(); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); ++WalkCount; @@ -1554,10 +1552,10 @@ public: } break; case PHASE_FIGHT_ILLIDAN: - if (GETUNIT(Illidan, IllidanGUID)) + if (Creature* illidan = ObjectAccessor::GetCreature(*me, IllidanGUID)) { - me->AddThreat(Illidan, 10000000.0f); - me->GetMotionMaster()->MoveChase(Illidan); + me->AddThreat(illidan, 10000000.0f); + me->GetMotionMaster()->MoveChase(illidan); } Timer = 30000; // chain lightning break; @@ -1584,10 +1582,10 @@ public: switch (TalkCount) { case 0: - if (GETCRE(Illidan, IllidanGUID)) + if (Creature* illidan = ObjectAccessor::GetCreature(*me, IllidanGUID)) { - CAST_AI(boss_illidan_stormrage::boss_illidan_stormrageAI, Illidan->AI())->Timer[EVENT_TAUNT] += 30000; - Illidan->AI()->Talk(SAY_ILLIDAN_MINION); + CAST_AI(boss_illidan_stormrage::boss_illidan_stormrageAI, illidan->AI())->Timer[EVENT_TAUNT] += 30000; + illidan->AI()->Talk(SAY_ILLIDAN_MINION); } Timer = 8000; break; @@ -1694,7 +1692,7 @@ public: { if (Check_Timer <= diff) { - if (instance && instance->GetData(DATA_ILLIDARICOUNCILEVENT) == DONE) + if (instance && instance->GetBossState(DATA_ILLIDARI_COUNCIL) == DONE) me->SetVisible(true); Check_Timer = 5000; @@ -1728,8 +1726,8 @@ public: break; case PHASE_FIGHT_ILLIDAN: { - GETUNIT(Illidan, IllidanGUID); - if (Illidan && Illidan->HealthBelowPct(90)) + Creature* illidan = ObjectAccessor::GetCreature(*me, IllidanGUID); + if (illidan && illidan->HealthBelowPct(90)) EnterPhase(PHASE_TALK); else { @@ -1752,9 +1750,9 @@ public: me->AddThreat(Elite, 1000000.0f); } Timer = urand(10000, 16000); - GETUNIT(Illidan, IllidanGUID); - if (Illidan && Illidan->HealthBelowPct(10)) - EnterPhase(PHASE_RETURN); + if (Creature* illidan = ObjectAccessor::GetCreature(*me, IllidanGUID)) + if (illidan->HealthBelowPct(10)) + EnterPhase(PHASE_RETURN); } break; default: @@ -1803,22 +1801,14 @@ public: void boss_illidan_stormrage::boss_illidan_stormrageAI::Reset() { if (instance) - instance->SetData(DATA_ILLIDANSTORMRAGEEVENT, NOT_STARTED); + instance->SetBossState(DATA_ILLIDAN_STORMRAGE, NOT_STARTED); - if (AkamaGUID) + if (Creature* akama = ObjectAccessor::GetCreature(*me, AkamaGUID)) { - if (GETCRE(Akama, AkamaGUID)) - { - if (!Akama->IsAlive()) - Akama->Respawn(); - else - { - CAST_AI(npc_akama_illidan::npc_akama_illidanAI, Akama->AI())->EnterEvadeMode(); - Akama->GetMotionMaster()->MoveTargetedHome(); - CAST_AI(npc_akama_illidan::npc_akama_illidanAI, Akama->AI())->Reset(); - } - } - AkamaGUID = 0; + if (!akama->IsAlive()) + akama->Respawn(); + else + akama->AI()->EnterEvadeMode(); } MaievGUID = 0; @@ -1908,11 +1898,11 @@ void boss_illidan_stormrage::boss_illidan_stormrageAI::HandleTalkSequence() me->SetWalk(false); break; case 9: - if (GETCRE(Akama, AkamaGUID)) + if (Creature* akama = ObjectAccessor::GetCreature(*me, AkamaGUID)) { me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE + UNIT_FLAG_NOT_SELECTABLE); - me->AddThreat(Akama, 100.0f); - CAST_AI(npc_akama_illidan::npc_akama_illidanAI, Akama->AI())->EnterPhase(PHASE_FIGHT_ILLIDAN); + me->AddThreat(akama, 100.0f); + CAST_AI(npc_akama_illidan::npc_akama_illidanAI, akama->AI())->EnterPhase(PHASE_FIGHT_ILLIDAN); EnterPhase(PHASE_NORMAL); } break; @@ -1920,23 +1910,23 @@ void boss_illidan_stormrage::boss_illidan_stormrageAI::HandleTalkSequence() SummonMaiev(); break; case 11: - if (GETUNIT(Maiev, MaievGUID)) + if (Creature* maiev = ObjectAccessor::GetCreature(*me, MaievGUID)) { - Maiev->SetVisible(true); // Maiev is now visible - Maiev->CastSpell(Maiev, SPELL_TELEPORT_VISUAL, true); // onoz she looks like she teleported! - Maiev->SetInFront(me); // Have her face us - me->SetInFront(Maiev); // Face her, so it's not rude =P - Maiev->GetMotionMaster()->MoveIdle(); + maiev->SetVisible(true); // Maiev is now visible + maiev->CastSpell(maiev, SPELL_TELEPORT_VISUAL, true); // onoz she looks like she teleported! + maiev->SetInFront(me); // Have her face us + me->SetInFront(maiev); // Face her, so it's not rude =P + maiev->GetMotionMaster()->MoveIdle(); me->GetMotionMaster()->MoveIdle(); } break; case 14: - if (GETCRE(Maiev, MaievGUID)) + if (Creature* maiev = ObjectAccessor::GetCreature(*me, MaievGUID)) { me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE + UNIT_FLAG_NOT_SELECTABLE); - Maiev->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE + UNIT_FLAG_NOT_SELECTABLE); - Maiev->AddThreat(me, 10000000.0f); // Have Maiev add a lot of threat on us so that players don't pull her off if they damage her via AOE - Maiev->AI()->AttackStart(me); // Force Maiev to attack us. + maiev->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE + UNIT_FLAG_NOT_SELECTABLE); + maiev->AddThreat(me, 10000000.0f); // Have Maiev add a lot of threat on us so that players don't pull her off if they damage her via AOE + maiev->AI()->AttackStart(me); // Force Maiev to attack us. EnterPhase(PHASE_NORMAL_MAIEV); } break; @@ -1945,26 +1935,26 @@ void boss_illidan_stormrage::boss_illidan_stormrageAI::HandleTalkSequence() Summons.DespawnAll(); break; case 17: - if (GETCRE(Akama, AkamaGUID)) + if (Creature* akama = ObjectAccessor::GetCreature(*me, AkamaGUID)) { - if (!me->IsWithinDistInMap(Akama, 15)) + if (!me->IsWithinDistInMap(akama, 15)) { float x, y, z; me->GetPosition(x, y, z); x += 10; y += 10; - Akama->GetMotionMaster()->Clear(false); + akama->GetMotionMaster()->Clear(false); // Akama->GetMotionMaster()->MoveIdle(); - Akama->SetPosition(x, y, z, 0.0f); - Akama->MonsterMoveWithSpeed(x, y, z, 0); // Illidan must not die until Akama arrives. - Akama->GetMotionMaster()->MoveChase(me); + akama->SetPosition(x, y, z, 0.0f); + akama->MonsterMoveWithSpeed(x, y, z, 0); // Illidan must not die until Akama arrives. + akama->GetMotionMaster()->MoveChase(me); } } break; case 19: // Make Maiev leave - if (GETUNIT(Maiev, MaievGUID)) + if (Creature* maiev = ObjectAccessor::GetCreature(*me, MaievGUID)) { - Maiev->CastSpell(Maiev, SPELL_TELEPORT_VISUAL, true); - Maiev->setDeathState(JUST_DIED); + maiev->CastSpell(maiev, SPELL_TELEPORT_VISUAL, true); + maiev->setDeathState(JUST_DIED); me->SetUInt32Value(UNIT_FIELD_BYTES_1, UNIT_STAND_STATE_DEAD); } break; @@ -2171,7 +2161,7 @@ public: void Reset() OVERRIDE { if (instance) - IllidanGUID = instance->GetData64(DATA_ILLIDANSTORMRAGE); + IllidanGUID = instance->GetData64(DATA_ILLIDAN_STORMRAGE); else IllidanGUID = 0; @@ -2208,22 +2198,24 @@ public: AttackStart(target); else { - me->SetVisible(false); - me->setDeathState(JUST_DIED); + me->DespawnOrUnsummon(); return; } } if (CheckTimer <= diff) { - GETUNIT(Illidan, IllidanGUID); - if (!Illidan || Illidan->ToCreature()->IsInEvadeMode()) + Creature* illidan = ObjectAccessor::GetCreature(*me, IllidanGUID); + if (!illidan || illidan->IsInEvadeMode()) { - me->SetVisible(false); - me->setDeathState(JUST_DIED); + me->DespawnOrUnsummon(); return; - } else CheckTimer = 5000; - } else CheckTimer -= diff; + } + else + CheckTimer = 5000; + } + else + CheckTimer -= diff; DoMeleeAttackIfReady(); } diff --git a/src/server/scripts/Outland/BlackTemple/boss_mother_shahraz.cpp b/src/server/scripts/Outland/BlackTemple/boss_mother_shahraz.cpp index b9172be49da..aafe5f365b2 100644 --- a/src/server/scripts/Outland/BlackTemple/boss_mother_shahraz.cpp +++ b/src/server/scripts/Outland/BlackTemple/boss_mother_shahraz.cpp @@ -114,7 +114,7 @@ public: void Reset() OVERRIDE { if (instance) - instance->SetData(DATA_MOTHERSHAHRAZEVENT, NOT_STARTED); + instance->SetBossState(DATA_MOTHER_SHAHRAZ, NOT_STARTED); for (uint8 i = 0; i<3; ++i) TargetGUID[i] = 0; @@ -137,7 +137,7 @@ public: void EnterCombat(Unit* /*who*/) OVERRIDE { if (instance) - instance->SetData(DATA_MOTHERSHAHRAZEVENT, IN_PROGRESS); + instance->SetBossState(DATA_MOTHER_SHAHRAZ, IN_PROGRESS); DoZoneInCombat(); Talk(SAY_AGGRO); @@ -151,7 +151,7 @@ public: void JustDied(Unit* /*killer*/) OVERRIDE { if (instance) - instance->SetData(DATA_MOTHERSHAHRAZEVENT, DONE); + instance->SetBossState(DATA_MOTHER_SHAHRAZ, DONE); Talk(SAY_DEATH); } diff --git a/src/server/scripts/Outland/BlackTemple/boss_reliquary_of_souls.cpp b/src/server/scripts/Outland/BlackTemple/boss_reliquary_of_souls.cpp index 22ea1b70c21..ab3bc98b41b 100644 --- a/src/server/scripts/Outland/BlackTemple/boss_reliquary_of_souls.cpp +++ b/src/server/scripts/Outland/BlackTemple/boss_reliquary_of_souls.cpp @@ -159,14 +159,13 @@ public: void Reset() OVERRIDE { if (instance) - instance->SetData(DATA_RELIQUARYOFSOULSEVENT, NOT_STARTED); + instance->SetBossState(DATA_RELIQUARY_OF_SOULS, NOT_STARTED); if (EssenceGUID) { - if (Creature* Essence = Unit::GetCreature(*me, EssenceGUID)) - { - Essence->DespawnOrUnsummon(); - } + if (Creature* essence = ObjectAccessor::GetCreature(*me, EssenceGUID)) + essence->DespawnOrUnsummon(); + EssenceGUID = 0; } @@ -178,7 +177,6 @@ public: } void MoveInLineOfSight(Unit* who) OVERRIDE - { if (!who) return; @@ -200,7 +198,7 @@ public: me->AddThreat(who, 10000.0f); DoZoneInCombat(); if (instance) - instance->SetData(DATA_RELIQUARYOFSOULSEVENT, IN_PROGRESS); + instance->SetBossState(DATA_RELIQUARY_OF_SOULS, IN_PROGRESS); Phase = 1; Counter = 0; @@ -246,7 +244,7 @@ public: void JustDied(Unit* /*killer*/) OVERRIDE { if (instance) - instance->SetData(DATA_RELIQUARYOFSOULSEVENT, DONE); + instance->SetBossState(DATA_RELIQUARY_OF_SOULS, DONE); } void UpdateAI(uint32 diff) OVERRIDE @@ -422,7 +420,6 @@ public: { damage = 0; me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->Yell(SUFF_SAY_RECAP, LANG_UNIVERSAL, 0); Talk(SUFF_SAY_RECAP); me->SetReactState(REACT_PASSIVE); } @@ -431,14 +428,13 @@ public: void EnterCombat(Unit* /*who*/) OVERRIDE { if (!me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE)) - { + { Talk(SUFF_SAY_FREED); DoZoneInCombat(); DoCast(me, AURA_OF_SUFFERING, true); // linked aura need core support DoCast(me, ESSENCE_OF_SUFFERING_PASSIVE, true); DoCast(me, ESSENCE_OF_SUFFERING_PASSIVE2, true); - } - else return; + } } void KilledUnit(Unit* /*victim*/) OVERRIDE diff --git a/src/server/scripts/Outland/BlackTemple/boss_shade_of_akama.cpp b/src/server/scripts/Outland/BlackTemple/boss_shade_of_akama.cpp index 4a4304bcd24..92647cfb69f 100644 --- a/src/server/scripts/Outland/BlackTemple/boss_shade_of_akama.cpp +++ b/src/server/scripts/Outland/BlackTemple/boss_shade_of_akama.cpp @@ -123,23 +123,22 @@ enum Events EVENT_SUMMON_ASHTONGUE_SORCERER = 12, EVENT_SUMMON_ASHTONGUE_DEFENDER = 13, // Channeler - EVENT_GET_SHADE_GUID = 14, - EVENT_CHANNEL = 15, + EVENT_CHANNEL = 14, // Ashtongue Sorcerer - EVENT_SORCERER_CHANNEL = 16, + EVENT_SORCERER_CHANNEL = 15, // Ashtongue Defender - EVENT_DEBILITATING_STRIKE = 17, - EVENT_HEROIC_STRIKE = 18, - EVENT_SHIELD_BASH = 19, - EVENT_WINDFURY = 20, + EVENT_DEBILITATING_STRIKE = 16, + EVENT_HEROIC_STRIKE = 17, + EVENT_SHIELD_BASH = 18, + EVENT_WINDFURY = 29, // Ashtongue Rogue - EVENT_DEBILITATING_POISON = 21, - EVENT_EVISCERATE = 22, + EVENT_DEBILITATING_POISON = 20, + EVENT_EVISCERATE = 21, // Ashtongue Elementalist - EVENT_RAIN_OF_FIRE = 23, - EVENT_LIGHTNING_BOLT = 24, + EVENT_RAIN_OF_FIRE = 22, + EVENT_LIGHTNING_BOLT = 23, // Ashtongue Spiritbinder - EVENT_SPIRIT_HEAL = 25, + EVENT_SPIRIT_HEAL = 24 }; struct Location @@ -177,11 +176,11 @@ public: if (!HasKilledAkamaAndReseting) { for (std::list<uint64>::const_iterator itr = Channelers.begin(); itr != Channelers.end(); ++itr) - if (Creature* Channeler = (Unit::GetCreature(*me, *itr))) + if (Creature* Channeler = ObjectAccessor::GetCreature(*me, *itr)) Channeler->DespawnOrUnsummon(); for (std::list<uint64>::const_iterator itr = Spawners.begin(); itr != Spawners.end(); ++itr) - if (Creature* Spawner = (Unit::GetCreature(*me, *itr))) + if (Creature* Spawner = ObjectAccessor::GetCreature(*me, *itr)) Spawner->AI()->SetData(SETDATA_DATA, SETDATA_DESPAWN_ALL_SPAWNS); events.ScheduleEvent(EVENT_FIND_CHANNELERS_SPAWNERS, 3000); @@ -200,16 +199,16 @@ public: void JustDied(Unit* /*killer*/) OVERRIDE { if (instance) - instance->SetData(DATA_SHADEOFAKAMAEVENT, DONE); + instance->SetBossState(DATA_SHADE_OF_AKAMA, DONE); } - void EnterCombat(Unit* /*who*/) OVERRIDE {} + void EnterCombat(Unit* /*who*/) OVERRIDE { } void AttackStart(Unit* who) OVERRIDE { if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE)) { - if (Creature* Akama = Unit::GetCreature((*me), akamaGUID)) + if (Creature* Akama = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_AKAMA_SHADE))) if (Akama->IsAlive()) ScriptedAI::AttackStart(Akama); } @@ -233,7 +232,7 @@ public: events.ScheduleEvent(EVENT_START_ATTACK_AKAMA, 500); events.ScheduleEvent(EVENT_SET_CHANNELERS_SPAWNERS, 1000); me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_NONE); - if (Creature* Akama = Unit::GetCreature((*me), akamaGUID)) + if (Creature* Akama = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_AKAMA_SHADE))) me->AddThreat(Akama, 10000000.0f); } else if (spell->Id == SPELL_SHADE_SOUL_CHANNEL_2) @@ -269,7 +268,7 @@ public: switch (eventId) { case EVENT_RESET_ENCOUNTER: - if (Creature* Akama = Unit::GetCreature((*me), akamaGUID)) + if (Creature* Akama = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_AKAMA_SHADE))) if (!Akama->IsAlive()) Akama->Respawn(); break; @@ -294,7 +293,6 @@ public: Spawners.push_back((*itr)->GetGUID()); me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_STUN); - akamaGUID = instance->GetData64(DATA_AKAMA_SHADE); break; } default: @@ -312,20 +310,19 @@ public: { for (std::list<uint64>::const_iterator itr = Channelers.begin(); itr != Channelers.end(); ++itr) { - if (Creature* Channeler = (Unit::GetCreature(*me, *itr))) + if (Creature* Channeler = ObjectAccessor::GetCreature(*me, *itr)) Channeler->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); } for (std::list<uint64>::const_iterator itr = Spawners.begin(); itr != Spawners.end(); ++itr) { - if (Creature* Spawner = (Unit::GetCreature(*me, *itr))) + if (Creature* Spawner = ObjectAccessor::GetCreature(*me, *itr)) Spawner->AI()->SetData(SETDATA_DATA, SETDATA_START_SPAWNING); } - break; } case EVENT_START_ATTACK_AKAMA: - me->GetMotionMaster()->MovePoint(0, ShadeWP.x, ShadeWP.y, ShadeWP.z ,false); + me->GetMotionMaster()->MovePoint(0, ShadeWP.x, ShadeWP.y, ShadeWP.z, false); events.ScheduleEvent(EVENT_START_ATTACK_AKAMA, 1000); break; case EVENT_ADD_THREAT: @@ -343,7 +340,7 @@ public: { HasKilledAkamaAndReseting = true; me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - instance->SetData(DATA_SHADEOFAKAMAEVENT, NOT_STARTED); + instance->SetBossState(DATA_SHADE_OF_AKAMA, NOT_STARTED); me->RemoveAllAurasExceptType(SPELL_AURA_DUMMY); me->DeleteThreatList(); me->CombatStop(); @@ -351,15 +348,15 @@ public: me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); combatStarted = false; - if (Creature* Akama = Unit::GetCreature((*me), akamaGUID)) + if (Creature* Akama = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_AKAMA_SHADE))) Akama->DespawnOrUnsummon(); for (std::list<uint64>::const_iterator itr = Channelers.begin(); itr != Channelers.end(); ++itr) - if (Creature* Channeler = (Unit::GetCreature(*me, *itr))) + if (Creature* Channeler = ObjectAccessor::GetCreature(*me, *itr)) Channeler->DespawnOrUnsummon(); for (std::list<uint64>::const_iterator itr = Spawners.begin(); itr != Spawners.end(); ++itr) - if (Creature* Spawner = (Unit::GetCreature(*me, *itr))) + if (Creature* Spawner = ObjectAccessor::GetCreature(*me, *itr)) Spawner->AI()->SetData(SETDATA_DATA, SETDATA_DESPAWN_ALL_SPAWNS); events.ScheduleEvent(EVENT_FIND_CHANNELERS_SPAWNERS, 10000); @@ -369,7 +366,7 @@ public: if (!akamaReached) { - if (Creature* Akama = Unit::GetCreature((*me), akamaGUID)) + if (Creature* Akama = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_AKAMA_SHADE))) { if (me->IsWithinDist(Akama, 2.0f, false)) { @@ -384,7 +381,7 @@ public: events.ScheduleEvent(EVENT_ADD_THREAT, 100); for (std::list<uint64>::const_iterator itr = Spawners.begin(); itr != Spawners.end(); ++itr) - if (Creature* Spawner = (Unit::GetCreature(*me, *itr))) + if (Creature* Spawner = ObjectAccessor::GetCreature(*me, *itr)) Spawner->AI()->SetData(SETDATA_DATA, SETDATA_STOP_SPAWNING); } } @@ -401,8 +398,6 @@ public: EventMap events; std::list<uint64> Channelers; std::list<uint64> Spawners; - uint64 akamaGUID; - uint64 ShadeGUID; bool akamaReached; bool combatStarted; bool HasKilledAkamaAndReseting; @@ -443,7 +438,7 @@ public: void JustDied(Unit* /*killer*/) OVERRIDE { - if (Creature* Shade = Unit::GetCreature((*me), ShadeGUID)) + if (Creature* Shade = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_SHADE_OF_AKAMA))) if (Shade->IsAlive()) CAST_AI(boss_shade_of_akama::boss_shade_of_akamaAI, Shade->AI())->HasKilledAkama = true; me->GetMotionMaster()->Clear(true); @@ -452,17 +447,14 @@ public: void SpellHit(Unit* /*caster*/, SpellInfo const* spell) OVERRIDE { - if (!StartCombat) + if (spell->Id == SPELL_THREAT && !StartCombat) { - if (spell->Id == SPELL_THREAT) - { - me->ClearUnitState(UNIT_STATE_ROOT); - me->RemoveAura(SPELL_AKAMA_SOUL_CHANNEL); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); - if (Creature* Shade = Unit::GetCreature((*me), ShadeGUID)) - Shade->RemoveAura(SPELL_AKAMA_SOUL_CHANNEL); - StartCombat = true; - } + me->ClearUnitState(UNIT_STATE_ROOT); + me->RemoveAura(SPELL_AKAMA_SOUL_CHANNEL); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); + if (Creature* Shade = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_SHADE_OF_AKAMA))) + Shade->RemoveAura(SPELL_AKAMA_SOUL_CHANNEL); + StartCombat = true; } } @@ -485,8 +477,7 @@ public: case EVENT_SHADE_START: if (instance) { - ShadeGUID = instance->GetData64(DATA_SHADEOFAKAMA); - instance->SetData(DATA_SHADEOFAKAMAEVENT, IN_PROGRESS); + instance->SetBossState(DATA_SHADE_OF_AKAMA, IN_PROGRESS); me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); me->RemoveAura(SPELL_STEALTH); me->SetWalk(true); @@ -550,7 +541,6 @@ public: private: InstanceScript* instance; EventMap events; - uint64 ShadeGUID; bool StartChannel; bool ShadeHasDied; bool StartCombat; @@ -587,17 +577,16 @@ public: me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); events.ScheduleEvent(EVENT_CHANNEL, 2000); - events.ScheduleEvent(EVENT_GET_SHADE_GUID, 1000); } void JustDied(Unit* /*killer*/) OVERRIDE { - if (Creature* Shade = (Unit::GetCreature((*me), ShadeGUID))) + if (Creature* Shade = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_SHADE_OF_AKAMA))) Shade->AI()->SetData(SETDATA_DATA, SETDATA_CHANNELER_DIED); } - void EnterCombat(Unit* /*who*/) OVERRIDE {} - void AttackStart(Unit* /*who*/) OVERRIDE {} + void EnterCombat(Unit* /*who*/) OVERRIDE { } + void AttackStart(Unit* /*who*/) OVERRIDE { } void UpdateAI(uint32 diff) OVERRIDE { @@ -608,7 +597,7 @@ public: switch (eventId) { case EVENT_CHANNEL: - if (Creature* Shade = (Unit::GetCreature((*me), ShadeGUID))) + if (Creature* Shade = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_SHADE_OF_AKAMA))) { if (Shade->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE)) DoCast(me, SPELL_SHADE_SOUL_CHANNEL); @@ -620,10 +609,6 @@ public: } events.ScheduleEvent(EVENT_CHANNEL, 2000); break; - case EVENT_GET_SHADE_GUID: - if (instance) - ShadeGUID = instance->GetData64(DATA_SHADEOFAKAMA); - break; default: break; } @@ -633,7 +618,6 @@ public: private: InstanceScript* instance; EventMap events; - uint64 ShadeGUID; }; CreatureAI* GetAI(Creature* creature) const OVERRIDE @@ -764,25 +748,19 @@ public: npc_ashtongue_sorcererAI(Creature* creature) : ScriptedAI(creature) { instance = creature->GetInstanceScript(); - - if (instance) - { - akamaGUID = instance->GetData64(DATA_AKAMA_SHADE); - shadeGUID = instance->GetData64(DATA_SHADEOFAKAMA); - } } void Reset() OVERRIDE { if (!startedBanishing) { - if (Creature* Shade = (Unit::GetCreature((*me), shadeGUID))) + if (Creature* Shade = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_SHADE_OF_AKAMA))) { if (Shade->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE)) me->GetMotionMaster()->MovePoint(0, Shade->GetPositionX(), Shade->GetPositionY(), Shade->GetPositionZ(), false); else { - if (Unit* target = me->GetCreature(*me, akamaGUID)) + if (Unit* target = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_AKAMA_SHADE))) AttackStart(target); } } @@ -795,7 +773,7 @@ public: void JustDied(Unit* /*killer*/) OVERRIDE { - if (Creature* Shade = (Unit::GetCreature((*me), shadeGUID))) + if (Creature* Shade = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_SHADE_OF_AKAMA))) Shade->AI()->SetData(SETDATA_DATA, SETDATA_CHANNELER_DIED); me->DespawnOrUnsummon(5000); } @@ -824,7 +802,7 @@ public: switch (eventId) { case EVENT_SORCERER_CHANNEL: - if (Creature* Shade = (Unit::GetCreature((*me), shadeGUID))) + if (Creature* Shade = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_SHADE_OF_AKAMA))) { if (Shade->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE)) { @@ -837,7 +815,7 @@ public: me->InterruptSpell(CURRENT_CHANNELED_SPELL); Shade->AI()->SetData(SETDATA_DATA, SETDATA_CHANNELER_DIED); switchToCombat = true; - if (Unit* target = me->GetCreature(*me, akamaGUID)) + if (Unit* target = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_AKAMA_SHADE))) AttackStart(target); } } @@ -849,7 +827,7 @@ public: if (!startedBanishing) { - Creature* Shade = Unit::GetCreature((*me), shadeGUID); + Creature* Shade = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_SHADE_OF_AKAMA)); if (me->IsWithinDist(Shade, 20.0f, false)) { me->StopMoving(); @@ -866,10 +844,7 @@ public: private: InstanceScript* instance; EventMap events; - uint64 akamaGUID; - uint64 shadeGUID; uint64 summonerGuid; - float distanceToShade; bool startedBanishing; bool switchToCombat; }; @@ -894,15 +869,13 @@ public: npc_ashtongue_defenderAI(Creature* creature) : ScriptedAI(creature) { instance = creature->GetInstanceScript(); - if (instance) - akamaGUID = instance->GetData64(DATA_AKAMA_SHADE); } void Reset() OVERRIDE { summonerGuid = 0; - if (Unit* target = me->GetCreature(*me, akamaGUID)) + if (Unit* target = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_AKAMA_SHADE))) AttackStart(target); } @@ -956,13 +929,13 @@ public: break; } } + DoMeleeAttackIfReady(); } private: InstanceScript* instance; EventMap events; - uint64 akamaGUID; uint64 summonerGuid; }; @@ -986,15 +959,13 @@ public: npc_ashtongue_rogueAI(Creature* creature) : ScriptedAI(creature) { instance = creature->GetInstanceScript(); - if (instance) - akamaGUID = instance->GetData64(DATA_AKAMA_SHADE); } void Reset() OVERRIDE { summonerGuid = 0; - if (Unit* target = me->GetCreature(*me, akamaGUID)) + if (Unit* target = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_AKAMA_SHADE))) AttackStart(target); } @@ -1038,13 +1009,13 @@ public: break; } } + DoMeleeAttackIfReady(); } private: InstanceScript* instance; EventMap events; - uint64 akamaGUID; uint64 summonerGuid; }; @@ -1068,15 +1039,13 @@ public: npc_ashtongue_elementalistAI(Creature* creature) : ScriptedAI(creature) { instance = creature->GetInstanceScript(); - if (instance) - akamaGUID = instance->GetData64(DATA_AKAMA_SHADE); } void Reset() OVERRIDE { summonerGuid = 0; - if (Unit* target = me->GetCreature(*me, akamaGUID)) + if (Unit* target = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_AKAMA_SHADE))) AttackStart(target); } @@ -1120,13 +1089,13 @@ public: break; } } + DoMeleeAttackIfReady(); } private: InstanceScript* instance; EventMap events; - uint64 akamaGUID; uint64 summonerGuid; }; @@ -1150,8 +1119,6 @@ public: npc_ashtongue_spiritbinderAI(Creature* creature) : ScriptedAI(creature) { instance = creature->GetInstanceScript(); - if (instance) - akamaGUID = instance->GetData64(DATA_AKAMA_SHADE); } void Reset() OVERRIDE @@ -1160,7 +1127,7 @@ public: chainHeal = false; summonerGuid = 0; - if (Unit* target = me->GetCreature(*me, akamaGUID)) + if (Unit* target = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_AKAMA_SHADE))) AttackStart(target); } @@ -1224,7 +1191,6 @@ public: private: InstanceScript* instance; EventMap events; - uint64 akamaGUID; uint64 summonerGuid; bool spiritMend; bool chainHeal; diff --git a/src/server/scripts/Outland/BlackTemple/boss_supremus.cpp b/src/server/scripts/Outland/BlackTemple/boss_supremus.cpp index fbc3e387e8e..94423f87bdf 100644 --- a/src/server/scripts/Outland/BlackTemple/boss_supremus.cpp +++ b/src/server/scripts/Outland/BlackTemple/boss_supremus.cpp @@ -31,7 +31,7 @@ EndScriptData */ enum Supremus { EMOTE_NEW_TARGET = 0, - EMOTE_PUNCH_GROUND = 1, //Talk(EMOTE_PUNCH_GROUND); + EMOTE_PUNCH_GROUND = 1, EMOTE_GROUND_CRACK = 2, //Spells @@ -110,11 +110,7 @@ public: if (instance) { if (me->IsAlive()) - { - instance->SetData(DATA_SUPREMUSEVENT, NOT_STARTED); - //ToggleDoors(true); - } - //else ToggleDoors(false); + instance->SetBossState(DATA_SUPREMUS, NOT_STARTED); } phase = 0; @@ -126,7 +122,7 @@ public: void EnterCombat(Unit* /*who*/) OVERRIDE { if (instance) - instance->SetData(DATA_SUPREMUSEVENT, IN_PROGRESS); + instance->SetBossState(DATA_SUPREMUS, IN_PROGRESS); ChangePhase(); events.ScheduleEvent(EVENT_BERSERK, 900000, GCD_CAST); @@ -163,10 +159,8 @@ public: void JustDied(Unit* /*killer*/) OVERRIDE { if (instance) - { - instance->SetData(DATA_SUPREMUSEVENT, DONE); - instance->HandleGameObject(instance->GetData64(DATA_GAMEOBJECT_SUPREMUS_DOORS), true); - } + instance->SetBossState(DATA_SUPREMUS, DONE); + summons.DespawnAll(); } diff --git a/src/server/scripts/Outland/BlackTemple/boss_teron_gorefiend.cpp b/src/server/scripts/Outland/BlackTemple/boss_teron_gorefiend.cpp index a861980ae42..c02954c7b2f 100644 --- a/src/server/scripts/Outland/BlackTemple/boss_teron_gorefiend.cpp +++ b/src/server/scripts/Outland/BlackTemple/boss_teron_gorefiend.cpp @@ -247,7 +247,7 @@ public: void Reset() OVERRIDE { if (instance) - instance->SetData(DATA_TERONGOREFIENDEVENT, NOT_STARTED); + instance->SetBossState(DATA_TERON_GOREFIEND, NOT_STARTED); IncinerateTimer = urand(20000, 31000); SummonDoomBlossomTimer = 12000; @@ -276,7 +276,7 @@ public: if (me->IsWithinDistInMap(who, VISIBLE_RANGE) && me->IsWithinLOSInMap(who)) { if (instance) - instance->SetData(DATA_TERONGOREFIENDEVENT, IN_PROGRESS); + instance->SetBossState(DATA_TERON_GOREFIEND, IN_PROGRESS); me->GetMotionMaster()->Clear(false); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); @@ -298,7 +298,7 @@ public: void JustDied(Unit* /*killer*/) OVERRIDE { if (instance) - instance->SetData(DATA_TERONGOREFIENDEVENT, DONE); + instance->SetBossState(DATA_TERON_GOREFIEND, DONE); Talk(SAY_DEATH); } diff --git a/src/server/scripts/Outland/BlackTemple/boss_warlord_najentus.cpp b/src/server/scripts/Outland/BlackTemple/boss_warlord_najentus.cpp index 532c66bb14a..1f4a36afad6 100644 --- a/src/server/scripts/Outland/BlackTemple/boss_warlord_najentus.cpp +++ b/src/server/scripts/Outland/BlackTemple/boss_warlord_najentus.cpp @@ -100,7 +100,7 @@ public: SpineTargetGUID = 0; if (instance) - instance->SetData(DATA_HIGHWARLORDNAJENTUSEVENT, NOT_STARTED); + instance->SetBossState(DATA_HIGH_WARLORD_NAJENTUS, NOT_STARTED); } void KilledUnit(Unit* /*victim*/) OVERRIDE @@ -112,7 +112,7 @@ public: void JustDied(Unit* /*killer*/) OVERRIDE { if (instance) - instance->SetData(DATA_HIGHWARLORDNAJENTUSEVENT, DONE); + instance->SetBossState(DATA_HIGH_WARLORD_NAJENTUS, DONE); Talk(SAY_DEATH); } @@ -130,7 +130,7 @@ public: void EnterCombat(Unit* /*who*/) OVERRIDE { if (instance) - instance->SetData(DATA_HIGHWARLORDNAJENTUSEVENT, IN_PROGRESS); + instance->SetBossState(DATA_HIGH_WARLORD_NAJENTUS, IN_PROGRESS); Talk(SAY_AGGRO); DoZoneInCombat(); @@ -228,7 +228,7 @@ public: bool OnGossipHello(Player* player, GameObject* go) OVERRIDE { if (InstanceScript* instance = go->GetInstanceScript()) - if (Creature* Najentus = Unit::GetCreature(*go, instance->GetData64(DATA_HIGHWARLORDNAJENTUS))) + if (Creature* Najentus = ObjectAccessor::GetCreature(*go, instance->GetData64(DATA_HIGH_WARLORD_NAJENTUS))) if (CAST_AI(boss_najentus::boss_najentusAI, Najentus->AI())->RemoveImpalingSpine()) { player->CastSpell(player, SPELL_CREATE_NAJENTUS_SPINE, true); diff --git a/src/server/scripts/Outland/BlackTemple/illidari_council.cpp b/src/server/scripts/Outland/BlackTemple/illidari_council.cpp index 290641437f3..05d19eb62bf 100644 --- a/src/server/scripts/Outland/BlackTemple/illidari_council.cpp +++ b/src/server/scripts/Outland/BlackTemple/illidari_council.cpp @@ -157,10 +157,10 @@ public: { if (InstanceScript* instance = me->GetInstanceScript()) { - Council[0] = instance->GetData64(DATA_GATHIOSTHESHATTERER); - Council[1] = instance->GetData64(DATA_VERASDARKSHADOW); - Council[2] = instance->GetData64(DATA_LADYMALANDE); - Council[3] = instance->GetData64(DATA_HIGHNETHERMANCERZEREVOR); + Council[0] = instance->GetData64(DATA_GATHIOS_THE_SHATTERER); + Council[1] = instance->GetData64(DATA_VERAS_DARKSHADOW); + Council[2] = instance->GetData64(DATA_LADY_MALANDE); + Council[3] = instance->GetData64(DATA_HIGH_NETHERMANCER_ZEREVOR); } else TC_LOG_ERROR(LOG_FILTER_TSCR, ERROR_INST_DATA); } @@ -265,8 +265,8 @@ public: if (instance) { - instance->SetData(DATA_ILLIDARICOUNCILEVENT, NOT_STARTED); - if (Creature* VoiceTrigger = (Unit::GetCreature(*me, instance->GetData64(DATA_BLOOD_ELF_COUNCIL_VOICE)))) + instance->SetBossState(DATA_ILLIDARI_COUNCIL, NOT_STARTED); + if (Creature* VoiceTrigger = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_BLOOD_ELF_COUNCIL_VOICE))) VoiceTrigger->AI()->EnterEvadeMode(); } @@ -289,13 +289,13 @@ public: if (target && target->IsAlive()) { - Council[0] = instance->GetData64(DATA_GATHIOSTHESHATTERER); - Council[1] = instance->GetData64(DATA_HIGHNETHERMANCERZEREVOR); - Council[2] = instance->GetData64(DATA_LADYMALANDE); - Council[3] = instance->GetData64(DATA_VERASDARKSHADOW); + Council[0] = instance->GetData64(DATA_GATHIOS_THE_SHATTERER); + Council[1] = instance->GetData64(DATA_HIGH_NETHERMANCER_ZEREVOR); + Council[2] = instance->GetData64(DATA_LADY_MALANDE); + Council[3] = instance->GetData64(DATA_VERAS_DARKSHADOW); // Start the event for the Voice Trigger - if (Creature* VoiceTrigger = (Unit::GetCreature(*me, instance->GetData64(DATA_BLOOD_ELF_COUNCIL_VOICE)))) + if (Creature* VoiceTrigger = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_BLOOD_ELF_COUNCIL_VOICE))) { CAST_AI(npc_blood_elf_council_voice_trigger::npc_blood_elf_council_voice_triggerAI, VoiceTrigger->AI())->LoadCouncilGUIDs(); CAST_AI(npc_blood_elf_council_voice_trigger::npc_blood_elf_council_voice_triggerAI, VoiceTrigger->AI())->EventStarted = true; @@ -305,13 +305,13 @@ public: { if (Council[i]) { - Unit* member = Unit::GetUnit(*me, Council[i]); - if (member && member->IsAlive()) - member->ToCreature()->AI()->AttackStart(target); + if (Creature* member = ObjectAccessor::GetCreature(*me, Council[i])) + if (member->IsAlive()) + member->AI()->AttackStart(target); } } - instance->SetData(DATA_ILLIDARICOUNCILEVENT, IN_PROGRESS); + instance->SetBossState(DATA_ILLIDARI_COUNCIL, IN_PROGRESS); EventBegun = true; } @@ -330,9 +330,9 @@ public: { if (instance) { - if (Creature* VoiceTrigger = (Unit::GetCreature(*me, instance->GetData64(DATA_BLOOD_ELF_COUNCIL_VOICE)))) + if (Creature* VoiceTrigger = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_BLOOD_ELF_COUNCIL_VOICE))) VoiceTrigger->DealDamage(VoiceTrigger, VoiceTrigger->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - instance->SetData(DATA_ILLIDARICOUNCILEVENT, DONE); + instance->SetBossState(DATA_ILLIDARI_COUNCIL, DONE); //me->SummonCreature(AKAMAID, 746.466980f, 304.394989f, 311.90208f, 6.272870f, TEMPSUMMON_DEAD_DESPAWN, 0); } me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); @@ -403,9 +403,8 @@ struct boss_illidari_councilAI : public ScriptedAI { if (instance) { - Creature* Controller = (Unit::GetCreature(*me, instance->GetData64(DATA_ILLIDARICOUNCIL))); - if (Controller) - CAST_AI(npc_illidari_council::npc_illidari_councilAI, Controller->AI())->StartEvent(who); + if (Creature* controller = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_ILLIDARI_COUNCIL))) + CAST_AI(npc_illidari_council::npc_illidari_councilAI, controller->AI())->StartEvent(who); } else { @@ -461,10 +460,10 @@ struct boss_illidari_councilAI : public ScriptedAI return; } - Council[0] = instance->GetData64(DATA_LADYMALANDE); - Council[1] = instance->GetData64(DATA_HIGHNETHERMANCERZEREVOR); - Council[2] = instance->GetData64(DATA_GATHIOSTHESHATTERER); - Council[3] = instance->GetData64(DATA_VERASDARKSHADOW); + Council[0] = instance->GetData64(DATA_LADY_MALANDE); + Council[1] = instance->GetData64(DATA_HIGH_NETHERMANCER_ZEREVOR); + Council[2] = instance->GetData64(DATA_GATHIOS_THE_SHATTERER); + Council[3] = instance->GetData64(DATA_VERAS_DARKSHADOW); LoadedGUIDs = true; } diff --git a/src/server/scripts/Outland/BlackTemple/instance_black_temple.cpp b/src/server/scripts/Outland/BlackTemple/instance_black_temple.cpp index bd70ce012ba..591f28a19f3 100644 --- a/src/server/scripts/Outland/BlackTemple/instance_black_temple.cpp +++ b/src/server/scripts/Outland/BlackTemple/instance_black_temple.cpp @@ -1,6 +1,5 @@ /* * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/> * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -16,382 +15,261 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -/* ScriptData -SDName: Instance_Black_Temple -SD%Complete: 100 -SDComment: Instance Data Scripts and functions to acquire mobs and set encounter status for use in various Black Temple Scripts -SDCategory: Black Temple -EndScriptData */ - #include "ScriptMgr.h" #include "InstanceScript.h" #include "black_temple.h" -#include "Player.h" -/* Black Temple encounters: -0 - High Warlord Naj'entus event -1 - Supremus Event -2 - Shade of Akama Event -3 - Teron Gorefiend Event -4 - Gurtogg Bloodboil Event -5 - Reliquary Of Souls Event -6 - Mother Shahraz Event -7 - Illidari Council Event -8 - Illidan Stormrage Event -*/ +DoorData const doorData[] = +{ + { GO_NAJENTUS_GATE, DATA_HIGH_WARLORD_NAJENTUS, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, + { GO_NAJENTUS_GATE, DATA_SUPREMUS, DOOR_TYPE_ROOM, BOUNDARY_NONE }, + { GO_SUPREMUS_GATE, DATA_SUPREMUS, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, + { GO_SHADE_OF_AKAMA_DOOR, DATA_SHADE_OF_AKAMA, DOOR_TYPE_ROOM, BOUNDARY_NONE }, + { GO_TERON_DOOR_1, DATA_TERON_GOREFIEND, DOOR_TYPE_ROOM, BOUNDARY_NONE }, + { GO_TERON_DOOR_2, DATA_TERON_GOREFIEND, DOOR_TYPE_ROOM, BOUNDARY_NONE }, + { GO_GURTOGG_DOOR, DATA_GURTOGG_BLOODBOIL, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, + { GO_TEMPLE_DOOR, DATA_RELIQUARY_OF_SOULS, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, + { GO_MOTHER_SHAHRAZ_DOOR, DATA_MOTHER_SHAHRAZ, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, + { GO_COUNCIL_DOOR_1, DATA_ILLIDARI_COUNCIL, DOOR_TYPE_ROOM, BOUNDARY_NONE }, + { GO_COUNCIL_DOOR_2, DATA_ILLIDARI_COUNCIL, DOOR_TYPE_ROOM, BOUNDARY_NONE }, + { 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE } // END +}; class instance_black_temple : public InstanceMapScript { -public: - instance_black_temple() : InstanceMapScript("instance_black_temple", 564) { } - - InstanceScript* GetInstanceScript(InstanceMap* map) const OVERRIDE - { - return new instance_black_temple_InstanceMapScript(map); - } - - struct instance_black_temple_InstanceMapScript : public InstanceScript - { - instance_black_temple_InstanceMapScript(Map* map) : InstanceScript(map) {} - - uint32 m_auiEncounter[EncounterCount]; - std::string str_data; - - uint64 Najentus; - uint64 Akama; // This is the Akama that starts the Illidan encounter. - uint64 Akama_Shade; // This is the Akama that starts the Shade of Akama encounter. - uint64 ShadeOfAkama; - uint64 Supremus; - uint64 LadyMalande; - uint64 GathiosTheShatterer; - uint64 HighNethermancerZerevor; - uint64 VerasDarkshadow; - uint64 IllidariCouncil; - uint64 BloodElfCouncilVoice; - uint64 IllidanStormrage; - - uint64 NajentusGate; - uint64 MainTempleDoors; - uint64 ShadeOfAkamaDoor; - uint64 CommonDoor;//Teron - uint64 TeronDoor; - uint64 GuurtogDoor; - uint64 MotherDoor; - uint64 TempleDoor;//Befor mother - uint64 CouncilDoor; - uint64 SimpleDoor;//council - uint64 IllidanGate; - uint64 IllidanDoor[2]; - - void Initialize() OVERRIDE - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + public: + instance_black_temple() : InstanceMapScript(BTScriptName, 564) { } - Najentus = 0; - Akama = 0; - Akama_Shade = 0; - ShadeOfAkama = 0; - Supremus = 0; - LadyMalande = 0; - GathiosTheShatterer = 0; - HighNethermancerZerevor = 0; - VerasDarkshadow = 0; - IllidariCouncil = 0; - BloodElfCouncilVoice = 0; - IllidanStormrage = 0; - - NajentusGate = 0; - MainTempleDoors = 0; - ShadeOfAkamaDoor = 0; - CommonDoor = 0; // teron - TeronDoor = 0; - GuurtogDoor = 0; - MotherDoor = 0; - TempleDoor = 0; - SimpleDoor = 0; // Bycouncil - CouncilDoor = 0; - IllidanGate = 0; - IllidanDoor[0] = 0; - IllidanDoor[1] = 0; - } - - bool IsEncounterInProgress() const OVERRIDE - { - for (uint8 i = 0; i < EncounterCount; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - return true; - - return false; - } - - Player* GetPlayerInMap() + struct instance_black_temple_InstanceMapScript : public InstanceScript { - Map::PlayerList const& players = instance->GetPlayers(); - - if (!players.isEmpty()) + instance_black_temple_InstanceMapScript(Map* map) : InstanceScript(map) { - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - { - if (Player* player = itr->GetSource()) - return player; - } + SetBossNumber(EncounterCount); + LoadDoorData(doorData); + + NajentusGUID = 0; + SupremusGUID = 0; + ShadeOfAkamaGUID = 0; + AkamaShadeGUID = 0; + AkamaGUID = 0; + GathiosTheShattererGUID = 0; + HighNethermancerZerevorGUID = 0; + LadyMalandeGUID = 0; + VerasDarkshadowGUID = 0; + IllidariCouncilGUID = 0; + BloodElfCouncilVoiceGUID = 0; + IllidanStormrageGUID = 0; + + IllidanGateGUID = 0; + + memset(IllidanDoorGUIDs, 0, 2 * sizeof(uint64)); } - TC_LOG_DEBUG(LOG_FILTER_TSCR, "Instance Black Temple: GetPlayerInMap, but PlayerList is empty!"); - return NULL; - } - - void OnCreatureCreate(Creature* creature) OVERRIDE - { - switch (creature->GetEntry()) + void OnCreatureCreate(Creature* creature) OVERRIDE { - case 22887: Najentus = creature->GetGUID(); break; - case 23089: Akama = creature->GetGUID(); break; - case 23191: Akama_Shade = creature->GetGUID(); break; - case 22841: ShadeOfAkama = creature->GetGUID(); break; - case 22898: Supremus = creature->GetGUID(); break; - case 22917: IllidanStormrage = creature->GetGUID(); break; - case 22949: GathiosTheShatterer = creature->GetGUID(); break; - case 22950: HighNethermancerZerevor = creature->GetGUID(); break; - case 22951: LadyMalande = creature->GetGUID(); break; - case 22952: VerasDarkshadow = creature->GetGUID(); break; - case 23426: IllidariCouncil = creature->GetGUID(); break; - case 23499: BloodElfCouncilVoice = creature->GetGUID(); break; + switch (creature->GetEntry()) + { + case NPC_HIGH_WARLORD_NAJENTUS: + NajentusGUID = creature->GetGUID(); + break; + case NPC_SUPREMUS: + SupremusGUID = creature->GetGUID(); + break; + case NPC_SHADE_OF_AKAMA: + ShadeOfAkamaGUID = creature->GetGUID(); + break; + case NPC_AKAMA_SHADE: + AkamaShadeGUID = creature->GetGUID(); + break; + case NPC_AKAMA: + AkamaGUID = creature->GetGUID(); + break; + case NPC_GATHIOS_THE_SHATTERER: + GathiosTheShattererGUID = creature->GetGUID(); + break; + case NPC_HIGH_NETHERMANCER_ZEREVOR: + HighNethermancerZerevorGUID = creature->GetGUID(); + break; + case NPC_LADY_MALANDE: + LadyMalandeGUID = creature->GetGUID(); + break; + case NPC_VERAS_DARKSHADOW: + VerasDarkshadowGUID = creature->GetGUID(); + break; + case NPC_ILLIDARI_COUNCIL: + IllidariCouncilGUID = creature->GetGUID(); + break; + case NPC_BLOOD_ELF_COUNCIL_VOICE: + BloodElfCouncilVoiceGUID = creature->GetGUID(); + break; + case NPC_ILLIDAN_STORMRAGE: + IllidanStormrageGUID = creature->GetGUID(); + break; + default: + break; + } } - } - void OnGameObjectCreate(GameObject* go) OVERRIDE - { - switch (go->GetEntry()) + void OnGameObjectCreate(GameObject* go) OVERRIDE { - case 185483: - NajentusGate = go->GetGUID(); // Gate past Naj'entus (at the entrance to Supermoose's courtyards) - if (m_auiEncounter[0] == DONE) - HandleGameObject(0, true, go); - break; - - case 185882: - MainTempleDoors = go->GetGUID(); // Main Temple Doors - right past Supermoose (Supremus) - if (m_auiEncounter[1] == DONE) - HandleGameObject(0, true, go); - break; - - case 185478: - ShadeOfAkamaDoor = go->GetGUID(); - break; - - case 185480: - CommonDoor = go->GetGUID(); - if (m_auiEncounter[3] == DONE) - HandleGameObject(0, true, go); - break; - - case 186153: - TeronDoor = go->GetGUID(); - if (m_auiEncounter[3] == DONE) - HandleGameObject(0, true, go); - break; - - case 185892: - GuurtogDoor = go->GetGUID(); - if (m_auiEncounter[4] == DONE) - HandleGameObject(0, true, go); - break; - - case 185479: - TempleDoor = go->GetGUID(); - if (m_auiEncounter[5] == DONE) - HandleGameObject(0, true, go); - break; - - case 185482: - MotherDoor = go->GetGUID(); - if (m_auiEncounter[6] == DONE) - HandleGameObject(0, true, go); - break; - - case 185481: - CouncilDoor = go->GetGUID(); - if (m_auiEncounter[7] == DONE) - HandleGameObject(0, true, go); - break; - - case 186152: - SimpleDoor = go->GetGUID(); - if (m_auiEncounter[7] == DONE) - HandleGameObject(0, true, go); - break; - - case 185905: - IllidanGate = go->GetGUID(); // Gate leading to Temple Summit - break; - - case 186261: - IllidanDoor[0] = go->GetGUID(); // Right door at Temple Summit - break; - - case 186262: - IllidanDoor[1] = go->GetGUID(); // Left door at Temple Summit - break; + switch (go->GetEntry()) + { + case GO_NAJENTUS_GATE: + case GO_SUPREMUS_GATE: + case GO_SHADE_OF_AKAMA_DOOR: + case GO_TERON_DOOR_1: + case GO_TERON_DOOR_2: + case GO_GURTOGG_DOOR: + case GO_TEMPLE_DOOR: + case GO_MOTHER_SHAHRAZ_DOOR: + case GO_COUNCIL_DOOR_1: + case GO_COUNCIL_DOOR_2: + AddDoor(go, true); + break; + case GO_ILLIDAN_GATE: + IllidanGateGUID = go->GetGUID(); + break; + case GO_ILLIDAN_DOOR_R: + IllidanDoorGUIDs[0] = go->GetGUID(); + break; + case GO_ILLIDAN_DOOR_L: + IllidanDoorGUIDs[1] = go->GetGUID(); + break; + default: + break; + } } - } - uint64 GetData64(uint32 identifier) const OVERRIDE - { - switch (identifier) + void OnGameObjectRemove(GameObject* go) OVERRIDE { - case DATA_HIGHWARLORDNAJENTUS: return Najentus; - case DATA_AKAMA: return Akama; - case DATA_AKAMA_SHADE: return Akama_Shade; - case DATA_SHADEOFAKAMA: return ShadeOfAkama; - case DATA_SUPREMUS: return Supremus; - case DATA_ILLIDANSTORMRAGE: return IllidanStormrage; - case DATA_GATHIOSTHESHATTERER: return GathiosTheShatterer; - case DATA_HIGHNETHERMANCERZEREVOR: return HighNethermancerZerevor; - case DATA_LADYMALANDE: return LadyMalande; - case DATA_VERASDARKSHADOW: return VerasDarkshadow; - case DATA_ILLIDARICOUNCIL: return IllidariCouncil; - case DATA_GAMEOBJECT_NAJENTUS_GATE: return NajentusGate; - case DATA_GAMEOBJECT_ILLIDAN_GATE: return IllidanGate; - case DATA_GAMEOBJECT_ILLIDAN_DOOR_R: return IllidanDoor[0]; - case DATA_GAMEOBJECT_ILLIDAN_DOOR_L: return IllidanDoor[1]; - case DATA_GAMEOBJECT_SUPREMUS_DOORS: return MainTempleDoors; - case DATA_BLOOD_ELF_COUNCIL_VOICE: return BloodElfCouncilVoice; + switch (go->GetEntry()) + { + case GO_NAJENTUS_GATE: + case GO_SUPREMUS_GATE: + case GO_SHADE_OF_AKAMA_DOOR: + case GO_TERON_DOOR_1: + case GO_TERON_DOOR_2: + case GO_GURTOGG_DOOR: + case GO_TEMPLE_DOOR: + case GO_MOTHER_SHAHRAZ_DOOR: + case GO_COUNCIL_DOOR_1: + case GO_COUNCIL_DOOR_2: + AddDoor(go, false); + break; + default: + break; + } } - return 0; - } - - void SetData(uint32 type, uint32 data) OVERRIDE - { - switch (type) + uint64 GetData64(uint32 type) const OVERRIDE { - case DATA_HIGHWARLORDNAJENTUSEVENT: - if (data == DONE) - HandleGameObject(NajentusGate, true); - m_auiEncounter[0] = data; - break; - case DATA_SUPREMUSEVENT: - if (data == DONE) - HandleGameObject(NajentusGate, true); - m_auiEncounter[1] = data; - break; - case DATA_SHADEOFAKAMAEVENT: - if (data == IN_PROGRESS) - HandleGameObject(ShadeOfAkamaDoor, false); - else - HandleGameObject(ShadeOfAkamaDoor, true); - m_auiEncounter[2] = data; - break; - case DATA_TERONGOREFIENDEVENT: - if (data == IN_PROGRESS) + switch (type) { - HandleGameObject(TeronDoor, false); - HandleGameObject(CommonDoor, false); + case DATA_HIGH_WARLORD_NAJENTUS: + return NajentusGUID; + case DATA_SUPREMUS: + return SupremusGUID; + case DATA_SHADE_OF_AKAMA: + return ShadeOfAkamaGUID; + case DATA_AKAMA_SHADE: + return AkamaShadeGUID; + case DATA_AKAMA: + return AkamaGUID; + case DATA_GATHIOS_THE_SHATTERER: + return GathiosTheShattererGUID; + case DATA_HIGH_NETHERMANCER_ZEREVOR: + return HighNethermancerZerevorGUID; + case DATA_LADY_MALANDE: + return LadyMalandeGUID; + case DATA_VERAS_DARKSHADOW: + return VerasDarkshadowGUID; + case DATA_ILLIDARI_COUNCIL: + return IllidariCouncilGUID; + case DATA_BLOOD_ELF_COUNCIL_VOICE: + return BloodElfCouncilVoiceGUID; + case DATA_ILLIDAN_STORMRAGE: + return IllidanStormrageGUID; + case DATA_GO_ILLIDAN_GATE: + return IllidanGateGUID; + case DATA_GO_ILLIDAN_DOOR_R: + return IllidanDoorGUIDs[0]; + case DATA_GO_ILLIDAN_DOOR_L: + return IllidanDoorGUIDs[1]; + default: + break; } - else - { - HandleGameObject(TeronDoor, true); - HandleGameObject(CommonDoor, true); - } - m_auiEncounter[3] = data; - break; - case DATA_GURTOGGBLOODBOILEVENT: - if (data == DONE) - HandleGameObject(GuurtogDoor, true); - m_auiEncounter[4] = data; - break; - case DATA_RELIQUARYOFSOULSEVENT: - if (data == DONE) - HandleGameObject(TempleDoor, true); - m_auiEncounter[5] = data; - break; - case DATA_MOTHERSHAHRAZEVENT: - if (data == DONE) - HandleGameObject(MotherDoor, true); - m_auiEncounter[6] = data; - break; - case DATA_ILLIDARICOUNCILEVENT: - if (data == IN_PROGRESS) - { - HandleGameObject(CouncilDoor, false); - HandleGameObject(SimpleDoor, false); - } - else - { - HandleGameObject(CouncilDoor, true); - HandleGameObject(SimpleDoor, true); - } - m_auiEncounter[7] = data; - break; - case DATA_ILLIDANSTORMRAGEEVENT: - m_auiEncounter[8] = data; - break; + + return 0; } - if (data == DONE) + std::string GetSaveData() OVERRIDE { OUT_SAVE_INST_DATA; std::ostringstream saveStream; - saveStream << m_auiEncounter[0] << ' ' << m_auiEncounter[1] << ' ' - << m_auiEncounter[2] << ' ' << m_auiEncounter[3] << ' ' << m_auiEncounter[4] - << ' ' << m_auiEncounter[5] << ' ' << m_auiEncounter[6] << ' ' << m_auiEncounter[7] - << ' ' << m_auiEncounter[8]; - - str_data = saveStream.str(); + saveStream << "B T " << GetBossSaveData(); - SaveToDB(); OUT_SAVE_INST_DATA_COMPLETE; + return saveStream.str(); } - } - uint32 GetData(uint32 type) const OVERRIDE - { - switch (type) + void Load(char const* str) OVERRIDE { - case DATA_HIGHWARLORDNAJENTUSEVENT: return m_auiEncounter[0]; - case DATA_SUPREMUSEVENT: return m_auiEncounter[1]; - case DATA_SHADEOFAKAMAEVENT: return m_auiEncounter[2]; - case DATA_TERONGOREFIENDEVENT: return m_auiEncounter[3]; - case DATA_GURTOGGBLOODBOILEVENT: return m_auiEncounter[4]; - case DATA_RELIQUARYOFSOULSEVENT: return m_auiEncounter[5]; - case DATA_MOTHERSHAHRAZEVENT: return m_auiEncounter[6]; - case DATA_ILLIDARICOUNCILEVENT: return m_auiEncounter[7]; - case DATA_ILLIDANSTORMRAGEEVENT: return m_auiEncounter[8]; - } + if (!str) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } - return 0; - } + OUT_LOAD_INST_DATA(str); - std::string GetSaveData() OVERRIDE - { - return str_data; - } + char dataHead1, dataHead2; - void Load(const char* in) OVERRIDE - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; + std::istringstream loadStream(str); + loadStream >> dataHead1 >> dataHead2; + + if (dataHead1 == 'B' && dataHead2 == 'T') + { + for (uint32 i = 0; i < EncounterCount; ++i) + { + uint32 tmpState; + loadStream >> tmpState; + if (tmpState == IN_PROGRESS || tmpState > SPECIAL) + tmpState = NOT_STARTED; + SetBossState(i, EncounterState(tmpState)); + } + } + else + OUT_LOAD_INST_DATA_FAIL; + + OUT_LOAD_INST_DATA_COMPLETE; } - OUT_LOAD_INST_DATA(in); + protected: + uint64 NajentusGUID; + uint64 SupremusGUID; + uint64 ShadeOfAkamaGUID; + uint64 AkamaShadeGUID; + uint64 AkamaGUID; - std::istringstream loadStream(in); - loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] - >> m_auiEncounter[3] >> m_auiEncounter[4] >> m_auiEncounter[5] >> m_auiEncounter[6] - >> m_auiEncounter[7] >> m_auiEncounter[8]; + uint64 GathiosTheShattererGUID; + uint64 HighNethermancerZerevorGUID; + uint64 LadyMalandeGUID; + uint64 VerasDarkshadowGUID; - for (uint8 i = 0; i < EncounterCount; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - m_auiEncounter[i] = NOT_STARTED; + uint64 IllidariCouncilGUID; + uint64 BloodElfCouncilVoiceGUID; - OUT_LOAD_INST_DATA_COMPLETE; - } - }; + uint64 IllidanStormrageGUID; + + uint64 IllidanGateGUID; + uint64 IllidanDoorGUIDs[2]; + }; + InstanceScript* GetInstanceScript(InstanceMap* map) const OVERRIDE + { + return new instance_black_temple_InstanceMapScript(map); + } }; void AddSC_instance_black_temple() diff --git a/src/server/scripts/Outland/CMakeLists.txt b/src/server/scripts/Outland/CMakeLists.txt index d7b863da0db..84cbbc3c30c 100644 --- a/src/server/scripts/Outland/CMakeLists.txt +++ b/src/server/scripts/Outland/CMakeLists.txt @@ -42,8 +42,10 @@ set(scripts_STAT_SRCS Outland/CoilfangReservoir/SerpentShrine/boss_leotheras_the_blind.cpp Outland/CoilfangReservoir/SerpentShrine/boss_lurker_below.cpp Outland/CoilfangReservoir/SerpentShrine/boss_morogrim_tidewalker.cpp - Outland/CoilfangReservoir/underbog/boss_hungarfen.cpp - Outland/CoilfangReservoir/underbog/boss_the_black_stalker.cpp + Outland/CoilfangReservoir/TheSlavePens/instance_the_slave_pens.cpp + Outland/CoilfangReservoir/TheUnderbog/boss_hungarfen.cpp + Outland/CoilfangReservoir/TheUnderbog/boss_the_black_stalker.cpp + Outland/CoilfangReservoir/TheUnderbog/instance_the_underbog.cpp Outland/zone_shattrath_city.cpp Outland/TempestKeep/Mechanar/boss_mechano_lord_capacitus.cpp Outland/TempestKeep/Mechanar/boss_pathaleon_the_calculator.cpp @@ -72,19 +74,23 @@ set(scripts_STAT_SRCS Outland/TempestKeep/arcatraz/arcatraz.cpp Outland/Auchindoun/AuchenaiCrypts/boss_shirrak_the_dead_watcher.cpp Outland/Auchindoun/AuchenaiCrypts/boss_exarch_maladaar.cpp + Outland/Auchindoun/AuchenaiCrypts/instance_auchenai_crypts.cpp + Outland/Auchindoun/AuchenaiCrypts/auchenai_crypts.h Outland/Auchindoun/ManaTombs/boss_pandemonius.cpp Outland/Auchindoun/ManaTombs/boss_nexusprince_shaffar.cpp - Outland/Auchindoun/SethekkHalls/boss_tailonking_ikiss.cpp + Outland/Auchindoun/ManaTombs/instance_mana_tombs.cpp + Outland/Auchindoun/ManaTombs/mana_tombs.h Outland/Auchindoun/SethekkHalls/boss_darkweaver_syth.cpp + Outland/Auchindoun/SethekkHalls/boss_tailonking_ikiss.cpp Outland/Auchindoun/SethekkHalls/boss_anzu.cpp Outland/Auchindoun/SethekkHalls/instance_sethekk_halls.cpp Outland/Auchindoun/SethekkHalls/sethekk_halls.h - Outland/Auchindoun/ShadowLabyrinth/boss_murmur.cpp Outland/Auchindoun/ShadowLabyrinth/boss_ambassador_hellmaw.cpp Outland/Auchindoun/ShadowLabyrinth/boss_blackheart_the_inciter.cpp + Outland/Auchindoun/ShadowLabyrinth/boss_grandmaster_vorpil.cpp + Outland/Auchindoun/ShadowLabyrinth/boss_murmur.cpp Outland/Auchindoun/ShadowLabyrinth/instance_shadow_labyrinth.cpp Outland/Auchindoun/ShadowLabyrinth/shadow_labyrinth.h - Outland/Auchindoun/ShadowLabyrinth/boss_grandmaster_vorpil.cpp Outland/boss_doomwalker.cpp Outland/zone_terokkar_forest.cpp Outland/zone_hellfire_peninsula.cpp diff --git a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_hydross_the_unstable.cpp b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_hydross_the_unstable.cpp index db270c943e5..d6205cb3ec7 100644 --- a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_hydross_the_unstable.cpp +++ b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_hydross_the_unstable.cpp @@ -94,6 +94,8 @@ public: boss_hydross_the_unstableAI(Creature* creature) : ScriptedAI(creature), Summons(me) { instance = creature->GetInstanceScript(); + beams[0] = 0; + beams[1] = 0; } InstanceScript* instance; @@ -159,10 +161,9 @@ public: } void DeSummonBeams() { - for (uint8 i=0; i<2; ++i) + for (uint8 i = 0; i < 2; ++i) { - Creature* mob = Unit::GetCreature(*me, beams[i]); - if (mob) + if (Creature* mob = Unit::GetCreature(*me, beams[i])) { mob->setDeathState(DEAD); mob->RemoveCorpse(); diff --git a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lady_vashj.cpp b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lady_vashj.cpp index 4499cb98475..ff66dcb550c 100644 --- a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lady_vashj.cpp +++ b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lady_vashj.cpp @@ -151,6 +151,8 @@ public: Intro = false; JustCreated = true; creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); // set it only once on Creature create (no need do intro if wiped) + for (uint8 i = 0; i < 4; ++i) + ShieldGeneratorChannel[i] = 0; } InstanceScript* instance; @@ -201,17 +203,20 @@ public: JustCreated = false; } else CanAttack = true; - for (uint8 i = 0; i < 4; ++i) - if (Unit* remo = Unit::GetUnit(*me, ShieldGeneratorChannel[i])) - remo->setDeathState(JUST_DIED); + { + if (ShieldGeneratorChannel[i]) + { + if (Unit* remo = Unit::GetUnit(*me, ShieldGeneratorChannel[i])) + { + remo->setDeathState(JUST_DIED); + ShieldGeneratorChannel[i] = 0; + } + } + } if (instance) instance->SetData(DATA_LADYVASHJEVENT, NOT_STARTED); - ShieldGeneratorChannel[0] = 0; - ShieldGeneratorChannel[1] = 0; - ShieldGeneratorChannel[2] = 0; - ShieldGeneratorChannel[3] = 0; me->SetCorpseDelay(1000*60*60); } diff --git a/src/server/scripts/Outland/CoilfangReservoir/TheSlavePens/instance_the_slave_pens.cpp b/src/server/scripts/Outland/CoilfangReservoir/TheSlavePens/instance_the_slave_pens.cpp new file mode 100644 index 00000000000..3475e83f02c --- /dev/null +++ b/src/server/scripts/Outland/CoilfangReservoir/TheSlavePens/instance_the_slave_pens.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2008-2013 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/>. + */ + +/* +This placeholder for the instance is needed for dungeon finding to be able +to give credit after the boss defined in lastEncounterDungeon is killed. +Without it, the party doing random dungeon won't get satchel of spoils and +gets instead the deserter debuff. +*/ + +#include "ScriptMgr.h" +#include "InstanceScript.h" + +class instance_the_slave_pens : public InstanceMapScript +{ +public: + instance_the_slave_pens() : InstanceMapScript("instance_the_slave_pens", 547) { } + + InstanceScript* GetInstanceScript(InstanceMap* map) const OVERRIDE + { + return new instance_the_slave_pens_InstanceMapScript(map); + } + + struct instance_the_slave_pens_InstanceMapScript : public InstanceScript + { + instance_the_slave_pens_InstanceMapScript(Map* map) : InstanceScript(map) {} + }; +}; + +void AddSC_instance_the_slave_pens() +{ + new instance_the_slave_pens(); +} diff --git a/src/server/scripts/Outland/CoilfangReservoir/underbog/boss_hungarfen.cpp b/src/server/scripts/Outland/CoilfangReservoir/TheUnderbog/boss_hungarfen.cpp index 0db48d83ebb..0db48d83ebb 100644 --- a/src/server/scripts/Outland/CoilfangReservoir/underbog/boss_hungarfen.cpp +++ b/src/server/scripts/Outland/CoilfangReservoir/TheUnderbog/boss_hungarfen.cpp diff --git a/src/server/scripts/Outland/CoilfangReservoir/underbog/boss_the_black_stalker.cpp b/src/server/scripts/Outland/CoilfangReservoir/TheUnderbog/boss_the_black_stalker.cpp index c22dedd269e..c22dedd269e 100644 --- a/src/server/scripts/Outland/CoilfangReservoir/underbog/boss_the_black_stalker.cpp +++ b/src/server/scripts/Outland/CoilfangReservoir/TheUnderbog/boss_the_black_stalker.cpp diff --git a/src/server/scripts/Outland/CoilfangReservoir/TheUnderbog/instance_the_underbog.cpp b/src/server/scripts/Outland/CoilfangReservoir/TheUnderbog/instance_the_underbog.cpp new file mode 100644 index 00000000000..0a305edf23f --- /dev/null +++ b/src/server/scripts/Outland/CoilfangReservoir/TheUnderbog/instance_the_underbog.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2008-2013 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/>. + */ + +/* +This placeholder for the instance is needed for dungeon finding to be able +to give credit after the boss defined in lastEncounterDungeon is killed. +Without it, the party doing random dungeon won't get satchel of spoils and +gets instead the deserter debuff. +*/ + +#include "ScriptMgr.h" +#include "InstanceScript.h" + +class instance_the_underbog : public InstanceMapScript +{ +public: + instance_the_underbog() : InstanceMapScript("instance_the_underbog", 546) { } + + InstanceScript* GetInstanceScript(InstanceMap* map) const OVERRIDE + { + return new instance_the_underbog_InstanceMapScript(map); + } + + struct instance_the_underbog_InstanceMapScript : public InstanceScript + { + instance_the_underbog_InstanceMapScript(Map* map) : InstanceScript(map) {} + }; +}; + +void AddSC_instance_the_underbog() +{ + new instance_the_underbog(); +} diff --git a/src/server/scripts/Outland/GruulsLair/boss_gruul.cpp b/src/server/scripts/Outland/GruulsLair/boss_gruul.cpp index 31f854803bc..0ae86f7c455 100644 --- a/src/server/scripts/Outland/GruulsLair/boss_gruul.cpp +++ b/src/server/scripts/Outland/GruulsLair/boss_gruul.cpp @@ -43,215 +43,217 @@ enum Spells { SPELL_GROWTH = 36300, SPELL_CAVE_IN = 36240, - SPELL_GROUND_SLAM = 33525, //AoE Ground Slam applying Ground Slam to everyone with a script effect (most likely the knock back, we can code it to a set knockback) + SPELL_GROUND_SLAM = 33525, // AoE Ground Slam applying Ground Slam to everyone with a script effect (most likely the knock back, we can code it to a set knockback) SPELL_REVERBERATION = 36297, SPELL_SHATTER = 33654, SPELL_SHATTER_EFFECT = 33671, SPELL_HURTFUL_STRIKE = 33813, - SPELL_STONED = 33652, //Spell is self cast by target + SPELL_STONED = 33652, // Spell is self cast by target SPELL_MAGNETIC_PULL = 28337, - SPELL_KNOCK_BACK = 24199, //Knockback spell until correct implementation is made + SPELL_KNOCK_BACK = 24199, // Knockback spell until correct implementation is made }; -class boss_gruul : public CreatureScript +enum Events { -public: - boss_gruul() : CreatureScript("boss_gruul") { } + EVENT_GROWTH = 1, + EVENT_CAVE_IN, + EVENT_CAVE_IN_STATIC, + EVENT_GROUND_SLAM, + EVENT_HURTFUL_STRIKE, + EVENT_REVERBERATION +}; - CreatureAI* GetAI(Creature* creature) const OVERRIDE - { - return new boss_gruulAI(creature); - } +class boss_gruul : public CreatureScript +{ + public: + boss_gruul() : CreatureScript("boss_gruul") { } - struct boss_gruulAI : public ScriptedAI - { - boss_gruulAI(Creature* creature) : ScriptedAI(creature) + struct boss_gruulAI : public BossAI { - instance = creature->GetInstanceScript(); - } - - InstanceScript* instance; - - uint32 m_uiGrowth_Timer; - uint32 m_uiCaveIn_Timer; - uint32 m_uiCaveIn_StaticTimer; - uint32 m_uiGroundSlamTimer; - uint32 m_uiHurtfulStrike_Timer; - uint32 m_uiReverberation_Timer; + boss_gruulAI(Creature* creature) : BossAI(creature, DATA_GRUUL) { } - bool m_bPerformingGroundSlam; + uint32 m_uiGrowth_Timer; + uint32 m_uiCaveIn_Timer; + uint32 m_uiCaveIn_StaticTimer; + uint32 m_uiGroundSlamTimer; + uint32 m_uiHurtfulStrike_Timer; + uint32 m_uiReverberation_Timer; - void Reset() OVERRIDE - { - m_uiGrowth_Timer= 30000; - m_uiCaveIn_Timer= 27000; - m_uiCaveIn_StaticTimer = 30000; - m_uiGroundSlamTimer= 35000; - m_bPerformingGroundSlam= false; - m_uiHurtfulStrike_Timer= 8000; - m_uiReverberation_Timer= 60000+45000; - - if (instance) - instance->SetData(DATA_GRUULEVENT, NOT_STARTED); - } + bool m_bPerformingGroundSlam; - void EnterCombat(Unit* /*who*/) OVERRIDE - { - Talk(SAY_AGGRO); - - if (instance) - instance->SetData(DATA_GRUULEVENT, IN_PROGRESS); - } + void Reset() OVERRIDE + { + _Reset(); + m_uiGrowth_Timer= 30000; + m_uiCaveIn_Timer= 27000; + m_uiCaveIn_StaticTimer = 30000; + m_uiGroundSlamTimer= 35000; + m_bPerformingGroundSlam= false; + m_uiHurtfulStrike_Timer= 8000; + m_uiReverberation_Timer= 60000+45000; + } - void KilledUnit(Unit* /*victim*/) OVERRIDE - { - Talk(SAY_SLAY); - } + void EnterCombat(Unit* /*who*/) OVERRIDE + { + _EnterCombat(); + Talk(SAY_AGGRO); + } - void JustDied(Unit* /*killer*/) OVERRIDE - { - Talk(SAY_DEATH); + void KilledUnit(Unit* who) OVERRIDE + { + if (who->GetTypeId() == TYPEID_PLAYER) + Talk(SAY_SLAY); + } - if (instance) + void JustDied(Unit* /*killer*/) OVERRIDE { - instance->SetData(DATA_GRUULEVENT, DONE); - instance->HandleGameObject(instance->GetData64(DATA_GRUULDOOR), true); // Open the encounter door + _JustDied(); + Talk(SAY_DEATH); } - } - void SpellHitTarget(Unit* target, const SpellInfo* pSpell) OVERRIDE - { - //This to emulate effect1 (77) of SPELL_GROUND_SLAM, knock back to any direction - //It's initially wrong, since this will cause fall damage, which is by comments, not intended. - if (pSpell->Id == SPELL_GROUND_SLAM) + void SpellHitTarget(Unit* target, const SpellInfo* pSpell) OVERRIDE { - if (target->GetTypeId() == TYPEID_PLAYER) + //This to emulate effect1 (77) of SPELL_GROUND_SLAM, knock back to any direction + //It's initially wrong, since this will cause fall damage, which is by comments, not intended. + if (pSpell->Id == SPELL_GROUND_SLAM) { - switch (urand(0, 1)) + if (target->GetTypeId() == TYPEID_PLAYER) { - case 0: - target->CastSpell(target, SPELL_MAGNETIC_PULL, true, NULL, NULL, me->GetGUID()); - break; - - case 1: - target->CastSpell(target, SPELL_KNOCK_BACK, true, NULL, NULL, me->GetGUID()); - break; + switch (urand(0, 1)) + { + case 0: + target->CastSpell(target, SPELL_MAGNETIC_PULL, true, NULL, NULL, me->GetGUID()); + break; + + case 1: + target->CastSpell(target, SPELL_KNOCK_BACK, true, NULL, NULL, me->GetGUID()); + break; + } } } - } - //this part should be in the core - if (pSpell->Id == SPELL_SHATTER) - { - /// @todo use eventmap to kill this stuff - //clear this, if we are still performing - if (m_bPerformingGroundSlam) + //this part should be in the core + if (pSpell->Id == SPELL_SHATTER) { - m_bPerformingGroundSlam = false; - - //and correct movement, if not already - if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() != CHASE_MOTION_TYPE) + /// @todo use eventmap to kill this stuff + //clear this, if we are still performing + if (m_bPerformingGroundSlam) { - if (me->GetVictim()) - me->GetMotionMaster()->MoveChase(me->GetVictim()); + m_bPerformingGroundSlam = false; + + //and correct movement, if not already + if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() != CHASE_MOTION_TYPE) + { + if (me->GetVictim()) + me->GetMotionMaster()->MoveChase(me->GetVictim()); + } } } } - } - - void UpdateAI(uint32 uiDiff) OVERRIDE - { - //Return since we have no target - if (!UpdateVictim()) - return; - // Growth - // Gruul can cast this spell up to 30 times - if (m_uiGrowth_Timer <= uiDiff) + void UpdateAI(uint32 diff) OVERRIDE { - Talk(EMOTE_GROW); - DoCast(me, SPELL_GROWTH); - m_uiGrowth_Timer = 30000; - } - else - m_uiGrowth_Timer -= uiDiff; + if (!UpdateVictim()) + return; - if (m_bPerformingGroundSlam) - { - if (m_uiGroundSlamTimer <= uiDiff) - { - m_uiGroundSlamTimer =120000; - m_uiHurtfulStrike_Timer= 8000; + events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; - if (m_uiReverberation_Timer < 10000) //Give a little time to the players to undo the damage from shatter - m_uiReverberation_Timer += 10000; + /// @todo: convert this shit to eventmap - DoCast(me, SPELL_SHATTER); + // Growth + // Gruul can cast this spell up to 30 times + if (m_uiGrowth_Timer <= diff) + { + Talk(EMOTE_GROW); + DoCast(me, SPELL_GROWTH); + m_uiGrowth_Timer = 30000; } else - m_uiGroundSlamTimer -= uiDiff; - } - else - { - // Hurtful Strike - if (m_uiHurtfulStrike_Timer <= uiDiff) + m_uiGrowth_Timer -= diff; + + if (m_bPerformingGroundSlam) { - Unit* target = SelectTarget(SELECT_TARGET_TOPAGGRO, 1); + if (m_uiGroundSlamTimer <= diff) + { + m_uiGroundSlamTimer =120000; + m_uiHurtfulStrike_Timer= 8000; - if (target && me->IsWithinMeleeRange(me->GetVictim())) - DoCast(target, SPELL_HURTFUL_STRIKE); - else - DoCastVictim(SPELL_HURTFUL_STRIKE); + if (m_uiReverberation_Timer < 10000) //Give a little time to the players to undo the damage from shatter + m_uiReverberation_Timer += 10000; - m_uiHurtfulStrike_Timer= 8000; + DoCast(me, SPELL_SHATTER); + } + else + m_uiGroundSlamTimer -= diff; } else - m_uiHurtfulStrike_Timer -= uiDiff; - - // Reverberation - if (m_uiReverberation_Timer <= uiDiff) { - DoCastVictim(SPELL_REVERBERATION, true); - m_uiReverberation_Timer = urand(15000, 25000); - } - else - m_uiReverberation_Timer -= uiDiff; + // Hurtful Strike + if (m_uiHurtfulStrike_Timer <= diff) + { + Unit* target = SelectTarget(SELECT_TARGET_TOPAGGRO, 1); - // Cave In - if (m_uiCaveIn_Timer <= uiDiff) - { - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) - DoCast(target, SPELL_CAVE_IN); + if (target && me->IsWithinMeleeRange(me->GetVictim())) + DoCast(target, SPELL_HURTFUL_STRIKE); + else + DoCastVictim(SPELL_HURTFUL_STRIKE); - if (m_uiCaveIn_StaticTimer >= 4000) - m_uiCaveIn_StaticTimer -= 2000; + m_uiHurtfulStrike_Timer= 8000; + } + else + m_uiHurtfulStrike_Timer -= diff; - m_uiCaveIn_Timer = m_uiCaveIn_StaticTimer; - } - else - m_uiCaveIn_Timer -= uiDiff; + // Reverberation + if (m_uiReverberation_Timer <= diff) + { + DoCastVictim(SPELL_REVERBERATION, true); + m_uiReverberation_Timer = urand(15000, 25000); + } + else + m_uiReverberation_Timer -= diff; - // Ground Slam, Gronn Lord's Grasp, Stoned, Shatter - if (m_uiGroundSlamTimer <= uiDiff) - { - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MoveIdle(); + // Cave In + if (m_uiCaveIn_Timer <= diff) + { + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) + DoCast(target, SPELL_CAVE_IN); - m_bPerformingGroundSlam= true; - m_uiGroundSlamTimer = 10000; + if (m_uiCaveIn_StaticTimer >= 4000) + m_uiCaveIn_StaticTimer -= 2000; - DoCast(me, SPELL_GROUND_SLAM); - } - else - m_uiGroundSlamTimer -= uiDiff; + m_uiCaveIn_Timer = m_uiCaveIn_StaticTimer; + } + else + m_uiCaveIn_Timer -= diff; + + // Ground Slam, Gronn Lord's Grasp, Stoned, Shatter + if (m_uiGroundSlamTimer <= diff) + { + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MoveIdle(); - DoMeleeAttackIfReady(); + m_bPerformingGroundSlam= true; + m_uiGroundSlamTimer = 10000; + + DoCast(me, SPELL_GROUND_SLAM); + } + else + m_uiGroundSlamTimer -= diff; + + DoMeleeAttackIfReady(); + } } - } - }; + }; + CreatureAI* GetAI(Creature* creature) const OVERRIDE + { + return GetGruulsLairAI<boss_gruulAI>(creature); + } }; class spell_gruul_shatter : public SpellScriptLoader diff --git a/src/server/scripts/Outland/GruulsLair/boss_high_king_maulgar.cpp b/src/server/scripts/Outland/GruulsLair/boss_high_king_maulgar.cpp index d216c0b02ee..dd44d764987 100644 --- a/src/server/scripts/Outland/GruulsLair/boss_high_king_maulgar.cpp +++ b/src/server/scripts/Outland/GruulsLair/boss_high_king_maulgar.cpp @@ -49,79 +49,35 @@ enum HighKingMaulgar SPELL_DEATH_COIL = 33130, SPELL_SUMMON_WFH = 33131, - //Kiggler the Craed + // Kiggler the Craed SPELL_GREATER_POLYMORPH = 33173, SPELL_LIGHTNING_BOLT = 36152, SPELL_ARCANE_SHOCK = 33175, SPELL_ARCANE_EXPLOSION = 33237, - //Blindeye the Seer + // Blindeye the Seer SPELL_GREATER_PW_SHIELD = 33147, SPELL_HEAL = 33144, SPELL_PRAYER_OH = 33152, - //Krosh Firehand + // Krosh Firehand SPELL_GREATER_FIREBALL = 33051, SPELL_SPELLSHIELD = 33054, - SPELL_BLAST_WAVE = 33061 -}; + SPELL_BLAST_WAVE = 33061, -bool CheckAllBossDied(InstanceScript* instance, Creature* me) -{ - if (!instance || !me) - return false; - - uint64 MaulgarGUID = 0; - uint64 KigglerGUID = 0; - uint64 BlindeyeGUID = 0; - uint64 OlmGUID = 0; - uint64 KroshGUID = 0; - - Creature* Maulgar = NULL; - Creature* Kiggler = NULL; - Creature* Blindeye = NULL; - Creature* Olm = NULL; - Creature* Krosh = NULL; - - MaulgarGUID = instance->GetData64(DATA_MAULGAR); - KigglerGUID = instance->GetData64(DATA_KIGGLERTHECRAZED); - BlindeyeGUID = instance->GetData64(DATA_BLINDEYETHESEER); - OlmGUID = instance->GetData64(DATA_OLMTHESUMMONER); - KroshGUID = instance->GetData64(DATA_KROSHFIREHAND); - - Maulgar = (Unit::GetCreature((*me), MaulgarGUID)); - Kiggler = (Unit::GetCreature((*me), KigglerGUID)); - Blindeye = (Unit::GetCreature((*me), BlindeyeGUID)); - Olm = (Unit::GetCreature((*me), OlmGUID)); - Krosh = (Unit::GetCreature((*me), KroshGUID)); - - if (!Maulgar || !Kiggler || !Blindeye || !Olm || !Krosh) - return false; - - if (!Maulgar->IsAlive() && !Kiggler->IsAlive() && !Blindeye->IsAlive() && !Olm->IsAlive() && !Krosh->IsAlive()) - return true; - - return false; -} + ACTION_ADD_DEATH = 1 +}; -//High King Maulgar AI class boss_high_king_maulgar : public CreatureScript { public: boss_high_king_maulgar() : CreatureScript("boss_high_king_maulgar") { } - CreatureAI* GetAI(Creature* creature) const OVERRIDE - { - return new boss_high_king_maulgarAI(creature); - } - struct boss_high_king_maulgarAI : public ScriptedAI { boss_high_king_maulgarAI(Creature* creature) : ScriptedAI(creature) { instance = creature->GetInstanceScript(); - for (uint8 i = 0; i < 4; ++i) - Council[i] = 0; } InstanceScript* instance; @@ -134,8 +90,6 @@ public: bool Phase2; - uint64 Council[4]; - void Reset() OVERRIDE { ArcingSmash_Timer = 10000; @@ -148,23 +102,7 @@ public: Phase2 = false; - Creature* creature = NULL; - for (uint8 i = 0; i < 4; ++i) - { - if (Council[i]) - { - creature = (Unit::GetCreature((*me), Council[i])); - if (creature && !creature->IsAlive()) - { - creature->Respawn(); - creature->AI()->EnterEvadeMode(); - } - } - } - - //reset encounter - if (instance) - instance->SetData(DATA_MAULGAREVENT, NOT_STARTED); + instance->SetBossState(DATA_MAULGAR, NOT_STARTED); } void KilledUnit(Unit* /*victim*/) OVERRIDE @@ -176,72 +114,27 @@ public: { Talk(SAY_DEATH); - if (CheckAllBossDied(instance, me)) - instance->SetData(DATA_MAULGAREVENT, DONE); - } - - void AddDeath() - { - Talk(SAY_OGRE_DEATH); - } - - void EnterCombat(Unit* who) OVERRIDE - { - StartEvent(who); + instance->SetBossState(DATA_MAULGAR, DONE); } - void GetCouncil() + void DoAction(int32 actionId) { - if (instance) - { - //get council member's guid to respawn them if needed - Council[0] = instance->GetData64(DATA_KIGGLERTHECRAZED); - Council[1] = instance->GetData64(DATA_BLINDEYETHESEER); - Council[2] = instance->GetData64(DATA_OLMTHESUMMONER); - Council[3] = instance->GetData64(DATA_KROSHFIREHAND); - } + if (actionId == ACTION_ADD_DEATH) + Talk(SAY_OGRE_DEATH); } - void StartEvent(Unit* who) + void EnterCombat(Unit* /*who*/) OVERRIDE { - if (!instance) - return; - - GetCouncil(); - - Talk(SAY_AGGRO); - - instance->SetData64(DATA_MAULGAREVENT_TANK, who->GetGUID()); - instance->SetData(DATA_MAULGAREVENT, IN_PROGRESS); - DoZoneInCombat(); + instance->SetBossState(DATA_MAULGAR, IN_PROGRESS); + Talk(SAY_AGGRO); } void UpdateAI(uint32 diff) OVERRIDE { - //Only if not incombat check if the event is started - if (!me->IsInCombat() && instance && instance->GetData(DATA_MAULGAREVENT)) - { - Unit* target = Unit::GetUnit(*me, instance->GetData64(DATA_MAULGAREVENT_TANK)); - - if (target) - { - AttackStart(target); - GetCouncil(); - } - } - - //Return since we have no target if (!UpdateVictim()) return; - //someone evaded! - if (instance && !instance->GetData(DATA_MAULGAREVENT)) - { - EnterEvadeMode(); - return; - } - //ArcingSmash_Timer if (ArcingSmash_Timer <= diff) { @@ -301,19 +194,17 @@ public: } }; + CreatureAI* GetAI(Creature* creature) const OVERRIDE + { + return GetGruulsLairAI<boss_high_king_maulgarAI>(creature); + } }; -//Olm The Summoner AI class boss_olm_the_summoner : public CreatureScript { public: boss_olm_the_summoner() : CreatureScript("boss_olm_the_summoner") { } - CreatureAI* GetAI(Creature* creature) const OVERRIDE - { - return new boss_olm_the_summonerAI(creature); - } - struct boss_olm_the_summonerAI : public ScriptedAI { boss_olm_the_summonerAI(Creature* creature) : ScriptedAI(creature) @@ -333,9 +224,7 @@ public: Summon_Timer = 15000; DeathCoil_Timer = 20000; - //reset encounter - if (instance) - instance->SetData(DATA_MAULGAREVENT, NOT_STARTED); + instance->SetBossState(DATA_MAULGAR, NOT_STARTED); } void AttackStart(Unit* who) OVERRIDE @@ -353,54 +242,25 @@ public: } } - void EnterCombat(Unit* who) OVERRIDE + void EnterCombat(Unit* /*who*/) OVERRIDE { - if (instance) - { - instance->SetData64(DATA_MAULGAREVENT_TANK, who->GetGUID()); - instance->SetData(DATA_MAULGAREVENT, IN_PROGRESS); - } + DoZoneInCombat(); + instance->SetBossState(DATA_MAULGAR, IN_PROGRESS); } void JustDied(Unit* /*killer*/) OVERRIDE { - if (instance) - { - Creature* Maulgar = NULL; - Maulgar = (Unit::GetCreature((*me), instance->GetData64(DATA_MAULGAR))); - - if (Maulgar) - CAST_AI(boss_high_king_maulgar::boss_high_king_maulgarAI, Maulgar->AI())->AddDeath(); + if (Creature* maulgar = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_MAULGAR))) + maulgar->AI()->DoAction(ACTION_ADD_DEATH); - if (CheckAllBossDied(instance, me)) - instance->SetData(DATA_MAULGAREVENT, DONE); - } + instance->SetBossState(DATA_MAULGAR, DONE); } void UpdateAI(uint32 diff) OVERRIDE { - //Only if not incombat check if the event is started - if (!me->IsInCombat() && instance && instance->GetData(DATA_MAULGAREVENT)) - { - Unit* target = Unit::GetUnit(*me, instance->GetData64(DATA_MAULGAREVENT_TANK)); - - if (target) - { - AttackStart(target); - } - } - - //Return since we have no target if (!UpdateVictim()) return; - //someone evaded! - if (instance && !instance->GetData(DATA_MAULGAREVENT)) - { - EnterEvadeMode(); - return; - } - //DarkDecay_Timer if (DarkDecay_Timer <= diff) { @@ -429,6 +289,10 @@ public: } }; + CreatureAI* GetAI(Creature* creature) const OVERRIDE + { + return GetGruulsLairAI<boss_olm_the_summonerAI>(creature); + } }; //Kiggler The Crazed AI @@ -437,11 +301,6 @@ class boss_kiggler_the_crazed : public CreatureScript public: boss_kiggler_the_crazed() : CreatureScript("boss_kiggler_the_crazed") { } - CreatureAI* GetAI(Creature* creature) const OVERRIDE - { - return new boss_kiggler_the_crazedAI(creature); - } - struct boss_kiggler_the_crazedAI : public ScriptedAI { boss_kiggler_the_crazedAI(Creature* creature) : ScriptedAI(creature) @@ -463,59 +322,28 @@ public: ArcaneShock_Timer = 20000; ArcaneExplosion_Timer = 30000; - //reset encounter - if (instance) - instance->SetData(DATA_MAULGAREVENT, NOT_STARTED); + instance->SetBossState(DATA_MAULGAR, NOT_STARTED); } - void EnterCombat(Unit* who) OVERRIDE + void EnterCombat(Unit* /*who*/) OVERRIDE { - if (instance) - { - instance->SetData64(DATA_MAULGAREVENT_TANK, who->GetGUID()); - instance->SetData(DATA_MAULGAREVENT, IN_PROGRESS); - } + DoZoneInCombat(); + instance->SetBossState(DATA_MAULGAR, IN_PROGRESS); } void JustDied(Unit* /*killer*/) OVERRIDE { - if (instance) - { - Creature* Maulgar = NULL; - Maulgar = (Unit::GetCreature((*me), instance->GetData64(DATA_MAULGAR))); - - if (Maulgar) - CAST_AI(boss_high_king_maulgar::boss_high_king_maulgarAI, Maulgar->AI())->AddDeath(); + if (Creature* maulgar = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_MAULGAR))) + maulgar->AI()->DoAction(ACTION_ADD_DEATH); - if (CheckAllBossDied(instance, me)) - instance->SetData(DATA_MAULGAREVENT, DONE); - } + instance->SetBossState(DATA_MAULGAR, DONE); } void UpdateAI(uint32 diff) OVERRIDE { - //Only if not incombat check if the event is started - if (!me->IsInCombat() && instance && instance->GetData(DATA_MAULGAREVENT)) - { - Unit* target = Unit::GetUnit(*me, instance->GetData64(DATA_MAULGAREVENT_TANK)); - - if (target) - { - AttackStart(target); - } - } - - //Return since we have no target if (!UpdateVictim()) return; - //someone evaded! - if (instance && !instance->GetData(DATA_MAULGAREVENT)) - { - EnterEvadeMode(); - return; - } - //GreaterPolymorph_Timer if (GreaterPolymorph_Timer <= diff) { @@ -550,19 +378,17 @@ public: } }; + CreatureAI* GetAI(Creature* creature) const OVERRIDE + { + return GetGruulsLairAI<boss_kiggler_the_crazedAI>(creature); + } }; -//Blindeye The Seer AI class boss_blindeye_the_seer : public CreatureScript { public: boss_blindeye_the_seer() : CreatureScript("boss_blindeye_the_seer") { } - CreatureAI* GetAI(Creature* creature) const OVERRIDE - { - return new boss_blindeye_the_seerAI(creature); - } - struct boss_blindeye_the_seerAI : public ScriptedAI { boss_blindeye_the_seerAI(Creature* creature) : ScriptedAI(creature) @@ -582,59 +408,28 @@ public: Heal_Timer = urand(25000, 40000); PrayerofHealing_Timer = urand(45000, 55000); - //reset encounter - if (instance) - instance->SetData(DATA_MAULGAREVENT, NOT_STARTED); + instance->SetBossState(DATA_MAULGAR, NOT_STARTED); } - void EnterCombat(Unit* who) OVERRIDE + void EnterCombat(Unit* /*who*/) OVERRIDE { - if (instance) - { - instance->SetData64(DATA_MAULGAREVENT_TANK, who->GetGUID()); - instance->SetData(DATA_MAULGAREVENT, IN_PROGRESS); - } + DoZoneInCombat(); + instance->SetBossState(DATA_MAULGAR, IN_PROGRESS); } void JustDied(Unit* /*killer*/) OVERRIDE { - if (instance) - { - Creature* Maulgar = NULL; - Maulgar = (Unit::GetCreature((*me), instance->GetData64(DATA_MAULGAR))); + if (Creature* maulgar = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_MAULGAR))) + maulgar->AI()->DoAction(ACTION_ADD_DEATH); - if (Maulgar) - CAST_AI(boss_high_king_maulgar::boss_high_king_maulgarAI, Maulgar->AI())->AddDeath(); - - if (CheckAllBossDied(instance, me)) - instance->SetData(DATA_MAULGAREVENT, DONE); - } + instance->SetBossState(DATA_MAULGAR, DONE); } void UpdateAI(uint32 diff) OVERRIDE { - //Only if not incombat check if the event is started - if (!me->IsInCombat() && instance && instance->GetData(DATA_MAULGAREVENT)) - { - Unit* target = Unit::GetUnit(*me, instance->GetData64(DATA_MAULGAREVENT_TANK)); - - if (target) - { - AttackStart(target); - } - } - - //Return since we have no target if (!UpdateVictim()) return; - //someone evaded! - if (instance && !instance->GetData(DATA_MAULGAREVENT)) - { - EnterEvadeMode(); - return; - } - //GreaterPowerWordShield_Timer if (GreaterPowerWordShield_Timer <= diff) { @@ -660,19 +455,17 @@ public: } }; + CreatureAI* GetAI(Creature* creature) const OVERRIDE + { + return GetGruulsLairAI<boss_blindeye_the_seerAI>(creature); + } }; -//Krosh Firehand AI class boss_krosh_firehand : public CreatureScript { public: boss_krosh_firehand() : CreatureScript("boss_krosh_firehand") { } - CreatureAI* GetAI(Creature* creature) const OVERRIDE - { - return new boss_krosh_firehandAI(creature); - } - struct boss_krosh_firehandAI : public ScriptedAI { boss_krosh_firehandAI(Creature* creature) : ScriptedAI(creature) @@ -692,59 +485,28 @@ public: SpellShield_Timer = 5000; BlastWave_Timer = 20000; - //reset encounter - if (instance) - instance->SetData(DATA_MAULGAREVENT, NOT_STARTED); + instance->SetBossState(DATA_MAULGAR, NOT_STARTED); } - void EnterCombat(Unit* who) OVERRIDE + void EnterCombat(Unit* /*who*/) OVERRIDE { - if (instance) - { - instance->SetData64(DATA_MAULGAREVENT_TANK, who->GetGUID()); - instance->SetData(DATA_MAULGAREVENT, IN_PROGRESS); - } + DoZoneInCombat(); + instance->SetBossState(DATA_MAULGAR, IN_PROGRESS); } void JustDied(Unit* /*killer*/) OVERRIDE { - if (instance) - { - Creature* Maulgar = NULL; - Maulgar = (Unit::GetCreature((*me), instance->GetData64(DATA_MAULGAR))); + if (Creature* maulgar = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_MAULGAR))) + maulgar->AI()->DoAction(ACTION_ADD_DEATH); - if (Maulgar) - CAST_AI(boss_high_king_maulgar::boss_high_king_maulgarAI, Maulgar->AI())->AddDeath(); - - if (CheckAllBossDied(instance, me)) - instance->SetData(DATA_MAULGAREVENT, DONE); - } + instance->SetBossState(DATA_MAULGAR, DONE); } void UpdateAI(uint32 diff) OVERRIDE { - //Only if not incombat check if the event is started - if (!me->IsInCombat() && instance && instance->GetData(DATA_MAULGAREVENT)) - { - Unit* target = Unit::GetUnit(*me, instance->GetData64(DATA_MAULGAREVENT_TANK)); - - if (target) - { - AttackStart(target); - } - } - - //Return since we have no target if (!UpdateVictim()) return; - //someone evaded! - if (instance && !instance->GetData(DATA_MAULGAREVENT)) - { - EnterEvadeMode(); - return; - } - //GreaterFireball_Timer if (GreaterFireball_Timer < diff || me->IsWithinDist(me->GetVictim(), 30)) { @@ -783,6 +545,11 @@ public: } else BlastWave_Timer -= diff; } }; + + CreatureAI* GetAI(Creature* creature) const OVERRIDE + { + return GetGruulsLairAI<boss_krosh_firehandAI>(creature); + } }; void AddSC_boss_high_king_maulgar() diff --git a/src/server/scripts/Outland/GruulsLair/gruuls_lair.h b/src/server/scripts/Outland/GruulsLair/gruuls_lair.h index 69ddba8c274..1425a19aa47 100644 --- a/src/server/scripts/Outland/GruulsLair/gruuls_lair.h +++ b/src/server/scripts/Outland/GruulsLair/gruuls_lair.h @@ -1,6 +1,5 @@ /* * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/> * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -16,23 +15,39 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef DEF_GRUULS_LAIR_H -#define DEF_GRUULS_LAIR_H +#ifndef GRUULS_LAIR_H_ +#define GRUULS_LAIR_H_ + +#define GLScriptName "instance_gruuls_lair" + +uint32 const EncounterCount = 2; enum DataTypes { - DATA_BLINDEYETHESEER = 1, - DATA_GRUULEVENT = 2, - DATA_KIGGLERTHECRAZED = 3, - DATA_KROSHFIREHAND = 4, - DATA_MAULGAREVENT = 5, - DATA_MAULGAREVENT_TANK = 6, - DATA_OLMTHESUMMONER = 7, - DATA_MAULGARDOOR = 8, - DATA_GRUULDOOR = 9, - DATA_MAULGAR = 10 + // Encounter States/Boss GUIDs + DATA_MAULGAR = 0, + DATA_GRUUL = 1 +}; + +enum CreatureIds +{ + NPC_MAULGAR = 18831, + NPC_KROSH_FIREHAND = 18832, + NPC_OLM_THE_SUMMONER = 18834, + NPC_KIGGLER_THE_CRAZED = 18835, + NPC_BLINDEYE_THE_SEER = 18836 }; -#define ERROR_INST_DATA "TSCR Error: Instance Data not set properly for Gruul's Lair instance (map 565). Encounters will be buggy." -#endif +enum GameObjectIds +{ + GO_MAULGAR_DOOR = 184468, + GO_GRUUL_DOOR = 184662 +}; + +template<class AI> +AI* GetGruulsLairAI(Creature* creature) +{ + return GetInstanceAI<AI>(creature, GLScriptName); +} +#endif // GRUULS_LAIR_H_ diff --git a/src/server/scripts/Outland/GruulsLair/instance_gruuls_lair.cpp b/src/server/scripts/Outland/GruulsLair/instance_gruuls_lair.cpp index d8399793df4..aa8a8d01d8a 100644 --- a/src/server/scripts/Outland/GruulsLair/instance_gruuls_lair.cpp +++ b/src/server/scripts/Outland/GruulsLair/instance_gruuls_lair.cpp @@ -1,6 +1,5 @@ /* * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2006-2009 ScriptDev2 <https://scriptdev2.svn.sourceforge.net/> * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -16,184 +15,165 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -/* ScriptData -SDName: Instance_Gruuls_Lair -SD%Complete: 100 -SDComment: -SDCategory: Gruul's Lair -EndScriptData */ - #include "ScriptMgr.h" #include "InstanceScript.h" #include "gruuls_lair.h" -#define MAX_ENCOUNTER 2 +DoorData const doorData[] = +{ + { GO_MAULGAR_DOOR, DATA_MAULGAR, DOOR_TYPE_PASSAGE, BOUNDARY_NONE }, + { GO_GRUUL_DOOR, DATA_GRUUL, DOOR_TYPE_ROOM, BOUNDARY_NONE }, + { 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE } // END +}; -/* Gruuls Lair encounters: -1 - High King Maulgar event -2 - Gruul event -*/ +MinionData const minionData[] = +{ + { NPC_MAULGAR, DATA_MAULGAR }, + { NPC_KROSH_FIREHAND, DATA_MAULGAR }, + { NPC_OLM_THE_SUMMONER, DATA_MAULGAR }, + { NPC_KIGGLER_THE_CRAZED, DATA_MAULGAR }, + { NPC_BLINDEYE_THE_SEER, DATA_MAULGAR } +}; class instance_gruuls_lair : public InstanceMapScript { -public: - instance_gruuls_lair() : InstanceMapScript("instance_gruuls_lair", 565) { } - - InstanceScript* GetInstanceScript(InstanceMap* map) const OVERRIDE - { - return new instance_gruuls_lair_InstanceMapScript(map); - } + public: + instance_gruuls_lair() : InstanceMapScript(GLScriptName, 565) { } - struct instance_gruuls_lair_InstanceMapScript : public InstanceScript - { - instance_gruuls_lair_InstanceMapScript(Map* map) : InstanceScript(map) {} - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - - uint64 MaulgarEvent_Tank; - uint64 KigglerTheCrazed; - uint64 BlindeyeTheSeer; - uint64 OlmTheSummoner; - uint64 KroshFirehand; - uint64 Maulgar; - - uint64 MaulgarDoor; - uint64 GruulDoor; - - void Initialize() OVERRIDE + struct instance_gruuls_lair_InstanceMapScript : public InstanceScript { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - MaulgarEvent_Tank = 0; - KigglerTheCrazed = 0; - BlindeyeTheSeer = 0; - OlmTheSummoner = 0; - KroshFirehand = 0; - Maulgar = 0; - - MaulgarDoor = 0; - GruulDoor = 0; - } - - bool IsEncounterInProgress() const OVERRIDE - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - return true; + instance_gruuls_lair_InstanceMapScript(Map* map) : InstanceScript(map) + { + SetBossNumber(EncounterCount); + LoadDoorData(doorData); + LoadMinionData(minionData); - return false; - } + MaulgarGUID = 0; + } - void OnCreatureCreate(Creature* creature) OVERRIDE - { - switch (creature->GetEntry()) + void OnCreatureCreate(Creature* creature) OVERRIDE { - case 18835: KigglerTheCrazed = creature->GetGUID(); break; - case 18836: BlindeyeTheSeer = creature->GetGUID(); break; - case 18834: OlmTheSummoner = creature->GetGUID(); break; - case 18832: KroshFirehand = creature->GetGUID(); break; - case 18831: Maulgar = creature->GetGUID(); break; + switch (creature->GetEntry()) + { + case NPC_MAULGAR: + MaulgarGUID = creature->GetGUID(); + // no break; + case NPC_KROSH_FIREHAND: + case NPC_OLM_THE_SUMMONER: + case NPC_KIGGLER_THE_CRAZED: + case NPC_BLINDEYE_THE_SEER: + AddMinion(creature, true); + break; + default: + break; + } } - } - void OnGameObjectCreate(GameObject* go) OVERRIDE - { - switch (go->GetEntry()) + void OnCreatureRemove(Creature* creature) OVERRIDE { - case 184468: - MaulgarDoor = go->GetGUID(); - if (m_auiEncounter[0] == DONE) - HandleGameObject(0, true, go); - break; - case 184662: - GruulDoor = go->GetGUID(); - break; + switch (creature->GetEntry()) + { + case NPC_MAULGAR: + case NPC_KROSH_FIREHAND: + case NPC_OLM_THE_SUMMONER: + case NPC_KIGGLER_THE_CRAZED: + case NPC_BLINDEYE_THE_SEER: + AddMinion(creature, false); + break; + default: + break; + } } - } - void SetData64(uint32 type, uint64 data) OVERRIDE - { - if (type == DATA_MAULGAREVENT_TANK) - MaulgarEvent_Tank = data; - } - - uint64 GetData64(uint32 identifier) const OVERRIDE - { - switch (identifier) + void OnGameObjectCreate(GameObject* go) OVERRIDE { - case DATA_MAULGAREVENT_TANK: return MaulgarEvent_Tank; - case DATA_KIGGLERTHECRAZED: return KigglerTheCrazed; - case DATA_BLINDEYETHESEER: return BlindeyeTheSeer; - case DATA_OLMTHESUMMONER: return OlmTheSummoner; - case DATA_KROSHFIREHAND: return KroshFirehand; - case DATA_MAULGARDOOR: return MaulgarDoor; - case DATA_GRUULDOOR: return GruulDoor; - case DATA_MAULGAR: return Maulgar; + switch (go->GetEntry()) + { + case GO_MAULGAR_DOOR: + case GO_GRUUL_DOOR: + AddDoor(go, true); + break; + default: + break; + } } - return 0; - } - void SetData(uint32 type, uint32 data) OVERRIDE - { - switch (type) + void OnGameObjectRemove(GameObject* go) OVERRIDE { - case DATA_MAULGAREVENT: - if (data == DONE) - HandleGameObject(MaulgarDoor, true); - m_auiEncounter[0] = data; - break; - - case DATA_GRUULEVENT: - if (data == IN_PROGRESS) - HandleGameObject(GruulDoor, false); - else - HandleGameObject(GruulDoor, true); - m_auiEncounter[1] = data; - break; + switch (go->GetEntry()) + { + case GO_MAULGAR_DOOR: + case GO_GRUUL_DOOR: + AddDoor(go, false); + break; + default: + break; + } } - if (data == DONE) - SaveToDB(); - } - - uint32 GetData(uint32 type) const OVERRIDE - { - switch (type) + uint64 GetData64(uint32 type) const OVERRIDE { - case DATA_MAULGAREVENT: return m_auiEncounter[0]; - case DATA_GRUULEVENT: return m_auiEncounter[1]; + switch (type) + { + case DATA_MAULGAR: + return MaulgarGUID; + default: + break; + } + return 0; } - return 0; - } - std::string GetSaveData() OVERRIDE - { - OUT_SAVE_INST_DATA; - std::ostringstream stream; - stream << m_auiEncounter[0] << ' ' << m_auiEncounter[1]; + std::string GetSaveData() OVERRIDE + { + OUT_SAVE_INST_DATA; - OUT_SAVE_INST_DATA_COMPLETE; - return stream.str(); - } + std::ostringstream saveStream; + saveStream << "G L " << GetBossSaveData(); - void Load(const char* in) OVERRIDE - { - if (!in) + OUT_SAVE_INST_DATA_COMPLETE; + return saveStream.str(); + } + + void Load(char const* str) OVERRIDE { - OUT_LOAD_INST_DATA_FAIL; - return; + if (!str) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(str); + + char dataHead1, dataHead2; + + std::istringstream loadStream(str); + loadStream >> dataHead1 >> dataHead2; + + if (dataHead1 == 'G' && dataHead2 == 'L') + { + for (uint32 i = 0; i < EncounterCount; ++i) + { + uint32 tmpState; + loadStream >> tmpState; + if (tmpState == IN_PROGRESS || tmpState > SPECIAL) + tmpState = NOT_STARTED; + SetBossState(i, EncounterState(tmpState)); + } + } + else + OUT_LOAD_INST_DATA_FAIL; + + OUT_LOAD_INST_DATA_COMPLETE; } - OUT_LOAD_INST_DATA(in); - std::istringstream stream(in); - stream >> m_auiEncounter[0] >> m_auiEncounter[1]; - 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; - } - }; + protected: + uint64 MaulgarGUID; + }; + InstanceScript* GetInstanceScript(InstanceMap* map) const OVERRIDE + { + return new instance_gruuls_lair_InstanceMapScript(map); + } }; void AddSC_instance_gruuls_lair() diff --git a/src/server/scripts/Outland/HellfireCitadel/BloodFurnace/instance_blood_furnace.cpp b/src/server/scripts/Outland/HellfireCitadel/BloodFurnace/instance_blood_furnace.cpp index 2193d3841a6..8b233901608 100644 --- a/src/server/scripts/Outland/HellfireCitadel/BloodFurnace/instance_blood_furnace.cpp +++ b/src/server/scripts/Outland/HellfireCitadel/BloodFurnace/instance_blood_furnace.cpp @@ -304,9 +304,9 @@ class instance_blood_furnace : public InstanceMapScript HandleGameObject(PrisonCell8GUID, false); } - void ResetPrisoners(std::set<uint64> prisoners) + void ResetPrisoners(const std::set<uint64>& prisoners) { - for (std::set<uint64>::iterator i = prisoners.begin(); i != prisoners.end(); ++i) + for (std::set<uint64>::const_iterator i = prisoners.begin(); i != prisoners.end(); ++i) if (Creature* prisoner = instance->GetCreature(*i)) ResetPrisoner(prisoner); } @@ -398,9 +398,9 @@ class instance_blood_furnace : public InstanceMapScript } } - void ActivatePrisoners(std::set<uint64> prisoners) + void ActivatePrisoners(const std::set<uint64>& prisoners) { - for (std::set<uint64>::iterator i = prisoners.begin(); i != prisoners.end(); ++i) + for (std::set<uint64>::const_iterator i = prisoners.begin(); i != prisoners.end(); ++i) if (Creature* prisoner = instance->GetCreature(*i)) { prisoner->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC | UNIT_FLAG_NON_ATTACKABLE); diff --git a/src/server/scripts/Outland/HellfireCitadel/HellfireRamparts/boss_omor_the_unscarred.cpp b/src/server/scripts/Outland/HellfireCitadel/HellfireRamparts/boss_omor_the_unscarred.cpp index a87aefa72af..7e80182f1e8 100644 --- a/src/server/scripts/Outland/HellfireCitadel/HellfireRamparts/boss_omor_the_unscarred.cpp +++ b/src/server/scripts/Outland/HellfireCitadel/HellfireRamparts/boss_omor_the_unscarred.cpp @@ -132,7 +132,7 @@ class boss_omor_the_unscarred : public CreatureScript { if (ShadowWhip_Timer <= diff) { - if (Player* temp = Unit::GetPlayer(*me, PlayerGUID)) + if (Player* temp = ObjectAccessor::GetPlayer(*me, PlayerGUID)) { //if unit dosen't have this flag, then no pulling back (script will attempt cast, even if orbital strike was resisted) if (temp->HasUnitMovementFlag(MOVEMENTFLAG_FALLING_FAR)) diff --git a/src/server/scripts/Outland/HellfireCitadel/HellfireRamparts/boss_vazruden_the_herald.cpp b/src/server/scripts/Outland/HellfireCitadel/HellfireRamparts/boss_vazruden_the_herald.cpp index 0f5cea6c4c6..a4007a5a7b1 100644 --- a/src/server/scripts/Outland/HellfireCitadel/HellfireRamparts/boss_vazruden_the_herald.cpp +++ b/src/server/scripts/Outland/HellfireCitadel/HellfireRamparts/boss_vazruden_the_herald.cpp @@ -186,7 +186,6 @@ class boss_nazan : public CreatureScript uint32 Turn_Timer; bool flight; uint64 VazrudenGUID; - SpellInfo* liquid_fire; }; CreatureAI* GetAI(Creature* creature) const OVERRIDE diff --git a/src/server/scripts/Outland/TempestKeep/Eye/boss_alar.cpp b/src/server/scripts/Outland/TempestKeep/Eye/boss_alar.cpp index 09fb235edb9..8b2cce69dc7 100644 --- a/src/server/scripts/Outland/TempestKeep/Eye/boss_alar.cpp +++ b/src/server/scripts/Outland/TempestKeep/Eye/boss_alar.cpp @@ -408,7 +408,7 @@ class boss_alar : public CreatureScript if (Summoned) { Summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - Summoned->SetObjectScale(Summoned->GetFloatValue(OBJECT_FIELD_SCALE_X)*2.5f); + Summoned->SetObjectScale(Summoned->GetObjectScale() * 2.5f); Summoned->SetDisplayId(11686); Summoned->setFaction(me->getFaction()); Summoned->SetLevel(me->getLevel()); diff --git a/src/server/scripts/Outland/TempestKeep/Eye/boss_astromancer.cpp b/src/server/scripts/Outland/TempestKeep/Eye/boss_astromancer.cpp index 3c8627c7058..c5c3f6deb12 100644 --- a/src/server/scripts/Outland/TempestKeep/Eye/boss_astromancer.cpp +++ b/src/server/scripts/Outland/TempestKeep/Eye/boss_astromancer.cpp @@ -104,7 +104,7 @@ class boss_high_astromancer_solarian : public CreatureScript instance = creature->GetInstanceScript(); defaultarmor = creature->GetArmor(); - defaultsize = creature->GetFloatValue(OBJECT_FIELD_SCALE_X); + defaultsize = creature->GetObjectScale(); } InstanceScript* instance; diff --git a/src/server/scripts/Outland/zone_blades_edge_mountains.cpp b/src/server/scripts/Outland/zone_blades_edge_mountains.cpp index 6273731f292..57eb587140f 100644 --- a/src/server/scripts/Outland/zone_blades_edge_mountains.cpp +++ b/src/server/scripts/Outland/zone_blades_edge_mountains.cpp @@ -500,7 +500,6 @@ public: } void MoveInLineOfSight(Unit* who) OVERRIDE - { if (!who || (!who->IsAlive())) return; @@ -516,15 +515,16 @@ public: void MovementInform(uint32 /*type*/, uint32 id) OVERRIDE { - Player* player = Unit::GetPlayer(*me, PlayerGUID); if (id == 1) { - GameObject* Keg = me->FindNearestGameObject(GO_KEG, 20); - if (Keg) + if (GameObject* Keg = me->FindNearestGameObject(GO_KEG, 20)) Keg->Delete(); + me->HandleEmoteCommand(7); me->SetReactState(REACT_AGGRESSIVE); me->GetMotionMaster()->MoveTargetedHome(); + + Player* player = ObjectAccessor::GetPlayer(*me, PlayerGUID); Creature* Credit = me->FindNearestCreature(NPC_QUEST_CREDIT, 50, true); if (player && Credit) player->KilledMonster(Credit->GetCreatureTemplate(), Credit->GetGUID()); @@ -1017,7 +1017,7 @@ class npc_simon_bunny : public CreatureScript } if (rewSpell) - if (Player* player = me->GetPlayer(*me, playerGUID)) + if (Player* player = ObjectAccessor::GetPlayer(*me, playerGUID)) DoCast(player, rewSpell, true); } @@ -1032,7 +1032,7 @@ class npc_simon_bunny : public CreatureScript { if (large) { - if (Player* player = me->GetPlayer(*me, playerGUID)) + if (Player* player = ObjectAccessor::GetPlayer(*me, playerGUID)) if (Creature* guardian = me->SummonCreature(NPC_APEXIS_GUARDIAN, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ() - zCoordCorrection, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 20000)) guardian->AI()->AttackStart(player); @@ -1042,7 +1042,7 @@ class npc_simon_bunny : public CreatureScript { fails++; - if (Player* player = me->GetPlayer(*me, playerGUID)) + if (Player* player = ObjectAccessor::GetPlayer(*me, playerGUID)) DoCast(player, SPELL_BAD_PRESS_TRIGGER, true); if (fails >= 4) @@ -1065,7 +1065,7 @@ class npc_simon_bunny : public CreatureScript // Checks if player has already die or has get too far from the current node bool CheckPlayer() { - if (Player* player = me->GetPlayer(*me, playerGUID)) + if (Player* player = ObjectAccessor::GetPlayer(*me, playerGUID)) { if (player->isDead()) return false; diff --git a/src/server/scripts/Outland/zone_netherstorm.cpp b/src/server/scripts/Outland/zone_netherstorm.cpp index 7e99275adbd..7c328f57e78 100644 --- a/src/server/scripts/Outland/zone_netherstorm.cpp +++ b/src/server/scripts/Outland/zone_netherstorm.cpp @@ -436,9 +436,9 @@ public: // Emote Ardonis and Pathaleon void Turn_to_Pathaleons_Image() { - Creature* ardonis = Unit::GetCreature(*me, ardonisGUID); - Creature* pathaleon = Unit::GetCreature(*me, pathaleonGUID); - Player* player = Unit::GetPlayer(*me, PlayerGUID); + Creature* ardonis = ObjectAccessor::GetCreature(*me, ardonisGUID); + Creature* pathaleon = ObjectAccessor::GetCreature(*me, pathaleonGUID); + Player* player = ObjectAccessor::GetPlayer(*me, PlayerGUID); if (!ardonis || !pathaleon || !player) return; @@ -462,9 +462,9 @@ public: //Set them back to each other void Turn_to_eachother() { - if (Unit* ardonis = Unit::GetUnit(*me, ardonisGUID)) + if (Unit* ardonis = ObjectAccessor::GetUnit(*me, ardonisGUID)) { - Player* player = Unit::GetPlayer(*me, PlayerGUID); + Player* player = ObjectAccessor::GetPlayer(*me, PlayerGUID); if (!player) return; @@ -519,9 +519,9 @@ public: return; } - Creature* ardonis = Creature::GetCreature(*me, ardonisGUID); - Creature* pathaleon = Creature::GetCreature(*me, pathaleonGUID); - Player* player = Unit::GetPlayer(*me, PlayerGUID); + Creature* ardonis = ObjectAccessor::GetCreature(*me, ardonisGUID); + Creature* pathaleon = ObjectAccessor::GetCreature(*me, pathaleonGUID); + Player* player = ObjectAccessor::GetPlayer(*me, PlayerGUID); if (!ardonis || !player) { @@ -753,7 +753,6 @@ public: bool Drained; uint8 WeakPercent; - Player* player; uint64 PlayerGUID; uint32 ManaBurnTimer; @@ -821,7 +820,7 @@ public: ManaBurnTimer = 3500; } else ManaBurnTimer -= diff; - if (Player* player = Unit::GetPlayer(*me, PlayerGUID)) // start: support for quest 10190 + if (Player* player = ObjectAccessor::GetPlayer(*me, PlayerGUID)) // start: support for quest 10190 { if (!Weak && HealthBelowPct(WeakPercent) && player->GetQuestStatus(QUEST_RECHARGING_THE_BATTERIES) == QUEST_STATUS_INCOMPLETE) diff --git a/src/server/scripts/Outland/zone_shadowmoon_valley.cpp b/src/server/scripts/Outland/zone_shadowmoon_valley.cpp index b7cf46ad8ae..eac3dce43b0 100644 --- a/src/server/scripts/Outland/zone_shadowmoon_valley.cpp +++ b/src/server/scripts/Outland/zone_shadowmoon_valley.cpp @@ -154,11 +154,11 @@ public: DoCast(me, SPELL_JUST_EATEN); Talk(SAY_JUST_EATEN); - if (Player* pPlr = Unit::GetPlayer(*me, uiPlayerGUID)) + if (Player* player = ObjectAccessor::GetPlayer(*me, uiPlayerGUID)) { - pPlr->KilledMonsterCredit(NPC_EVENT_PINGER, 0); + player->KilledMonsterCredit(NPC_EVENT_PINGER, 0); - if (GameObject* go = pPlr->FindNearestGameObject(GO_CARCASS, 10)) + if (GameObject* go = player->FindNearestGameObject(GO_CARCASS, 10)) go->Delete(); } @@ -298,7 +298,7 @@ public: Tapped = false; if (PlayerGUID) { - Player* player = Unit::GetPlayer(*me, PlayerGUID); + Player* player = ObjectAccessor::GetPlayer(*me, PlayerGUID); if (player && player->GetQuestStatus(10854) == QUEST_STATUS_INCOMPLETE) { DoCast(player, SPELL_FORCE_OF_NELTHARAKU, true); @@ -400,7 +400,7 @@ public: { if (PlayerGUID) { - Player* player = Unit::GetPlayer(*me, PlayerGUID); + Player* player = ObjectAccessor::GetPlayer(*me, PlayerGUID); if (player && player->GetQuestStatus(11020) == QUEST_STATUS_INCOMPLETE) player->KilledMonsterCredit(23209, 0); } @@ -760,7 +760,7 @@ public: } if (PlayerGUID) { - Player* player = Unit::GetPlayer(*me, PlayerGUID); + Player* player = ObjectAccessor::GetPlayer(*me, PlayerGUID); if (player) Talk(OVERLORD_SAY_1, player->GetGUID()); } @@ -771,8 +771,8 @@ public: uint32 NextStep(uint32 Step) { - Player* player = Unit::GetPlayer(*me, PlayerGUID); - Creature* Illi = Creature::GetCreature(*me, IllidanGUID); + Player* player = ObjectAccessor::GetPlayer(*me, PlayerGUID); + Creature* Illi = ObjectAccessor::GetCreature(*me, IllidanGUID); if (!player) { @@ -1311,7 +1311,7 @@ public: me->RemoveFlag(UNIT_FIELD_BYTES_1, 8); break; case 5: - if (Player* AggroTarget = (Unit::GetPlayer(*me, AggroTargetGUID))) + if (Player* AggroTarget = ObjectAccessor::GetPlayer(*me, AggroTargetGUID)) { me->SetTarget(AggroTarget->GetGUID()); me->AddThreat(AggroTarget, 1); @@ -1319,7 +1319,7 @@ public: } break; case 6: - if (Player* AggroTarget = (Unit::GetPlayer(*me, AggroTargetGUID))) + if (Player* AggroTarget = ObjectAccessor::GetPlayer(*me, AggroTargetGUID)) { me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); me->ClearUnitState(UNIT_STATE_ROOT); @@ -1456,15 +1456,13 @@ public: void CheckEventFail() { - Player* player = Unit::GetPlayer(*me, PlayerGUID); + Player* player = ObjectAccessor::GetPlayer(*me, PlayerGUID); if (!player) return; if (Group* EventGroup = player->GetGroup()) { - Player* GroupMember; - uint8 GroupMemberCount = 0; uint8 DeadMemberCount = 0; uint8 FailedMemberCount = 0; @@ -1473,7 +1471,7 @@ public: for (Group::member_citerator itr = members.begin(); itr!= members.end(); ++itr) { - GroupMember = (Unit::GetPlayer(*me, itr->guid)); + Player* GroupMember = ObjectAccessor::GetPlayer(*me, itr->guid); if (!GroupMember) continue; if (!GroupMember->IsWithinDistInMap(me, EVENT_AREA_RADIUS) && GroupMember->GetQuestStatus(QUEST_BATTLE_OF_THE_CRIMSON_WATCH) == QUEST_STATUS_INCOMPLETE) @@ -1484,9 +1482,7 @@ public: ++GroupMemberCount; if (GroupMember->isDead()) - { ++DeadMemberCount; - } } if (GroupMemberCount == FailedMemberCount) @@ -1498,12 +1494,9 @@ public: { for (Group::member_citerator itr = members.begin(); itr!= members.end(); ++itr) { - GroupMember = Unit::GetPlayer(*me, itr->guid); - - if (GroupMember && GroupMember->GetQuestStatus(QUEST_BATTLE_OF_THE_CRIMSON_WATCH) == QUEST_STATUS_INCOMPLETE) - { - GroupMember->FailQuest(QUEST_BATTLE_OF_THE_CRIMSON_WATCH); - } + if (Player* groupMember = ObjectAccessor::GetPlayer(*me, itr->guid)) + if (groupMember->GetQuestStatus(QUEST_BATTLE_OF_THE_CRIMSON_WATCH) == QUEST_STATUS_INCOMPLETE) + groupMember->FailQuest(QUEST_BATTLE_OF_THE_CRIMSON_WATCH); } Failed = true; } @@ -1713,7 +1706,7 @@ void npc_lord_illidan_stormrage::npc_lord_illidan_stormrageAI::SummonNextWave() { if (PlayerGUID) { - if (Player* target = Unit::GetPlayer(*me, PlayerGUID)) + if (Player* target = ObjectAccessor::GetPlayer(*me, PlayerGUID)) { float x, y, z; target->GetPosition(x, y, z); @@ -1906,7 +1899,7 @@ class spell_unlocking_zuluheds_chains : public SpellScriptLoader { if (GetCaster()->GetTypeId() == TYPEID_PLAYER) if (Creature* karynaku = GetCaster()->FindNearestCreature(NPC_KARYNAKU, 15.0f)) - GetCaster()->ToPlayer()->CastedCreatureOrGO(NPC_KARYNAKU, karynaku->GetGUID(), GetSpellInfo()->Id); + GetCaster()->ToPlayer()->KilledMonsterCredit(NPC_KARYNAKU, karynaku->GetGUID()); } void Register() OVERRIDE diff --git a/src/server/scripts/Pet/CMakeLists.txt b/src/server/scripts/Pet/CMakeLists.txt index b4a8eea77d8..87bbfd63c69 100644 --- a/src/server/scripts/Pet/CMakeLists.txt +++ b/src/server/scripts/Pet/CMakeLists.txt @@ -11,6 +11,7 @@ set(scripts_STAT_SRCS ${scripts_STAT_SRCS} Pet/pet_dk.cpp + Pet/pet_generic.cpp Pet/pet_hunter.cpp Pet/pet_mage.cpp Pet/pet_priest.cpp diff --git a/src/server/scripts/Pet/pet_generic.cpp b/src/server/scripts/Pet/pet_generic.cpp new file mode 100644 index 00000000000..f10a14716c6 --- /dev/null +++ b/src/server/scripts/Pet/pet_generic.cpp @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2008-2013 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/>. + */ + +/* + * Ordered alphabetically using scriptname. + * Scriptnames of files in this file should be prefixed with "npc_pet_gen_". + */ + +#include "ScriptMgr.h" +#include "ScriptedCreature.h" +#include "Player.h" + +enum Mojo +{ + SAY_MOJO = 0, + + SPELL_FEELING_FROGGY = 43906, + SPELL_SEDUCTION_VISUAL = 43919 +}; + +class npc_pet_gen_mojo : public CreatureScript +{ + public: + npc_pet_gen_mojo() : CreatureScript("npc_pet_gen_mojo") { } + + struct npc_pet_gen_mojoAI : public ScriptedAI + { + npc_pet_gen_mojoAI(Creature* creature) : ScriptedAI(creature) { } + + void Reset() OVERRIDE + { + _victimGUID = 0; + + if (Unit* owner = me->GetOwner()) + me->GetMotionMaster()->MoveFollow(owner, 0.0f, 0.0f); + } + + void EnterCombat(Unit* /*who*/) OVERRIDE { } + void UpdateAI(uint32 /*diff*/) OVERRIDE { } + + void ReceiveEmote(Player* player, uint32 emote) OVERRIDE + { + me->HandleEmoteCommand(emote); + Unit* owner = me->GetOwner(); + if (emote != TEXT_EMOTE_KISS || !owner || owner->GetTypeId() != TYPEID_PLAYER || + owner->ToPlayer()->GetTeam() != player->GetTeam()) + { + return; + } + + Talk(SAY_MOJO, player->GetGUID()); + + if (_victimGUID) + if (Player* victim = ObjectAccessor::GetPlayer(*me, _victimGUID)) + victim->RemoveAura(SPELL_FEELING_FROGGY); + + _victimGUID = player->GetGUID(); + + DoCast(player, SPELL_FEELING_FROGGY, true); + DoCast(me, SPELL_SEDUCTION_VISUAL, true); + me->GetMotionMaster()->MoveFollow(player, 0.0f, 0.0f); + } + + private: + uint64 _victimGUID; + }; + + CreatureAI* GetAI(Creature* creature) const OVERRIDE + { + return new npc_pet_gen_mojoAI(creature); + } +}; + +void AddSC_generic_pet_scripts() +{ + new npc_pet_gen_mojo(); +} diff --git a/src/server/scripts/Spells/spell_hunter.cpp b/src/server/scripts/Spells/spell_hunter.cpp index 9456dc8fdcb..d9017538842 100644 --- a/src/server/scripts/Spells/spell_hunter.cpp +++ b/src/server/scripts/Spells/spell_hunter.cpp @@ -793,7 +793,7 @@ class spell_hun_sniper_training : public SpellScriptLoader if (!target->HasAura(spellId)) { SpellInfo const* triggeredSpellInfo = sSpellMgr->GetSpellInfo(spellId); - Unit* triggerCaster = triggeredSpellInfo->NeedsToBeTriggeredByCaster() ? caster : target; + Unit* triggerCaster = triggeredSpellInfo->NeedsToBeTriggeredByCaster(GetSpellInfo()) ? caster : target; triggerCaster->CastSpell(target, triggeredSpellInfo, true, 0, aurEff); } } diff --git a/src/server/scripts/Spells/spell_quest.cpp b/src/server/scripts/Spells/spell_quest.cpp index ca94f871d03..6b56c51d6e1 100644 --- a/src/server/scripts/Spells/spell_quest.cpp +++ b/src/server/scripts/Spells/spell_quest.cpp @@ -25,7 +25,7 @@ #include "ScriptMgr.h" #include "ScriptedCreature.h" #include "SpellScript.h" -#include "SpellAuras.h" +#include "SpellAuraEffects.h" #include "Vehicle.h" #include "GridNotifiers.h" #include "GridNotifiersImpl.h" @@ -1876,6 +1876,291 @@ class spell_q13086_cannons_target : public SpellScriptLoader } }; +enum BurstAtTheSeams +{ + NPC_DRAKKARI_CHIEFTAINK = 29099, + + QUEST_BURST_AT_THE_SEAMS = 12690, + + SPELL_BURST_AT_THE_SEAMS = 52510, // Burst at the Seams + SPELL_BURST_AT_THE_SEAMS_DMG = 52508, // Damage spell + SPELL_BURST_AT_THE_SEAMS_DMG_2 = 59580, // Abomination self damage spell + SPELL_BURST_AT_THE_SEAMS_BONE = 52516, // Burst at the Seams:Bone + SPELL_BURST_AT_THE_SEAMS_MEAT = 52520, // Explode Abomination:Meat + SPELL_BURST_AT_THE_SEAMS_BMEAT = 52523, // Explode Abomination:Bloody Meat + SPELL_DRAKKARI_SKULLCRUSHER_CREDIT = 52590, // Credit for Drakkari Skullcrusher + SPELL_SUMMON_DRAKKARI_CHIEFTAIN = 52616, // Summon Drakkari Chieftain + SPELL_DRAKKARI_CHIEFTAINK_KILL_CREDIT = 52620 // Drakkari Chieftain Kill Credit +}; + +class spell_q12690_burst_at_the_seams : public SpellScriptLoader +{ + public: + spell_q12690_burst_at_the_seams() : SpellScriptLoader("spell_q12690_burst_at_the_seams") { } + + class spell_q12690_burst_at_the_seams_SpellScript : public SpellScript + { + PrepareSpellScript(spell_q12690_burst_at_the_seams_SpellScript); + + bool Validate(SpellInfo const* /*spellInfo*/) OVERRIDE + { + if (!sSpellMgr->GetSpellInfo(SPELL_BURST_AT_THE_SEAMS) + || !sSpellMgr->GetSpellInfo(SPELL_BURST_AT_THE_SEAMS_DMG) + || !sSpellMgr->GetSpellInfo(SPELL_BURST_AT_THE_SEAMS_DMG_2) + || !sSpellMgr->GetSpellInfo(SPELL_BURST_AT_THE_SEAMS_BONE) + || !sSpellMgr->GetSpellInfo(SPELL_BURST_AT_THE_SEAMS_MEAT) + || !sSpellMgr->GetSpellInfo(SPELL_BURST_AT_THE_SEAMS_BMEAT)) + return false; + return true; + } + + bool Load() OVERRIDE + { + return GetCaster()->GetTypeId() == TYPEID_UNIT; + } + + void HandleKnockBack(SpellEffIndex /*effIndex*/) + { + if (Unit* creature = GetHitCreature()) + { + if (Unit* charmer = GetCaster()->GetCharmerOrOwner()) + { + if (Player* player = charmer->ToPlayer()) + { + if (player->GetQuestStatus(QUEST_BURST_AT_THE_SEAMS) == QUEST_STATUS_INCOMPLETE) + { + creature->CastSpell(creature, SPELL_BURST_AT_THE_SEAMS_BONE, true); + creature->CastSpell(creature, SPELL_BURST_AT_THE_SEAMS_MEAT, true); + creature->CastSpell(creature, SPELL_BURST_AT_THE_SEAMS_BMEAT, true); + creature->CastSpell(creature, SPELL_BURST_AT_THE_SEAMS_DMG, true); + creature->CastSpell(creature, SPELL_BURST_AT_THE_SEAMS_DMG_2, true); + + player->CastSpell(player, SPELL_DRAKKARI_SKULLCRUSHER_CREDIT, true); + uint16 count = player->GetReqKillOrCastCurrentCount(QUEST_BURST_AT_THE_SEAMS, NPC_DRAKKARI_CHIEFTAINK); + if ((count % 20) == 0) + player->CastSpell(player, SPELL_SUMMON_DRAKKARI_CHIEFTAIN, true); + } + } + } + } + } + + void HandleScript(SpellEffIndex /*effIndex*/) + { + GetCaster()->ToCreature()->DespawnOrUnsummon(2 * IN_MILLISECONDS); + } + + void Register() OVERRIDE + { + OnEffectHitTarget += SpellEffectFn(spell_q12690_burst_at_the_seams_SpellScript::HandleKnockBack, EFFECT_1, SPELL_EFFECT_KNOCK_BACK); + OnEffectHitTarget += SpellEffectFn(spell_q12690_burst_at_the_seams_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const OVERRIDE + { + return new spell_q12690_burst_at_the_seams_SpellScript(); + } +}; + +enum EscapeFromSilverbrook +{ + SPELL_SUMMON_WORGEN = 48681 +}; + +// 48682 - Escape from Silverbrook - Periodic Dummy +class spell_q12308_escape_from_silverbrook : public SpellScriptLoader +{ + public: + spell_q12308_escape_from_silverbrook() : SpellScriptLoader("spell_q12308_escape_from_silverbrook") { } + + class spell_q12308_escape_from_silverbrook_SpellScript : public SpellScript + { + PrepareSpellScript(spell_q12308_escape_from_silverbrook_SpellScript); + + bool Validate(SpellInfo const* /*spellInfo*/) OVERRIDE + { + if (!sSpellMgr->GetSpellInfo(SPELL_SUMMON_WORGEN)) + return false; + return true; + } + + void HandleDummy(SpellEffIndex /*effIndex*/) + { + GetCaster()->CastSpell(GetCaster(), SPELL_SUMMON_WORGEN, true); + } + + void Register() OVERRIDE + { + OnEffectHit += SpellEffectFn(spell_q12308_escape_from_silverbrook_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); + } + }; + + SpellScript* GetSpellScript() const OVERRIDE + { + return new spell_q12308_escape_from_silverbrook_SpellScript(); + } +}; + +// 48681 - Summon Silverbrook Worgen +class spell_q12308_escape_from_silverbrook_summon_worgen : public SpellScriptLoader +{ + public: + spell_q12308_escape_from_silverbrook_summon_worgen() : SpellScriptLoader("spell_q12308_escape_from_silverbrook_summon_worgen") { } + + class spell_q12308_escape_from_silverbrook_summon_worgen_SpellScript : public SpellScript + { + PrepareSpellScript(spell_q12308_escape_from_silverbrook_summon_worgen_SpellScript); + + void ModDest(SpellEffIndex effIndex) + { + float dist = GetSpellInfo()->Effects[effIndex].CalcRadius(GetCaster()); + float angle = (urand(0, 1) ? -1 : 1) * (frand(0.75f, 1.0f) * M_PI); + + Position pos; + GetCaster()->GetNearPosition(pos, dist, angle); + GetHitDest()->Relocate(&pos); + } + + void Register() OVERRIDE + { + OnEffectHit += SpellEffectFn(spell_q12308_escape_from_silverbrook_summon_worgen_SpellScript::ModDest, EFFECT_0, SPELL_EFFECT_SUMMON); + } + }; + + SpellScript* GetSpellScript() const OVERRIDE + { + return new spell_q12308_escape_from_silverbrook_summon_worgen_SpellScript(); + } +}; + + +enum DeathComesFromOnHigh +{ + SPELL_FORGE_CREDIT = 51974, + SPELL_TOWN_HALL_CREDIT = 51977, + SPELL_SCARLET_HOLD_CREDIT = 51980, + SPELL_CHAPEL_CREDIT = 51982, + + NPC_NEW_AVALON_FORGE = 28525, + NPC_NEW_AVALON_TOWN_HALL = 28543, + NPC_SCARLET_HOLD = 28542, + NPC_CHAPEL_OF_THE_CRIMSON_FLAME = 28544 +}; + +// 51858 - Siphon of Acherus +class spell_q12641_death_comes_from_on_high : public SpellScriptLoader +{ + public: + spell_q12641_death_comes_from_on_high() : SpellScriptLoader("spell_q12641_death_comes_from_on_high") { } + + class spell_q12641_death_comes_from_on_high_SpellScript : public SpellScript + { + PrepareSpellScript(spell_q12641_death_comes_from_on_high_SpellScript); + + bool Validate(SpellInfo const* /*spellInfo*/) OVERRIDE + { + if (!sSpellMgr->GetSpellInfo(SPELL_FORGE_CREDIT) || + !sSpellMgr->GetSpellInfo(SPELL_TOWN_HALL_CREDIT) || + !sSpellMgr->GetSpellInfo(SPELL_SCARLET_HOLD_CREDIT) || + !sSpellMgr->GetSpellInfo(SPELL_CHAPEL_CREDIT)) + return false; + return true; + } + + void HandleDummy(SpellEffIndex /*effIndex*/) + { + uint32 spellId = 0; + + switch (GetHitCreature()->GetEntry()) + { + case NPC_NEW_AVALON_FORGE: + spellId = SPELL_FORGE_CREDIT; + break; + case NPC_NEW_AVALON_TOWN_HALL: + spellId = SPELL_TOWN_HALL_CREDIT; + break; + case NPC_SCARLET_HOLD: + spellId = SPELL_SCARLET_HOLD_CREDIT; + break; + case NPC_CHAPEL_OF_THE_CRIMSON_FLAME: + spellId = SPELL_CHAPEL_CREDIT; + break; + default: + return; + } + + GetCaster()->CastSpell((Unit*)NULL, spellId, true); + } + + void Register() OVERRIDE + { + OnEffectHitTarget += SpellEffectFn(spell_q12641_death_comes_from_on_high_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); + } + }; + + SpellScript* GetSpellScript() const OVERRIDE + { + return new spell_q12641_death_comes_from_on_high_SpellScript(); + } +}; + +// 51769 - Emblazon Runeblade +class spell_q12619_emblazon_runeblade : public SpellScriptLoader +{ + public: + spell_q12619_emblazon_runeblade() : SpellScriptLoader("spell_q12619_emblazon_runeblade") { } + + class spell_q12619_emblazon_runeblade_AuraScript : public AuraScript + { + PrepareAuraScript(spell_q12619_emblazon_runeblade_AuraScript); + + void HandleEffectPeriodic(AuraEffect const* aurEff) + { + PreventDefaultAction(); + if (Unit* caster = GetCaster()) + caster->CastSpell(caster, GetSpellInfo()->Effects[aurEff->GetEffIndex()].TriggerSpell, true, NULL, aurEff); + } + + void Register() OVERRIDE + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_q12619_emblazon_runeblade_AuraScript::HandleEffectPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); + } + }; + + AuraScript* GetAuraScript() const OVERRIDE + { + return new spell_q12619_emblazon_runeblade_AuraScript(); + } +}; + +// 51770 - Emblazon Runeblade +class spell_q12619_emblazon_runeblade_effect : public SpellScriptLoader +{ + public: + spell_q12619_emblazon_runeblade_effect() : SpellScriptLoader("spell_q12619_emblazon_runeblade_effect") { } + + class spell_q12619_emblazon_runeblade_effect_SpellScript : public SpellScript + { + PrepareSpellScript(spell_q12619_emblazon_runeblade_effect_SpellScript); + + void HandleScript(SpellEffIndex /*effIndex*/) + { + GetCaster()->CastSpell(GetCaster(), uint32(GetEffectValue()), false); + } + + void Register() OVERRIDE + { + OnEffectHit += SpellEffectFn(spell_q12619_emblazon_runeblade_effect_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const OVERRIDE + { + return new spell_q12619_emblazon_runeblade_effect_SpellScript(); + } +}; + void AddSC_quest_spell_scripts() { new spell_q55_sacred_cleansing(); @@ -1922,4 +2207,10 @@ void AddSC_quest_spell_scripts() new spell_q12847_summon_soul_moveto_bunny(); new spell_q13011_bear_flank_master(); new spell_q13086_cannons_target(); + new spell_q12690_burst_at_the_seams(); + new spell_q12308_escape_from_silverbrook_summon_worgen(); + new spell_q12308_escape_from_silverbrook(); + new spell_q12641_death_comes_from_on_high(); + new spell_q12619_emblazon_runeblade(); + new spell_q12619_emblazon_runeblade_effect(); } diff --git a/src/server/scripts/Spells/spell_shaman.cpp b/src/server/scripts/Spells/spell_shaman.cpp index 3bf305d73c9..caae7944f78 100644 --- a/src/server/scripts/Spells/spell_shaman.cpp +++ b/src/server/scripts/Spells/spell_shaman.cpp @@ -512,9 +512,9 @@ class spell_sha_flame_shock : public SpellScriptLoader // Lava Flows if (AuraEffect const* aurEff = caster->GetDummyAuraEffect(SPELLFAMILY_SHAMAN, SHAMAN_ICON_ID_SHAMAN_LAVA_FLOW, EFFECT_0)) { - SpellInfo const* firstRankSpellInfo = sSpellMgr->GetSpellInfo(SPELL_SHAMAN_LAVA_FLOWS_R1); - if (!aurEff->GetSpellInfo()->IsRankOf(firstRankSpellInfo)) - return; + if (SpellInfo const* firstRankSpellInfo = sSpellMgr->GetSpellInfo(SPELL_SHAMAN_LAVA_FLOWS_R1)) + if (!aurEff->GetSpellInfo()->IsRankOf(firstRankSpellInfo)) + return; int32 basepoints = aurEff->GetAmount(); caster->CastCustomSpell(caster, SPELL_SHAMAN_LAVA_FLOWS_TRIGGERED_R1, &basepoints, NULL, NULL, true); diff --git a/src/server/scripts/Spells/spell_warlock.cpp b/src/server/scripts/Spells/spell_warlock.cpp index 0b24d200477..bae21d0baea 100644 --- a/src/server/scripts/Spells/spell_warlock.cpp +++ b/src/server/scripts/Spells/spell_warlock.cpp @@ -112,7 +112,7 @@ class spell_warl_aftermath : public SpellScriptLoader { PreventDefaultAction(); - if (roll_chance_i(aurEff->GetAmount())) + if (eventInfo.GetProcTarget() && roll_chance_i(aurEff->GetAmount())) GetTarget()->CastSpell(eventInfo.GetProcTarget(), SPELL_WARLOCK_AFTERMATH_STUN, true, NULL, aurEff); } } diff --git a/src/server/scripts/Spells/spell_warrior.cpp b/src/server/scripts/Spells/spell_warrior.cpp index c81d3aaae62..d80cab12c26 100644 --- a/src/server/scripts/Spells/spell_warrior.cpp +++ b/src/server/scripts/Spells/spell_warrior.cpp @@ -750,7 +750,7 @@ class spell_warr_second_wind_proc : public SpellScriptLoader { if (eventInfo.GetProcTarget() == GetTarget()) return false; - if (!(eventInfo.GetDamageInfo() || eventInfo.GetDamageInfo()->GetSpellInfo()->GetAllEffectsMechanicMask() & ((1 << MECHANIC_ROOT) | (1 << MECHANIC_STUN)))) + if (!eventInfo.GetDamageInfo()->GetSpellInfo() || !(eventInfo.GetDamageInfo()->GetSpellInfo()->GetAllEffectsMechanicMask() & ((1 << MECHANIC_ROOT) | (1 << MECHANIC_STUN)))) return false; return true; } diff --git a/src/server/scripts/World/achievement_scripts.cpp b/src/server/scripts/World/achievement_scripts.cpp index 94e448bd9bc..6cd5e962c02 100644 --- a/src/server/scripts/World/achievement_scripts.cpp +++ b/src/server/scripts/World/achievement_scripts.cpp @@ -279,6 +279,17 @@ class achievement_flirt_with_disaster_perf_check : public AchievementCriteriaScr } }; +class achievement_killed_exp_or_honor_target : public AchievementCriteriaScript +{ + public: + achievement_killed_exp_or_honor_target() : AchievementCriteriaScript("achievement_killed_exp_or_honor_target") { } + + bool OnCheck(Player* player, Unit* target) OVERRIDE + { + return target && player->isHonorOrXPTarget(target); + } +}; + void AddSC_achievement_scripts() { new achievement_resilient_victory(); @@ -298,4 +309,5 @@ void AddSC_achievement_scripts() new achievement_tilted(); new achievement_not_even_a_scratch(); new achievement_flirt_with_disaster_perf_check(); + new achievement_killed_exp_or_honor_target(); } diff --git a/src/server/scripts/World/npcs_special.cpp b/src/server/scripts/World/npcs_special.cpp index 1348e433de3..0872038d377 100644 --- a/src/server/scripts/World/npcs_special.cpp +++ b/src/server/scripts/World/npcs_special.cpp @@ -628,7 +628,7 @@ public: void PatientDied(Location* point) { - Player* player = Unit::GetPlayer(*me, PlayerGUID); + Player* player = ObjectAccessor::GetPlayer(*me, PlayerGUID); if (player && ((player->GetQuestStatus(6624) == QUEST_STATUS_INCOMPLETE) || (player->GetQuestStatus(6622) == QUEST_STATUS_INCOMPLETE))) { ++PatientDiedCount; @@ -1569,130 +1569,34 @@ public: ## npc_brewfest_reveler ####*/ -class npc_brewfest_reveler : public CreatureScript +enum BrewfestReveler { -public: - npc_brewfest_reveler() : CreatureScript("npc_brewfest_reveler") { } - - struct npc_brewfest_revelerAI : public ScriptedAI - { - npc_brewfest_revelerAI(Creature* creature) : ScriptedAI(creature) {} - void ReceiveEmote(Player* player, uint32 emote) OVERRIDE - { - if (!IsHolidayActive(HOLIDAY_BREWFEST)) - return; - - if (emote == TEXT_EMOTE_DANCE) - me->CastSpell(player, 41586, false); - } - }; - - CreatureAI* GetAI(Creature* creature) const OVERRIDE - { - return new npc_brewfest_revelerAI(creature); - } + SPELL_BREWFEST_TOAST = 41586 }; - -#define SAY_RANDOM_MOJO0 "Now that's what I call froggy-style!" -#define SAY_RANDOM_MOJO1 "Your lily pad or mine?" -#define SAY_RANDOM_MOJO2 "This won't take long, did it?" -#define SAY_RANDOM_MOJO3 "I thought you'd never ask!" -#define SAY_RANDOM_MOJO4 "I promise not to give you warts..." -#define SAY_RANDOM_MOJO5 "Feelin' a little froggy, are ya?" -#define SAY_RANDOM_MOJO6a "Listen, " -#define SAY_RANDOM_MOJO6b ", I know of a little swamp not too far from here...." -#define SAY_RANDOM_MOJO7 "There's just never enough Mojo to go around..." - -class npc_mojo : public CreatureScript +class npc_brewfest_reveler : public CreatureScript { -public: - npc_mojo() : CreatureScript("npc_mojo") { } + public: + npc_brewfest_reveler() : CreatureScript("npc_brewfest_reveler") { } - struct npc_mojoAI : public ScriptedAI - { - npc_mojoAI(Creature* creature) : ScriptedAI(creature) {Reset();} - uint32 hearts; - uint64 victimGUID; - void Reset() OVERRIDE + struct npc_brewfest_revelerAI : public ScriptedAI { - victimGUID = 0; - hearts = 15000; - if (Unit* own = me->GetOwner()) - me->GetMotionMaster()->MoveFollow(own, 0, 0); - } - - void EnterCombat(Unit* /*who*/)OVERRIDE {} + npc_brewfest_revelerAI(Creature* creature) : ScriptedAI(creature) { } - void UpdateAI(uint32 diff) OVERRIDE - { - if (me->HasAura(20372)) + void ReceiveEmote(Player* player, uint32 emote) OVERRIDE { - if (hearts <= diff) - { - me->RemoveAurasDueToSpell(20372); - hearts = 15000; - } hearts -= diff; - } - } - - void ReceiveEmote(Player* player, uint32 emote) OVERRIDE - { - me->HandleEmoteCommand(emote); - Unit* owner = me->GetOwner(); - if (emote != TEXT_EMOTE_KISS || !owner || owner->GetTypeId() != TYPEID_PLAYER || - owner->ToPlayer()->GetTeam() != player->GetTeam()) - { - return; - } + if (!IsHolidayActive(HOLIDAY_BREWFEST)) + return; - std::string whisp = ""; - switch (rand() % 8) - { - case 0: - whisp.append(SAY_RANDOM_MOJO0); - break; - case 1: - whisp.append(SAY_RANDOM_MOJO1); - break; - case 2: - whisp.append(SAY_RANDOM_MOJO2); - break; - case 3: - whisp.append(SAY_RANDOM_MOJO3); - break; - case 4: - whisp.append(SAY_RANDOM_MOJO4); - break; - case 5: - whisp.append(SAY_RANDOM_MOJO5); - break; - case 6: - whisp.append(SAY_RANDOM_MOJO6a); - whisp.append(player->GetName()); - whisp.append(SAY_RANDOM_MOJO6b); - break; - case 7: - whisp.append(SAY_RANDOM_MOJO7); - break; + if (emote == TEXT_EMOTE_DANCE) + me->CastSpell(player, SPELL_BREWFEST_TOAST, false); } + }; - me->MonsterWhisper(whisp.c_str(), player->GetGUID()); - if (victimGUID) - if (Player* victim = Unit::GetPlayer(*me, victimGUID)) - victim->RemoveAura(43906); // remove polymorph frog thing - me->AddAura(43906, player); // add polymorph frog thing - victimGUID = player->GetGUID(); - DoCast(me, 20372, true); // tag.hearts - me->GetMotionMaster()->MoveFollow(player, 0, 0); - hearts = 15000; + CreatureAI* GetAI(Creature* creature) const OVERRIDE + { + return new npc_brewfest_revelerAI(creature); } - }; - - CreatureAI* GetAI(Creature* creature) const OVERRIDE - { - return new npc_mojoAI(creature); - } }; enum TrainingDummy @@ -2548,7 +2452,6 @@ void AddSC_npcs_special() new npc_steam_tonk(); new npc_tonk_mine(); new npc_brewfest_reveler(); - new npc_mojo(); new npc_training_dummy(); new npc_wormhole(); new npc_pet_trainer(); diff --git a/src/server/shared/Common.h b/src/server/shared/Common.h index 779eb95e291..6a15d12e02a 100644 --- a/src/server/shared/Common.h +++ b/src/server/shared/Common.h @@ -92,6 +92,7 @@ #include <ace/Guard_T.h> #include <ace/RW_Thread_Mutex.h> #include <ace/Thread_Mutex.h> +#include <ace/OS_NS_time.h> #if PLATFORM == PLATFORM_WINDOWS # include <ace/config-all.h> diff --git a/src/server/shared/CompilerDefs.h b/src/server/shared/CompilerDefs.h index 10cdaf4e179..909dcd1707b 100644 --- a/src/server/shared/CompilerDefs.h +++ b/src/server/shared/CompilerDefs.h @@ -55,11 +55,6 @@ # error "FATAL ERROR: Unknown compiler." #endif -#if COMPILER == COMPILER_MICROSOFT -# pragma warning( disable : 4267 ) // conversion from 'size_t' to 'int', possible loss of data -# pragma warning( disable : 4786 ) // identifier was truncated to '255' characters in the debug information -#endif - #if defined(__cplusplus) && __cplusplus == 201103L # define COMPILER_HAS_CPP11_SUPPORT 1 #else diff --git a/src/server/shared/Cryptography/BigNumber.cpp b/src/server/shared/Cryptography/BigNumber.cpp index 06ea57b662e..bfe92cd6051 100644 --- a/src/server/shared/Cryptography/BigNumber.cpp +++ b/src/server/shared/Cryptography/BigNumber.cpp @@ -22,17 +22,18 @@ #include <openssl/bn.h> #include <openssl/crypto.h> #include <algorithm> +#include <ace/Auto_Ptr.h> BigNumber::BigNumber() - : _bn(BN_new()), _array(NULL) + : _bn(BN_new()) { } BigNumber::BigNumber(BigNumber const& bn) - : _bn(BN_dup(bn._bn)), _array(NULL) + : _bn(BN_dup(bn._bn)) { } BigNumber::BigNumber(uint32 val) - : _bn(BN_new()), _array(NULL) + : _bn(BN_new()) { BN_set_word(_bn, val); } @@ -40,7 +41,6 @@ BigNumber::BigNumber(uint32 val) BigNumber::~BigNumber() { BN_free(_bn); - delete[] _array; } void BigNumber::SetDword(uint32 val) @@ -50,16 +50,21 @@ void BigNumber::SetDword(uint32 val) void BigNumber::SetQword(uint64 val) { - BN_add_word(_bn, (uint32)(val >> 32)); + BN_set_word(_bn, (uint32)(val >> 32)); BN_lshift(_bn, _bn, 32); BN_add_word(_bn, (uint32)(val & 0xFFFFFFFF)); } void BigNumber::SetBinary(uint8 const* bytes, int32 len) { - uint8 t[1000]; - for (int i = 0; i < len; i++) t[i] = bytes[len - 1 - i]; - BN_bin2bn(t, len, _bn); + uint8* array = new uint8[len]; + + for (int i = 0; i < len; i++) + array[i] = bytes[len - 1 - i]; + + BN_bin2bn(array, len, _bn); + + delete[] array; } void BigNumber::SetHexStr(char const* str) @@ -165,29 +170,24 @@ bool BigNumber::isZero() const return BN_is_zero(_bn); } -uint8* BigNumber::AsByteArray(int32 minSize, bool reverse) +ACE_Auto_Array_Ptr<uint8> BigNumber::AsByteArray(int32 minSize, bool littleEndian) { int length = (minSize >= GetNumBytes()) ? minSize : GetNumBytes(); - ACE_GUARD_RETURN(ACE_Mutex, g, _lock, 0); - - if (_array) - { - delete[] _array; - _array = NULL; - } - _array = new uint8[length]; + uint8* array = new uint8[length]; // If we need more bytes than length of BigNumber set the rest to 0 if (length > GetNumBytes()) - memset((void*)_array, 0, length); + memset((void*)array, 0, length); - BN_bn2bin(_bn, (unsigned char *)_array); + BN_bn2bin(_bn, (unsigned char *)array); - if (reverse) - std::reverse(_array, _array + length); + // openssl's BN stores data internally in big endian format, reverse if little endian desired + if (littleEndian) + std::reverse(array, array + length); - return _array; + ACE_Auto_Array_Ptr<uint8> ret(array); + return ret; } char * BigNumber::AsHexStr() const diff --git a/src/server/shared/Cryptography/BigNumber.h b/src/server/shared/Cryptography/BigNumber.h index fe56fd7e6f9..6129a24d1bc 100644 --- a/src/server/shared/Cryptography/BigNumber.h +++ b/src/server/shared/Cryptography/BigNumber.h @@ -20,7 +20,7 @@ #define _AUTH_BIGNUMBER_H #include "Define.h" -#include <ace/Mutex.h> +#include <ace/Auto_Ptr.h> struct bignum_st; @@ -86,17 +86,14 @@ class BigNumber struct bignum_st *BN() { return _bn; } uint32 AsDword(); - uint8* AsByteArray(int32 minSize = 0, bool reverse = true); + + ACE_Auto_Array_Ptr<uint8> AsByteArray(int32 minSize = 0, bool littleEndian = true); char * AsHexStr() const; char * AsDecStr() const; private: struct bignum_st *_bn; - uint8 *_array; - - // This mutex only controls thread-safe access to AsByteArray() and should be replaced with a thread-safe implementation of BigNumber - ACE_Mutex _lock; }; #endif diff --git a/src/server/shared/Cryptography/HMACSHA1.cpp b/src/server/shared/Cryptography/HMACSHA1.cpp index 297b4e90316..c6c49f14a8e 100644 --- a/src/server/shared/Cryptography/HMACSHA1.cpp +++ b/src/server/shared/Cryptography/HMACSHA1.cpp @@ -36,6 +36,11 @@ void HmacHash::UpdateData(const std::string &str) HMAC_Update(&m_ctx, (uint8 const*)str.c_str(), str.length()); } +void HmacHash::UpdateData(const uint8* data, size_t len) +{ + HMAC_Update(&m_ctx, data, len); +} + void HmacHash::Finalize() { uint32 length = 0; @@ -45,7 +50,7 @@ void HmacHash::Finalize() uint8 *HmacHash::ComputeHash(BigNumber* bn) { - HMAC_Update(&m_ctx, bn->AsByteArray(), bn->GetNumBytes()); + HMAC_Update(&m_ctx, bn->AsByteArray().get(), bn->GetNumBytes()); Finalize(); return (uint8*)m_digest; } diff --git a/src/server/shared/Cryptography/HMACSHA1.h b/src/server/shared/Cryptography/HMACSHA1.h index e09e7fdb43c..04b8f7d0277 100644 --- a/src/server/shared/Cryptography/HMACSHA1.h +++ b/src/server/shared/Cryptography/HMACSHA1.h @@ -34,6 +34,7 @@ class HmacHash HmacHash(uint32 len, uint8 *seed); ~HmacHash(); void UpdateData(const std::string &str); + void UpdateData(const uint8* data, size_t len); void Finalize(); uint8 *ComputeHash(BigNumber* bn); uint8 *GetDigest() { return (uint8*)m_digest; } diff --git a/src/server/shared/Cryptography/OpenSSLCrypto.cpp b/src/server/shared/Cryptography/OpenSSLCrypto.cpp new file mode 100644 index 00000000000..417be813347 --- /dev/null +++ b/src/server/shared/Cryptography/OpenSSLCrypto.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2008-2013 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 <OpenSSLCrypto.h> +#include <openssl/crypto.h> +#include <ace/Thread_Mutex.h> +#include <vector> +#include <ace/Thread.h> + +std::vector<ACE_Thread_Mutex*> cryptoLocks; + +static void lockingCallback(int mode, int type, const char* /*file*/, int /*line*/) +{ + if (mode & CRYPTO_LOCK) + cryptoLocks[type]->acquire(); + else + cryptoLocks[type]->release(); +} + +static void threadIdCallback(CRYPTO_THREADID * id) +{ + CRYPTO_THREADID_set_numeric(id, ACE_Thread::self()); +} + +void OpenSSLCrypto::threadsSetup() +{ + cryptoLocks.resize(CRYPTO_num_locks()); + for(int i = 0 ; i < CRYPTO_num_locks(); ++i) + { + cryptoLocks[i] = new ACE_Thread_Mutex(); + } + CRYPTO_THREADID_set_callback(threadIdCallback); + CRYPTO_set_locking_callback(lockingCallback); +} + +void OpenSSLCrypto::threadsCleanup() +{ + CRYPTO_set_locking_callback(NULL); + CRYPTO_THREADID_set_callback(NULL); + for(int i = 0 ; i < CRYPTO_num_locks(); ++i) + { + delete cryptoLocks[i]; + } + cryptoLocks.resize(0); +}
\ No newline at end of file diff --git a/src/server/shared/Cryptography/OpenSSLCrypto.h b/src/server/shared/Cryptography/OpenSSLCrypto.h new file mode 100644 index 00000000000..70071007c5f --- /dev/null +++ b/src/server/shared/Cryptography/OpenSSLCrypto.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2008-2013 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 OPENSSL_CRYPTO_H +#define OPENSSL_CRYPTO_H + +/** +* A group of functions which setup openssl crypto module to work properly in multithreaded enviroment +* If not setup properly - it will crash +*/ +namespace OpenSSLCrypto +{ + /// Needs to be called before threads using openssl are spawned + void threadsSetup(); + /// Needs to be called after threads using openssl are despawned + void threadsCleanup(); +} + +#endif
\ No newline at end of file diff --git a/src/server/shared/Cryptography/SHA1.cpp b/src/server/shared/Cryptography/SHA1.cpp index 00d7e520d51..1f65c88a6f3 100644 --- a/src/server/shared/Cryptography/SHA1.cpp +++ b/src/server/shared/Cryptography/SHA1.cpp @@ -50,7 +50,7 @@ void SHA1Hash::UpdateBigNumbers(BigNumber* bn0, ...) bn = bn0; while (bn) { - UpdateData(bn->AsByteArray(), bn->GetNumBytes()); + UpdateData(bn->AsByteArray().get(), bn->GetNumBytes()); bn = va_arg(v, BigNumber*); } va_end(v); diff --git a/src/server/shared/Database/DatabaseWorkerPool.h b/src/server/shared/Database/DatabaseWorkerPool.h index 5ecadfe18a8..e209beef8b6 100644 --- a/src/server/shared/Database/DatabaseWorkerPool.h +++ b/src/server/shared/Database/DatabaseWorkerPool.h @@ -214,6 +214,9 @@ class DatabaseWorkerPool T* t = GetFreeConnection(); t->Execute(stmt); t->Unlock(); + + //! Delete proxy-class. Not needed anymore + delete stmt; } /** @@ -430,7 +433,7 @@ class DatabaseWorkerPool */ //! Automanaged (internally) pointer to a prepared statement object for usage in upper level code. - //! Pointer is deleted in this->Query(PreparedStatement*) or PreparedStatementTask::~PreparedStatementTask. + //! Pointer is deleted in this->DirectExecute(PreparedStatement*), this->Query(PreparedStatement*) or PreparedStatementTask::~PreparedStatementTask. //! This object is not tied to the prepared statement on the MySQL context yet until execution. PreparedStatement* GetPreparedStatement(uint32 index) { diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.cpp b/src/server/shared/Database/Implementation/CharacterDatabase.cpp index e20334156df..01f059ade0c 100644 --- a/src/server/shared/Database/Implementation/CharacterDatabase.cpp +++ b/src/server/shared/Database/Implementation/CharacterDatabase.cpp @@ -476,6 +476,9 @@ void CharacterDatabaseConnection::DoPrepareStatements() PrepareStatement(CHAR_SEL_GUILD_BANK_ITEM_BY_ENTRY, "SELECT gi.item_guid, gi.guildid, g.name FROM guild_bank_item gi INNER JOIN guild g ON g.guildid = gi.guildid INNER JOIN item_instance ii ON ii.guid = gi.item_guid WHERE ii.itemEntry = ? LIMIT ?", CONNECTION_SYNCH); PrepareStatement(CHAR_DEL_CHAR_ACHIEVEMENT, "DELETE FROM character_achievement WHERE guid = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_DEL_CHAR_ACHIEVEMENT_PROGRESS, "DELETE FROM character_achievement_progress WHERE guid = ?", CONNECTION_ASYNC); + PrepareStatement(CHAR_INS_CHAR_ACHIEVEMENT, "INSERT INTO character_achievement (guid, achievement, date) VALUES (?, ?, ?)", CONNECTION_ASYNC); + PrepareStatement(CHAR_DEL_CHAR_ACHIEVEMENT_PROGRESS_BY_CRITERIA, "DELETE FROM character_achievement_progress WHERE guid = ? AND criteria = ?", CONNECTION_ASYNC); + PrepareStatement(CHAR_INS_CHAR_ACHIEVEMENT_PROGRESS, "INSERT INTO character_achievement_progress (guid, criteria, counter, date) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC); PrepareStatement(CHAR_DEL_CHAR_REPUTATION_BY_FACTION, "DELETE FROM character_reputation WHERE guid = ? AND faction = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_INS_CHAR_REPUTATION_BY_FACTION, "INSERT INTO character_reputation (guid, faction, standing, flags) VALUES (?, ?, ? , ?)", CONNECTION_ASYNC); PrepareStatement(CHAR_DEL_ITEM_REFUND_INSTANCE, "DELETE FROM item_refund_instance WHERE item_guid = ?", CONNECTION_ASYNC); diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.h b/src/server/shared/Database/Implementation/CharacterDatabase.h index 53c309f9ba0..abe1f070953 100755 --- a/src/server/shared/Database/Implementation/CharacterDatabase.h +++ b/src/server/shared/Database/Implementation/CharacterDatabase.h @@ -410,6 +410,9 @@ enum CharacterDatabaseStatements CHAR_SEL_GUILD_BANK_ITEM_BY_ENTRY, CHAR_DEL_CHAR_ACHIEVEMENT, CHAR_DEL_CHAR_ACHIEVEMENT_PROGRESS, + CHAR_INS_CHAR_ACHIEVEMENT, + CHAR_DEL_CHAR_ACHIEVEMENT_PROGRESS_BY_CRITERIA, + CHAR_INS_CHAR_ACHIEVEMENT_PROGRESS, CHAR_DEL_CHAR_REPUTATION_BY_FACTION, CHAR_INS_CHAR_REPUTATION_BY_FACTION, CHAR_DEL_ITEM_REFUND_INSTANCE, diff --git a/src/server/shared/Database/Implementation/LoginDatabase.cpp b/src/server/shared/Database/Implementation/LoginDatabase.cpp index 6113dd61d70..6e01e8f515a 100644 --- a/src/server/shared/Database/Implementation/LoginDatabase.cpp +++ b/src/server/shared/Database/Implementation/LoginDatabase.cpp @@ -37,7 +37,7 @@ void LoginDatabaseConnection::DoPrepareStatements() PrepareStatement(LOGIN_SEL_SESSIONKEY, "SELECT a.sessionkey, a.id, aa.gmlevel FROM account a LEFT JOIN account_access aa ON (a.id = aa.id) WHERE username = ?", CONNECTION_SYNCH); PrepareStatement(LOGIN_UPD_VS, "UPDATE account SET v = ?, s = ? WHERE username = ?", CONNECTION_ASYNC); PrepareStatement(LOGIN_UPD_LOGONPROOF, "UPDATE account SET sessionkey = ?, last_ip = ?, last_login = NOW(), locale = ?, failed_logins = 0, os = ? WHERE username = ?", CONNECTION_ASYNC); - PrepareStatement(LOGIN_SEL_LOGONCHALLENGE, "SELECT a.sha_pass_hash, a.id, a.locked, a.lock_country, a.last_ip, aa.gmlevel, a.v, a.s FROM account a LEFT JOIN account_access aa ON (a.id = aa.id) WHERE a.username = ?", CONNECTION_SYNCH); + PrepareStatement(LOGIN_SEL_LOGONCHALLENGE, "SELECT a.sha_pass_hash, a.id, a.locked, a.lock_country, a.last_ip, aa.gmlevel, a.v, a.s, a.token_key FROM account a LEFT JOIN account_access aa ON (a.id = aa.id) WHERE a.username = ?", CONNECTION_SYNCH); PrepareStatement(LOGIN_SEL_LOGON_COUNTRY, "SELECT country FROM ip2nation WHERE ip < ? ORDER BY ip DESC LIMIT 0,1", CONNECTION_SYNCH); PrepareStatement(LOGIN_UPD_FAILEDLOGINS, "UPDATE account SET failed_logins = failed_logins + 1 WHERE username = ?", CONNECTION_ASYNC); PrepareStatement(LOGIN_SEL_FAILEDLOGINS, "SELECT id, failed_logins FROM account WHERE username = ?", CONNECTION_SYNCH); @@ -56,7 +56,7 @@ void LoginDatabaseConnection::DoPrepareStatements() PrepareStatement(LOGIN_DEL_REALM_CHARACTERS, "DELETE FROM realmcharacters WHERE acctid = ?", CONNECTION_ASYNC); PrepareStatement(LOGIN_INS_REALM_CHARACTERS, "INSERT INTO realmcharacters (numchars, acctid, realmid) VALUES (?, ?, ?)", CONNECTION_ASYNC); PrepareStatement(LOGIN_SEL_SUM_REALM_CHARACTERS, "SELECT SUM(numchars) FROM realmcharacters WHERE acctid = ?", CONNECTION_ASYNC); - PrepareStatement(LOGIN_INS_ACCOUNT, "INSERT INTO account(username, sha_pass_hash, joindate) VALUES(?, ?, NOW())", CONNECTION_SYNCH); + PrepareStatement(LOGIN_INS_ACCOUNT, "INSERT INTO account(username, sha_pass_hash, reg_mail, email, joindate) VALUES(?, ?, ?, ?, NOW())", CONNECTION_SYNCH); PrepareStatement(LOGIN_INS_REALM_CHARACTERS_INIT, "INSERT INTO realmcharacters (realmid, acctid, numchars) SELECT realmlist.id, account.id, 0 FROM realmlist, account LEFT JOIN realmcharacters ON acctid=account.id WHERE acctid IS NULL", CONNECTION_ASYNC); PrepareStatement(LOGIN_UPD_EXPANSION, "UPDATE account SET expansion = ? WHERE id = ?", CONNECTION_ASYNC); PrepareStatement(LOGIN_UPD_ACCOUNT_LOCK, "UPDATE account SET locked = ? WHERE id = ?", CONNECTION_ASYNC); @@ -64,6 +64,8 @@ void LoginDatabaseConnection::DoPrepareStatements() PrepareStatement(LOGIN_INS_LOG, "INSERT INTO logs (time, realm, type, level, string) VALUES (?, ?, ?, ?, ?)", CONNECTION_ASYNC); PrepareStatement(LOGIN_UPD_USERNAME, "UPDATE account SET v = 0, s = 0, username = ?, sha_pass_hash = ? WHERE id = ?", CONNECTION_ASYNC); PrepareStatement(LOGIN_UPD_PASSWORD, "UPDATE account SET v = 0, s = 0, sha_pass_hash = ? WHERE id = ?", CONNECTION_ASYNC); + PrepareStatement(LOGIN_UPD_EMAIL, "UPDATE account SET email = ? WHERE id = ?", CONNECTION_ASYNC); + PrepareStatement(LOGIN_UPD_REG_EMAIL, "UPDATE account SET reg_mail = ? WHERE id = ?", CONNECTION_ASYNC); PrepareStatement(LOGIN_UPD_MUTE_TIME, "UPDATE account SET mutetime = ? , mutereason = ? , muteby = ? WHERE id = ?", CONNECTION_ASYNC); PrepareStatement(LOGIN_UPD_MUTE_TIME_LOGIN, "UPDATE account SET mutetime = ? WHERE id = ?", CONNECTION_ASYNC); PrepareStatement(LOGIN_UPD_LAST_IP, "UPDATE account SET last_ip = ? WHERE username = ?", CONNECTION_ASYNC); @@ -79,7 +81,7 @@ void LoginDatabaseConnection::DoPrepareStatements() PrepareStatement(LOGIN_GET_USERNAME_BY_ID, "SELECT username FROM account WHERE id = ?", CONNECTION_SYNCH); PrepareStatement(LOGIN_SEL_CHECK_PASSWORD, "SELECT 1 FROM account WHERE id = ? AND sha_pass_hash = ?", CONNECTION_SYNCH); PrepareStatement(LOGIN_SEL_CHECK_PASSWORD_BY_NAME, "SELECT 1 FROM account WHERE username = ? AND sha_pass_hash = ?", CONNECTION_SYNCH); - PrepareStatement(LOGIN_SEL_PINFO, "SELECT a.username, aa.gmlevel, a.email, a.last_ip, DATE_FORMAT(a.last_login, '%Y-%m-%d %T'), a.mutetime, a.mutereason, a.muteby, a.failed_logins, a.locked, a.OS FROM account a LEFT JOIN account_access aa ON (a.id = aa.id AND (aa.RealmID = ? OR aa.RealmID = -1)) WHERE a.id = ?", CONNECTION_SYNCH); + PrepareStatement(LOGIN_SEL_PINFO, "SELECT a.username, aa.gmlevel, a.email, a.reg_mail, a.last_ip, DATE_FORMAT(a.last_login, '%Y-%m-%d %T'), a.mutetime, a.mutereason, a.muteby, a.failed_logins, a.locked, a.OS FROM account a LEFT JOIN account_access aa ON (a.id = aa.id AND (aa.RealmID = ? OR aa.RealmID = -1)) WHERE a.id = ?", CONNECTION_SYNCH); PrepareStatement(LOGIN_SEL_PINFO_BANS, "SELECT unbandate, bandate = unbandate, bannedby, banreason FROM account_banned WHERE id = ? AND active ORDER BY bandate ASC LIMIT 1", CONNECTION_SYNCH); PrepareStatement(LOGIN_SEL_GM_ACCOUNTS, "SELECT a.username, aa.gmlevel FROM account a, account_access aa WHERE a.id=aa.id AND aa.gmlevel >= ? AND (aa.realmid = -1 OR aa.realmid = ?)", CONNECTION_SYNCH); PrepareStatement(LOGIN_SEL_ACCOUNT_INFO, "SELECT a.username, a.last_ip, aa.gmlevel, a.expansion FROM account a LEFT JOIN account_access aa ON (a.id = aa.id) WHERE a.id = ?", CONNECTION_SYNCH); @@ -92,6 +94,7 @@ void LoginDatabaseConnection::DoPrepareStatements() PrepareStatement(LOGIN_DEL_ACCOUNT, "DELETE FROM account WHERE id = ?", CONNECTION_ASYNC); PrepareStatement(LOGIN_SEL_IP2NATION_COUNTRY, "SELECT c.country FROM ip2nationCountries c, ip2nation i WHERE i.ip < ? AND c.code = i.country ORDER BY i.ip DESC LIMIT 0,1", CONNECTION_SYNCH); PrepareStatement(LOGIN_SEL_AUTOBROADCAST, "SELECT id, weight, text FROM autobroadcast WHERE realmid = ? OR realmid = -1", CONNECTION_SYNCH); + PrepareStatement(LOGIN_GET_EMAIL_BY_ID, "SELECT email FROM account WHERE id = ?", CONNECTION_SYNCH); PrepareStatement(LOGIN_SEL_ACCOUNT_ACCESS_BY_ID, "SELECT gmlevel, RealmID FROM account_access WHERE id = ? and (RealmID = ? OR RealmID = -1) ORDER BY gmlevel desc", CONNECTION_SYNCH); diff --git a/src/server/shared/Database/Implementation/LoginDatabase.h b/src/server/shared/Database/Implementation/LoginDatabase.h index 97cf91fc178..47fa48c6ada 100644 --- a/src/server/shared/Database/Implementation/LoginDatabase.h +++ b/src/server/shared/Database/Implementation/LoginDatabase.h @@ -84,6 +84,8 @@ enum LoginDatabaseStatements LOGIN_INS_LOG, LOGIN_UPD_USERNAME, LOGIN_UPD_PASSWORD, + LOGIN_UPD_EMAIL, + LOGIN_UPD_REG_EMAIL, LOGIN_UPD_MUTE_TIME, LOGIN_UPD_MUTE_TIME_LOGIN, LOGIN_UPD_LAST_IP, @@ -112,6 +114,7 @@ enum LoginDatabaseStatements LOGIN_DEL_ACCOUNT, LOGIN_SEL_IP2NATION_COUNTRY, LOGIN_SEL_AUTOBROADCAST, + LOGIN_GET_EMAIL_BY_ID, LOGIN_SEL_ACCOUNT_ACCESS_BY_ID, LOGIN_SEL_RBAC_ACCOUNT_GROUPS, diff --git a/src/server/shared/Database/Implementation/WorldDatabase.cpp b/src/server/shared/Database/Implementation/WorldDatabase.cpp index 75bafb571e9..addfc8f0f7b 100644 --- a/src/server/shared/Database/Implementation/WorldDatabase.cpp +++ b/src/server/shared/Database/Implementation/WorldDatabase.cpp @@ -77,7 +77,7 @@ void WorldDatabaseConnection::DoPrepareStatements() PrepareStatement(WORLD_DEL_CREATURE, "DELETE FROM creature WHERE guid = ?", CONNECTION_ASYNC); PrepareStatement(WORLD_INS_CREATURE_TRANSPORT, "INSERT INTO creature_transport (guid, npc_entry, transport_entry, TransOffsetX, TransOffsetY, TransOffsetZ, TransOffsetO) values (?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC); PrepareStatement(WORLD_UPD_CREATURE_TRANSPORT_EMOTE, "UPDATE creature_transport SET emote = ? WHERE transport_entry = ? AND guid = ?", CONNECTION_ASYNC); - PrepareStatement(WORLD_SEL_COMMANDS, "SELECT name, security, help FROM command", CONNECTION_SYNCH); + PrepareStatement(WORLD_SEL_COMMANDS, "SELECT name, permission, help FROM command", CONNECTION_SYNCH); PrepareStatement(WORLD_SEL_CREATURE_TEMPLATE, "SELECT difficulty_entry_1, difficulty_entry_2, difficulty_entry_3, KillCredit1, KillCredit2, modelid1, modelid2, modelid3, modelid4, name, subname, IconName, gossip_menu_id, minlevel, maxlevel, exp, exp_unk, faction_A, faction_H, npcflag, speed_walk, speed_run, scale, rank, mindmg, maxdmg, dmgschool, attackpower, dmg_multiplier, baseattacktime, rangeattacktime, unit_class, unit_flags, unit_flags2, dynamicflags, family, trainer_type, trainer_class, trainer_race, minrangedmg, maxrangedmg, rangedattackpower, type, type_flags, type_flags2, lootid, pickpocketloot, skinloot, resistance1, resistance2, resistance3, resistance4, resistance5, resistance6, spell1, spell2, spell3, spell4, spell5, spell6, spell7, spell8, PetSpellDataId, VehicleId, mingold, maxgold, AIName, MovementType, InhabitType, HoverHeight, Health_mod, Mana_mod, Mana_mod_extra, Armor_mod, RacialLeader, questItem1, questItem2, questItem3, questItem4, questItem5, questItem6, movementId, RegenHealth, mechanic_immune_mask, flags_extra, ScriptName FROM creature_template WHERE entry = ?", CONNECTION_SYNCH); PrepareStatement(WORLD_SEL_WAYPOINT_SCRIPT_BY_ID, "SELECT guid, delay, command, datalong, datalong2, dataint, x, y, z, o FROM waypoint_scripts WHERE id = ?", CONNECTION_SYNCH); PrepareStatement(WORLD_SEL_ITEM_TEMPLATE_BY_NAME, "SELECT entry FROM item_template WHERE name = ?", CONNECTION_SYNCH); diff --git a/src/server/shared/Database/QueryResult.cpp b/src/server/shared/Database/QueryResult.cpp index 4f4c0ec51f4..9413e28a0c0 100644 --- a/src/server/shared/Database/QueryResult.cpp +++ b/src/server/shared/Database/QueryResult.cpp @@ -60,6 +60,9 @@ m_length(NULL) if (mysql_stmt_store_result(m_stmt)) { TC_LOG_WARN(LOG_FILTER_SQL, "%s:mysql_stmt_store_result, cannot bind result from MySQL server. Error: %s", __FUNCTION__, mysql_stmt_error(m_stmt)); + delete[] m_rBind; + delete[] m_isNull; + delete[] m_length; return; } diff --git a/src/server/shared/Debugging/WheatyExceptionReport.cpp b/src/server/shared/Debugging/WheatyExceptionReport.cpp index d4bd630ca25..f4da4093dfa 100644 --- a/src/server/shared/Debugging/WheatyExceptionReport.cpp +++ b/src/server/shared/Debugging/WheatyExceptionReport.cpp @@ -350,13 +350,12 @@ void WheatyExceptionReport::PrintSystemInfo() //=========================================================================== void WheatyExceptionReport::printTracesForAllThreads() { - HANDLE hThreadSnap = INVALID_HANDLE_VALUE; THREADENTRY32 te32; DWORD dwOwnerPID = GetCurrentProcessId(); m_hProcess = GetCurrentProcess(); // Take a snapshot of all running threads - hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); + HANDLE hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); if (hThreadSnap == INVALID_HANDLE_VALUE) return; diff --git a/src/server/shared/Logging/Appender.cpp b/src/server/shared/Logging/Appender.cpp index cde94fe3a7c..f47cbc3b095 100644 --- a/src/server/shared/Logging/Appender.cpp +++ b/src/server/shared/Logging/Appender.cpp @@ -20,9 +20,10 @@ std::string LogMessage::getTimeStr(time_t time) { - tm* aTm = localtime(&time); + tm aTm; + ACE_OS::localtime_r(&time, &aTm); char buf[20]; - snprintf(buf, 20, "%04d-%02d-%02d_%02d:%02d:%02d", aTm->tm_year+1900, aTm->tm_mon+1, aTm->tm_mday, aTm->tm_hour, aTm->tm_min, aTm->tm_sec); + snprintf(buf, 20, "%04d-%02d-%02d_%02d:%02d:%02d", aTm.tm_year+1900, aTm.tm_mon+1, aTm.tm_mday, aTm.tm_hour, aTm.tm_min, aTm.tm_sec); return std::string(buf); } diff --git a/src/server/shared/Logging/AppenderFile.cpp b/src/server/shared/Logging/AppenderFile.cpp index 93d53bcc30d..54458346bb9 100644 --- a/src/server/shared/Logging/AppenderFile.cpp +++ b/src/server/shared/Logging/AppenderFile.cpp @@ -40,7 +40,7 @@ AppenderFile::~AppenderFile() void AppenderFile::_write(LogMessage const& message) { - bool exceedMaxSize = maxFileSize > 0 && (fileSize + message.Size()) > maxFileSize; + bool exceedMaxSize = maxFileSize > 0 && (fileSize.value() + message.Size()) > maxFileSize; if (dynamicName) { @@ -56,7 +56,7 @@ void AppenderFile::_write(LogMessage const& message) fprintf(logfile, "%s%s", message.prefix.c_str(), message.text.c_str()); fflush(logfile); - fileSize += message.Size(); + fileSize += uint64(message.Size()); if (dynamicName) CloseFile(); diff --git a/src/server/shared/Logging/AppenderFile.h b/src/server/shared/Logging/AppenderFile.h index c15974799e1..de94a46d692 100644 --- a/src/server/shared/Logging/AppenderFile.h +++ b/src/server/shared/Logging/AppenderFile.h @@ -19,6 +19,7 @@ #define APPENDERFILE_H #include "Appender.h" +#include "ace/Atomic_Op.h" class AppenderFile: public Appender { @@ -37,7 +38,7 @@ class AppenderFile: public Appender bool dynamicName; bool backup; uint64 maxFileSize; - uint64 fileSize; + ACE_Atomic_Op<ACE_Thread_Mutex, uint64> fileSize; }; #endif diff --git a/src/server/shared/Logging/Log.cpp b/src/server/shared/Logging/Log.cpp index be7aab9cf5e..e6400176155 100644 --- a/src/server/shared/Logging/Log.cpp +++ b/src/server/shared/Logging/Log.cpp @@ -295,7 +295,8 @@ void Log::write(LogMessage* msg) std::string Log::GetTimestampStr() { time_t t = time(NULL); - tm* aTm = localtime(&t); + tm aTm; + ACE_OS::localtime_r(&t, &aTm); // YYYY year // MM month (2 digits 01-12) // DD day (2 digits 01-31) @@ -303,7 +304,7 @@ std::string Log::GetTimestampStr() // MM minutes (2 digits 00-59) // SS seconds (2 digits 00-59) char buf[20]; - snprintf(buf, 20, "%04d-%02d-%02d_%02d-%02d-%02d", aTm->tm_year+1900, aTm->tm_mon+1, aTm->tm_mday, aTm->tm_hour, aTm->tm_min, aTm->tm_sec); + snprintf(buf, 20, "%04d-%02d-%02d_%02d-%02d-%02d", aTm.tm_year+1900, aTm.tm_mon+1, aTm.tm_mday, aTm.tm_hour, aTm.tm_min, aTm.tm_sec); return std::string(buf); } diff --git a/src/server/shared/Packets/ByteBuffer.h b/src/server/shared/Packets/ByteBuffer.h index 51b1a615bf1..c30dfff2f40 100644 --- a/src/server/shared/Packets/ByteBuffer.h +++ b/src/server/shared/Packets/ByteBuffer.h @@ -23,6 +23,7 @@ #include "Errors.h" #include "ByteConverter.h" +#include <ace/OS_NS_time.h> #include <exception> #include <list> #include <map> @@ -585,8 +586,9 @@ class ByteBuffer void AppendPackedTime(time_t time) { - tm* lt = localtime(&time); - append<uint32>((lt->tm_year - 100) << 24 | lt->tm_mon << 20 | (lt->tm_mday - 1) << 14 | lt->tm_wday << 11 | lt->tm_hour << 6 | lt->tm_min); + tm lt; + ACE_OS::localtime_r(&time, <); + append<uint32>((lt.tm_year - 100) << 24 | lt.tm_mon << 20 | (lt.tm_mday - 1) << 14 | lt.tm_wday << 11 | lt.tm_hour << 6 | lt.tm_min); } void put(size_t pos, const uint8 *src, size_t cnt) diff --git a/src/server/shared/Threading/Threading.cpp b/src/server/shared/Threading/Threading.cpp index bd96c359616..1ed29d5106a 100644 --- a/src/server/shared/Threading/Threading.cpp +++ b/src/server/shared/Threading/Threading.cpp @@ -59,10 +59,10 @@ ThreadPriority::ThreadPriority() } } - //since we have only 7(seven) values in enum Priority - //and 3 we know already (Idle, Normal, Realtime) so - //we need to split each list [Idle...Normal] and [Normal...Realtime] - //into ¹ piesces + // since we have only 7(seven) values in enum Priority + // and 3 we know already (Idle, Normal, Realtime) so + // we need to split each list [Idle...Normal] and [Normal...Realtime] + // into pieces const size_t _divider = 4; size_t _div = (norm_pos - min_pos) / _divider; if (_div == 0) @@ -130,10 +130,13 @@ bool Thread::start() if (m_task == 0 || m_iThreadId != 0) return false; + // incRef before spawing the thread, otherwise Thread::ThreadTask() might call decRef and delete m_task + m_task->incReference(); + bool res = (ACE_Thread::spawn(&Thread::ThreadTask, (void*)m_task, THREADFLAG, &m_iThreadId, &m_hThreadHandle) == 0); - if (res) - m_task->incReference(); + if (!res) + m_task->decReference(); return res; } diff --git a/src/server/shared/Utilities/Timer.h b/src/server/shared/Utilities/Timer.h index 5bc19a2b779..b0b395865b4 100644 --- a/src/server/shared/Utilities/Timer.h +++ b/src/server/shared/Utilities/Timer.h @@ -66,7 +66,7 @@ struct IntervalTimer void Reset() { if (_current >= _interval) - _current -= _interval; + _current %= _interval; } void SetCurrent(time_t current) diff --git a/src/server/shared/Utilities/Util.cpp b/src/server/shared/Utilities/Util.cpp index 32ff396e1c1..e53f0c9b839 100644 --- a/src/server/shared/Utilities/Util.cpp +++ b/src/server/shared/Utilities/Util.cpp @@ -215,7 +215,8 @@ uint32 TimeStringToSecs(const std::string& timestring) std::string TimeToTimestampStr(time_t t) { - tm* aTm = localtime(&t); + tm aTm; + ACE_OS::localtime_r(&t, &aTm); // YYYY year // MM month (2 digits 01-12) // DD day (2 digits 01-31) @@ -223,7 +224,7 @@ std::string TimeToTimestampStr(time_t t) // MM minutes (2 digits 00-59) // SS seconds (2 digits 00-59) char buf[20]; - snprintf(buf, 20, "%04d-%02d-%02d_%02d-%02d-%02d", aTm->tm_year+1900, aTm->tm_mon+1, aTm->tm_mday, aTm->tm_hour, aTm->tm_min, aTm->tm_sec); + snprintf(buf, 20, "%04d-%02d-%02d_%02d-%02d-%02d", aTm.tm_year+1900, aTm.tm_mon+1, aTm.tm_mday, aTm.tm_hour, aTm.tm_min, aTm.tm_sec); return std::string(buf); } diff --git a/src/server/shared/Utilities/Util.h b/src/server/shared/Utilities/Util.h index 5d1ce862d21..d814c5b59e7 100644 --- a/src/server/shared/Utilities/Util.h +++ b/src/server/shared/Utilities/Util.h @@ -20,6 +20,7 @@ #define _UTIL_H #include "Define.h" +#include "Errors.h" #include <algorithm> #include <string> @@ -173,7 +174,7 @@ inline bool isExtendedLatinCharacter(wchar_t wchar) return true; if (wchar >= 0x00C0 && wchar <= 0x00D6) // LATIN CAPITAL LETTER A WITH GRAVE - LATIN CAPITAL LETTER O WITH DIAERESIS return true; - if (wchar >= 0x00D8 && wchar <= 0x00DF) // LATIN CAPITAL LETTER O WITH STROKE - LATIN CAPITAL LETTER THORN + if (wchar >= 0x00D8 && wchar <= 0x00DE) // LATIN CAPITAL LETTER O WITH STROKE - LATIN CAPITAL LETTER THORN return true; if (wchar == 0x00DF) // LATIN SMALL LETTER SHARP S return true; @@ -242,7 +243,7 @@ inline bool isNumericOrSpace(wchar_t wchar) return isNumeric(wchar) || wchar == L' '; } -inline bool isBasicLatinString(std::wstring wstr, bool numericOrSpace) +inline bool isBasicLatinString(const std::wstring &wstr, bool numericOrSpace) { for (size_t i = 0; i < wstr.size(); ++i) if (!isBasicLatinCharacter(wstr[i]) && (!numericOrSpace || !isNumericOrSpace(wstr[i]))) @@ -250,7 +251,7 @@ inline bool isBasicLatinString(std::wstring wstr, bool numericOrSpace) return true; } -inline bool isExtendedLatinString(std::wstring wstr, bool numericOrSpace) +inline bool isExtendedLatinString(const std::wstring &wstr, bool numericOrSpace) { for (size_t i = 0; i < wstr.size(); ++i) if (!isExtendedLatinCharacter(wstr[i]) && (!numericOrSpace || !isNumericOrSpace(wstr[i]))) @@ -258,7 +259,7 @@ inline bool isExtendedLatinString(std::wstring wstr, bool numericOrSpace) return true; } -inline bool isCyrillicString(std::wstring wstr, bool numericOrSpace) +inline bool isCyrillicString(const std::wstring &wstr, bool numericOrSpace) { for (size_t i = 0; i < wstr.size(); ++i) if (!isCyrillicCharacter(wstr[i]) && (!numericOrSpace || !isNumericOrSpace(wstr[i]))) @@ -266,7 +267,7 @@ inline bool isCyrillicString(std::wstring wstr, bool numericOrSpace) return true; } -inline bool isEastAsianString(std::wstring wstr, bool numericOrSpace) +inline bool isEastAsianString(const std::wstring &wstr, bool numericOrSpace) { for (size_t i = 0; i < wstr.size(); ++i) if (!isEastAsianCharacter(wstr[i]) && (!numericOrSpace || !isNumericOrSpace(wstr[i]))) @@ -532,4 +533,36 @@ public: } }; +enum ComparisionType +{ + COMP_TYPE_EQ = 0, + COMP_TYPE_HIGH, + COMP_TYPE_LOW, + COMP_TYPE_HIGH_EQ, + COMP_TYPE_LOW_EQ, + COMP_TYPE_MAX +}; + +template <class T> +bool CompareValues(ComparisionType type, T val1, T val2) +{ + switch (type) + { + case COMP_TYPE_EQ: + return val1 == val2; + case COMP_TYPE_HIGH: + return val1 > val2; + case COMP_TYPE_LOW: + return val1 < val2; + case COMP_TYPE_HIGH_EQ: + return val1 >= val2; + case COMP_TYPE_LOW_EQ: + return val1 <= val2; + default: + // incorrect parameter + ASSERT(false); + return false; + } +} + #endif diff --git a/src/server/worldserver/CommandLine/CliRunnable.cpp b/src/server/worldserver/CommandLine/CliRunnable.cpp index e136269e2a0..1ebb58eef1a 100644 --- a/src/server/worldserver/CommandLine/CliRunnable.cpp +++ b/src/server/worldserver/CommandLine/CliRunnable.cpp @@ -175,6 +175,8 @@ void CliRunnable::run() { #if PLATFORM == PLATFORM_WINDOWS printf("TC>"); +#else + free(command_str); #endif continue; } @@ -184,6 +186,8 @@ void CliRunnable::run() { #if PLATFORM == PLATFORM_WINDOWS printf("TC>"); +#else + free(command_str); #endif continue; } @@ -192,6 +196,7 @@ void CliRunnable::run() sWorld->QueueCliCommand(new CliCommandHolder(NULL, command.c_str(), &utf8print, &commandFinished)); #if PLATFORM != PLATFORM_WINDOWS add_history(command.c_str()); + free(command_str); #endif } else if (feof(stdin)) diff --git a/src/server/worldserver/Master.cpp b/src/server/worldserver/Master.cpp index 6fd57179140..d9b97cfd3f5 100644 --- a/src/server/worldserver/Master.cpp +++ b/src/server/worldserver/Master.cpp @@ -44,6 +44,7 @@ #include "RealmList.h" #include "BigNumber.h" +#include "OpenSSLCrypto.h" #ifdef _WIN32 #include "ServiceWin32.h" @@ -102,10 +103,11 @@ public: ACE_Based::Thread::Sleep(1000); uint32 curtime = getMSTime(); // normal work - if (_loops != World::m_worldLoopCounter) + uint32 worldLoopCounter = World::m_worldLoopCounter.value(); + if (_loops != worldLoopCounter) { _lastChange = curtime; - _loops = World::m_worldLoopCounter; + _loops = worldLoopCounter; } // possible freeze else if (getMSTimeDiff(_lastChange, curtime) > _delaytime) @@ -121,6 +123,7 @@ public: /// Main function int Master::Run() { + OpenSSLCrypto::threadsSetup(); BigNumber seed1; seed1.SetRand(16 * 8); @@ -368,6 +371,7 @@ int Master::Run() // fixes a memory leak related to detaching threads from the module //UnloadScriptingModule(); + OpenSSLCrypto::threadsCleanup(); // Exit the process with specified return value return World::GetExitCode(); } diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist index ce4312672d3..dfd382c310e 100644 --- a/src/server/worldserver/worldserver.conf.dist +++ b/src/server/worldserver/worldserver.conf.dist @@ -29,6 +29,7 @@ # CUSTOM SERVER OPTIONS # LOGGING SYSTEM SETTINGS # CURRENCIES SETTINGS +# PACKET SPOOF PROTECTION SETTINGS # ################################################################################################### @@ -870,6 +871,13 @@ Instance.ResetTimeHour = 4 Instance.UnloadDelay = 1800000 # +# InstancesResetAnnounce +# Description: Announce the reset of one instance to whole party. +# Default: false - (Disabled, don't show, blizzlike) +# true - (Enabled, show) + +InstancesResetAnnounce = false +# # Quests.LowLevelHideDiff # Description: Level difference between player and quest level at which quests are # considered low-level and are not shown via exclamation mark (!) at quest @@ -1080,7 +1088,6 @@ AllowTickets = 1 DungeonFinder.OptionsMask = 1 - # # DBC.EnforceItemAttributes # Description: Disallow overriding item attributes stored in DBC files with values from the @@ -1106,6 +1113,15 @@ AccountInstancesPerHour = 5 RBAC.DefaultGroups = "" # +# Account.PasswordChangeSecurity +# Description: Controls how secure the password changes are. +# Default: 0 - None (Old and new password) +# 1 - Email (Email confirmation necessary) +# 2 - RBAC (RBAC enable or disables email confirmation per group) + +Account.PasswordChangeSecurity = 0 + +# ################################################################################################### ################################################################################################### @@ -1178,7 +1194,6 @@ Warden.BanDuration = 86400 ################################################################################################### # PLAYER INTERACTION # -# # AllowTwoSide.Interaction.Calendar # Description: Allow calendar invites between factions. # Default: 0 - (Disabled) @@ -2097,6 +2112,29 @@ Battleground.GiveXPForKills = 0 Battleground.Random.ResetHour = 6 # +# Battleground.RewardWinnerHonorFirst +# Battleground.RewardWinnerConquestFirst +# Battleground.RewardWinnerHonorLast +# Battleground.RewardWinnerConquestLast +# Battleground.RewardLoserHonorFirst +# Battleground.RewardLoserHonorLast +# Description: Random Battlegrounds / call to the arms rewards +# Default: 30 - Battleground.RewardWinnerHonorFirst +# 25 - Battleground.RewardWinnerArenaFirst +# 15 - Battleground.RewardWinnerHonorLast +# 0 - Battleground.RewardWinnerArenaLast +# 5 - Battleground.RewardLoserHonorFirst +# 5 - Battleground.RewardLoserHonorLast +# + +Battleground.RewardWinnerHonorFirst = 27000 +Battleground.RewardWinnerConquestFirst = 10000 +Battleground.RewardWinnerHonorLast = 13500 +Battleground.RewardWinnerConquestLast = 5000 +Battleground.RewardLoserHonorFirst = 4500 +Battleground.RewardLoserHonorLast = 3500 + +# ################################################################################################### ################################################################################################### @@ -2575,7 +2613,6 @@ UI.ShowQuestLevelsInDialogs = 0 ################################################################################################### ################################################################################################### -# # LOGGING SYSTEM SETTINGS # # Appender config values: Given a appender "name" @@ -2764,7 +2801,6 @@ Log.Async.Enable = 0 ################################################################################################### ################################################################################################### -# # GUILD LEVELING SETTINGS # # Guild.LevelingEnabled @@ -2826,7 +2862,6 @@ Guild.WeeklyReputationCap = 4375 ################################################################################################### ################################################################################################### -# # CURRENCIES SETTINGS # # Currency.ResetInterval @@ -2910,3 +2945,36 @@ Currency.ConquestPointsArenaReward = 180 # ################################################################################################### +# PACKET SPOOF PROTECTION SETTINGS +# +# These settings determine which action to take when harmful packet spoofing is detected. +# +# PacketSpoof.Policy +# Description: Determines the course of action when packet spoofing is detected. +# Default: 1 - Log + kick +# 0 - Log only (LOG_FILTER_NETWORKIO) +# 2 - Log + kick + ban + +PacketSpoof.Policy = 1 + +# +# PacketSpoof.BanMode +# Description: If PacketSpoof.Policy equals 2, this will determine the ban mode. +# Note: Banning by character not supported for logical reasons. +# Default: 0 - Ban Account +# 2 - Ban IP +# + +PacketSpoof.BanMode = 0 + +# +# PacketSpoof.BanDuration +# Description: Duration of the ban in seconds. Only valid if PacketSpoof.Policy is set to 2. +# Set to 0 for permanent ban. +# Default: 86400 seconds (1 day) +# + +PacketSpoof.BanDuration = 86400 + +# +################################################################################################### diff --git a/src/tools/map_extractor/loadlib.cpp b/src/tools/map_extractor/loadlib.cpp index 6a47f2d2a30..d549a0c96f4 100644 --- a/src/tools/map_extractor/loadlib.cpp +++ b/src/tools/map_extractor/loadlib.cpp @@ -30,19 +30,17 @@ bool FileLoader::loadFile(HANDLE mpq, char* filename, bool log) data_size = SFileGetFileSize(file, NULL); data = new uint8[data_size]; - if (data) + SFileReadFile(file, data, data_size, NULL/*bytesRead*/, NULL); + if (prepareLoadedData()) { - SFileReadFile(file, data, data_size, NULL/*bytesRead*/, NULL); - if (prepareLoadedData()) - { - SFileCloseFile(file); - return true; - } + SFileCloseFile(file); + return true; } printf("Error loading %s\n", filename); SFileCloseFile(file); free(); + return false; } diff --git a/src/tools/mmaps_generator/MapBuilder.cpp b/src/tools/mmaps_generator/MapBuilder.cpp index 06a764690ca..9c2dda51621 100644 --- a/src/tools/mmaps_generator/MapBuilder.cpp +++ b/src/tools/mmaps_generator/MapBuilder.cpp @@ -202,7 +202,10 @@ namespace MMAP minX = INT_MIN; minY = INT_MIN; - float bmin[3], bmax[3], lmin[3], lmax[3]; + float bmin[3] = { 0, 0, 0 }; + float bmax[3] = { 0, 0, 0 }; + float lmin[3] = { 0, 0, 0 }; + float lmax[3] = { 0, 0, 0 }; MeshData meshData; // make sure we process maps which don't have tiles @@ -243,11 +246,20 @@ namespace MMAP printf("Building mesh from file\n"); int tileX, tileY, mapId; if (fread(&mapId, sizeof(int), 1, file) != 1) + { + fclose(file); return; + } if (fread(&tileX, sizeof(int), 1, file) != 1) + { + fclose(file); return; + } if (fread(&tileY, sizeof(int), 1, file) != 1) + { + fclose(file); return; + } dtNavMesh* navMesh = NULL; buildNavMesh(mapId, navMesh); @@ -260,25 +272,45 @@ namespace MMAP uint32 verticesCount, indicesCount; if (fread(&verticesCount, sizeof(uint32), 1, file) != 1) + { + fclose(file); return; + } + if (fread(&indicesCount, sizeof(uint32), 1, file) != 1) + { + fclose(file); return; + } float* verts = new float[verticesCount]; int* inds = new int[indicesCount]; if (fread(verts, sizeof(float), verticesCount, file) != verticesCount) + { + fclose(file); + delete[] verts; + delete[] inds; return; + } + if (fread(inds, sizeof(int), indicesCount, file) != indicesCount) + { + fclose(file); + delete[] verts; + delete[] inds; return; + } MeshData data; for (uint32 i = 0; i < verticesCount; ++i) data.solidVerts.append(verts[i]); + delete[] verts; for (uint32 i = 0; i < indicesCount; ++i) data.solidTris.append(inds[i]); + delete[] inds; TerrainBuilder::cleanVertices(data.solidVerts, data.solidTris); // get bounds of current tile @@ -539,19 +571,7 @@ namespace MMAP // merge per tile poly and detail meshes rcPolyMesh** pmmerge = new rcPolyMesh*[TILES_PER_MAP * TILES_PER_MAP]; - if (!pmmerge) - { - printf("%s alloc pmmerge FIALED!\n", tileString); - return; - } - rcPolyMeshDetail** dmmerge = new rcPolyMeshDetail*[TILES_PER_MAP * TILES_PER_MAP]; - if (!dmmerge) - { - printf("%s alloc dmmerge FIALED!\n", tileString); - return; - } - int nmerge = 0; // build all tiles for (int y = 0; y < TILES_PER_MAP; ++y) @@ -646,12 +666,9 @@ namespace MMAP rcFreeContourSet(tile.cset); tile.cset = NULL; - if (tile.pmesh) - { - pmmerge[nmerge] = tile.pmesh; - dmmerge[nmerge] = tile.dmesh; - nmerge++; - } + pmmerge[nmerge] = tile.pmesh; + dmmerge[nmerge] = tile.dmesh; + nmerge++; } } @@ -659,6 +676,9 @@ namespace MMAP if (!iv.polyMesh) { printf("%s alloc iv.polyMesh FIALED!\n", tileString); + delete[] pmmerge; + delete[] dmmerge; + delete[] tiles; return; } rcMergePolyMeshes(m_rcContext, pmmerge, nmerge, *iv.polyMesh); @@ -667,6 +687,9 @@ namespace MMAP if (!iv.polyMeshDetail) { printf("%s alloc m_dmesh FIALED!\n", tileString); + delete[] pmmerge; + delete[] dmmerge; + delete[] tiles; return; } rcMergePolyMeshDetails(m_rcContext, dmmerge, nmerge, *iv.polyMeshDetail); @@ -674,7 +697,6 @@ namespace MMAP // free things up delete[] pmmerge; delete[] dmmerge; - delete[] tiles; // set polygons as walkable diff --git a/src/tools/mmaps_generator/PathCommon.h b/src/tools/mmaps_generator/PathCommon.h index 3e06ff58410..94a11e01730 100644 --- a/src/tools/mmaps_generator/PathCommon.h +++ b/src/tools/mmaps_generator/PathCommon.h @@ -114,7 +114,6 @@ namespace MMAP const char *p = dirpath.c_str(); DIR * dirp = opendir(p); struct dirent * dp; - dirp = opendir(p); while (dirp) { diff --git a/src/tools/mmaps_generator/PathGenerator.cpp b/src/tools/mmaps_generator/PathGenerator.cpp index ed114491b27..882ec7ffb66 100644 --- a/src/tools/mmaps_generator/PathGenerator.cpp +++ b/src/tools/mmaps_generator/PathGenerator.cpp @@ -235,7 +235,7 @@ bool handleArgs(int argc, char** argv, int finish(const char* message, int returnValue) { printf("%s", message); - getchar(); + getchar(); // Wait for user input return returnValue; } diff --git a/src/tools/mmaps_generator/TerrainBuilder.cpp b/src/tools/mmaps_generator/TerrainBuilder.cpp index 3a87da3d4f1..5c76161c0d6 100644 --- a/src/tools/mmaps_generator/TerrainBuilder.cpp +++ b/src/tools/mmaps_generator/TerrainBuilder.cpp @@ -260,7 +260,8 @@ namespace MMAP meshData.solidVerts.append(coord[1]); } - int indices[3], loopStart = 0, loopEnd = 0, loopInc = 0; + int indices[] = { 0, 0, 0 }; + int loopStart = 0, loopEnd = 0, loopInc = 0; getLoopVars(portion, loopStart, loopEnd, loopInc); for (int i = loopStart; i < loopEnd; i+=loopInc) for (int j = TOP; j <= BOTTOM; j+=1) @@ -340,7 +341,8 @@ namespace MMAP delete [] liquid_map; - int indices[3], loopStart = 0, loopEnd = 0, loopInc = 0, triInc = BOTTOM-TOP; + int indices[] = { 0, 0, 0 }; + int loopStart = 0, loopEnd = 0, loopInc = 0, triInc = BOTTOM-TOP; getLoopVars(portion, loopStart, loopEnd, loopInc); // generate triangles diff --git a/src/tools/vmap4_assembler/VMapAssembler.cpp b/src/tools/vmap4_assembler/VMapAssembler.cpp index bb8e324bc75..4ee6f5fce3c 100644 --- a/src/tools/vmap4_assembler/VMapAssembler.cpp +++ b/src/tools/vmap4_assembler/VMapAssembler.cpp @@ -5,9 +5,8 @@ int main(int argc, char* argv[]) { - if(argc != 3) + if (argc != 3) { - //printf("\nusage: %s <raw data dir> <vmap dest dir> [config file name]\n", argv[0]); std::cout << "usage: " << argv[0] << " <raw data dir> <vmap dest dir>" << std::endl; return 1; } @@ -19,7 +18,7 @@ int main(int argc, char* argv[]) VMAP::TileAssembler* ta = new VMAP::TileAssembler(src, dest); - if(!ta->convertWorld2()) + if (!ta->convertWorld2()) { std::cout << "exit with errors" << std::endl; delete ta; diff --git a/src/tools/vmap4_extractor/gameobject_extract.cpp b/src/tools/vmap4_extractor/gameobject_extract.cpp index 3147469e342..af6d621248c 100644 --- a/src/tools/vmap4_extractor/gameobject_extract.cpp +++ b/src/tools/vmap4_extractor/gameobject_extract.cpp @@ -50,7 +50,13 @@ void ExtractGameobjectModels() basepath += "/"; std::string path; - FILE * model_list = fopen((basepath + "temp_gameobject_models").c_str(), "wb"); + std::string modelListPath = basepath + "temp_gameobject_models"; + FILE* model_list = fopen(modelListPath.c_str(), "wb"); + if (!model_list) + { + printf("Fatal error: Could not open file %s\n", modelListPath.c_str()); + return; + } for (DBCFile::Iterator it = dbc.begin(); it != dbc.end(); ++it) { diff --git a/src/tools/vmap4_extractor/vmapexport.cpp b/src/tools/vmap4_extractor/vmapexport.cpp index b650121f587..cd9f552eaee 100644 --- a/src/tools/vmap4_extractor/vmapexport.cpp +++ b/src/tools/vmap4_extractor/vmapexport.cpp @@ -315,16 +315,16 @@ bool ExtractSingleWmo(std::string& fname) return true; int p = 0; - //Select root wmo files + // Select root wmo files char const* rchr = strrchr(plain_name, '_'); - if(rchr != NULL) + if (rchr != NULL) { char cpy[4]; - strncpy((char*)cpy, rchr, 4); + memcpy(cpy, rchr, 4); for (int i = 0; i < 4; ++i) { int m = cpy[i]; - if(isdigit(m)) + if (isdigit(m)) p++; } } diff --git a/src/tools/vmap4_extractor/wmo.cpp b/src/tools/vmap4_extractor/wmo.cpp index 63187963550..983d0316bc1 100644 --- a/src/tools/vmap4_extractor/wmo.cpp +++ b/src/tools/vmap4_extractor/wmo.cpp @@ -138,14 +138,12 @@ bool WMORoot::ConvertToVMAPRootWmo(FILE* pOutfile) return true; } -WMORoot::~WMORoot() -{ -} - WMOGroup::WMOGroup(const std::string &filename) : filename(filename), MOPY(0), MOVI(0), MoviEx(0), MOVT(0), MOBA(0), MobaEx(0), hlq(0), LiquEx(0), LiquBytes(0), groupName(0), descGroupName(0), mogpFlags(0), - mopy_size(0), moba_size(0), LiquEx_size(0), nVertices(0), nTriangles(0) + moprIdx(0), moprNItems(0), nBatchA(0), nBatchB(0), nBatchC(0), fogIdx(0), + liquidType(0), groupWMOID(0), mopy_size(0), moba_size(0), LiquEx_size(0), + nVertices(0), nTriangles(0), liquflags(0) { memset(bbcorn1, 0, sizeof(bbcorn1)); memset(bbcorn2, 0, sizeof(bbcorn2)); @@ -390,7 +388,7 @@ int WMOGroup::ConvertToVMAPGroupWmo(FILE *output, WMORoot *rootWMO, bool precise fwrite(MoviEx,2,nColTriangles*3,output); // write vertices - int VERT[] = {0x54524556, nColVertices*3*sizeof(float)+4, nColVertices};// "VERT" + int VERT[] = {0x54524556, nColVertices*3*static_cast<int>(sizeof(float))+4, nColVertices};// "VERT" int check = 3*nColVertices; fwrite(VERT,4,3,output); for (uint32 i=0; i<nVertices; ++i) @@ -404,9 +402,9 @@ int WMOGroup::ConvertToVMAPGroupWmo(FILE *output, WMORoot *rootWMO, bool precise } //------LIQU------------------------ - if(LiquEx_size != 0) + if (LiquEx_size != 0) { - int LIQU_h[] = {0x5551494C, sizeof(WMOLiquidHeader) + LiquEx_size + hlq->xtiles*hlq->ytiles};// "LIQU" + int LIQU_h[] = {0x5551494C, static_cast<int>(sizeof(WMOLiquidHeader) + LiquEx_size) + hlq->xtiles*hlq->ytiles};// "LIQU" fwrite(LIQU_h, 4, 2, output); // according to WoW.Dev Wiki: @@ -441,7 +439,7 @@ int WMOGroup::ConvertToVMAPGroupWmo(FILE *output, WMORoot *rootWMO, bool precise if (liquidEntry && liquidEntry < 21) { - switch (((uint8)liquidEntry - 1) & 3) + switch ((liquidEntry - 1) & 3) { case 0: liquidEntry = ((mogpFlags & 0x80000) != 0) + 13; @@ -455,8 +453,6 @@ int WMOGroup::ConvertToVMAPGroupWmo(FILE *output, WMORoot *rootWMO, bool precise case 3: liquidEntry = 20; break; - default: - break; } } @@ -490,7 +486,7 @@ WMOGroup::~WMOGroup() } WMOInstance::WMOInstance(MPQFile& f, char const* WmoInstName, uint32 mapID, uint32 tileX, uint32 tileY, FILE* pDirfile) - : currx(0), curry(0), wmo(NULL), doodadset(0), pos(), indx(0), d3(0) + : currx(0), curry(0), wmo(NULL), doodadset(0), pos(), indx(0), id(0), d2(0), d3(0) { float ff[3]; f.read(&id, 4); diff --git a/src/tools/vmap4_extractor/wmo.h b/src/tools/vmap4_extractor/wmo.h index 16d55ffe7de..204e4ead0ce 100644 --- a/src/tools/vmap4_extractor/wmo.h +++ b/src/tools/vmap4_extractor/wmo.h @@ -53,7 +53,6 @@ public: float bbcorn2[3]; WMORoot(std::string& filename); - ~WMORoot(); bool open(); bool ConvertToVMAPRootWmo(FILE* output); |