diff options
Diffstat (limited to 'src')
60 files changed, 2327 insertions, 1296 deletions
diff --git a/src/server/authserver/Authentication/AuthCodes.cpp b/src/server/authserver/Authentication/AuthCodes.cpp index 55229e0d18b..b47ef21b24b 100644 --- a/src/server/authserver/Authentication/AuthCodes.cpp +++ b/src/server/authserver/Authentication/AuthCodes.cpp @@ -37,6 +37,7 @@ namespace AuthHelper static RealmBuildInfo const PreBcAcceptedClientBuilds[] = { + {6141, 1, 12, 3, ' '}, {6005, 1, 12, 2, ' '}, {5875, 1, 12, 1, ' '}, {0, 0, 0, 0, ' '} // terminator diff --git a/src/server/authserver/Server/AuthSocket.cpp b/src/server/authserver/Server/AuthSocket.cpp index 2e73498eb52..792e1bf2a86 100644 --- a/src/server/authserver/Server/AuthSocket.cpp +++ b/src/server/authserver/Server/AuthSocket.cpp @@ -196,12 +196,12 @@ const AuthHandler table[] = Patcher PatchesCache; // Constructor - set the N and g values for SRP6 -AuthSocket::AuthSocket(RealmSocket& socket) : pPatch(NULL), socket_(socket) +AuthSocket::AuthSocket(RealmSocket& socket) : + pPatch(NULL), socket_(socket), _authed(false), _build(0), + _expversion(0), _accountSecurityLevel(SEC_PLAYER) { N.SetHexStr("894B645E89E1535BBDAD5B8B290650530801B18EBFBF5E8FAB3C82872A3E9BB7"); g.SetDword(7); - _authed = false; - _accountSecurityLevel = SEC_PLAYER; } // Close patch file descriptor before leaving diff --git a/src/server/authserver/Server/RealmSocket.cpp b/src/server/authserver/Server/RealmSocket.cpp index e249894a4d3..6710a6a88ae 100644 --- a/src/server/authserver/Server/RealmSocket.cpp +++ b/src/server/authserver/Server/RealmSocket.cpp @@ -27,7 +27,9 @@ RealmSocket::Session::Session(void) {} RealmSocket::Session::~Session(void) { } -RealmSocket::RealmSocket(void) : input_buffer_(4096), session_(NULL), _remoteAddress() +RealmSocket::RealmSocket(void) : + input_buffer_(4096), session_(NULL), + _remoteAddress(), _remotePort(0) { reference_counting_policy().value(ACE_Event_Handler::Reference_Counting_Policy::ENABLED); diff --git a/src/server/collision/Management/VMapManager2.cpp b/src/server/collision/Management/VMapManager2.cpp index 8a1bd346957..6355dbcf4ce 100644 --- a/src/server/collision/Management/VMapManager2.cpp +++ b/src/server/collision/Management/VMapManager2.cpp @@ -96,7 +96,10 @@ namespace VMAP std::string mapFileName = getMapFileName(mapId); StaticMapTree* newTree = new StaticMapTree(mapId, basePath); if (!newTree->InitMap(mapFileName, this)) + { + delete newTree; return false; + } instanceTree = iInstanceMapTrees.insert(InstanceTreeMap::value_type(mapId, newTree)).first; } diff --git a/src/server/collision/Maps/MapTree.cpp b/src/server/collision/Maps/MapTree.cpp index 7dbfcd78bc9..dc12bb68e0d 100644 --- a/src/server/collision/Maps/MapTree.cpp +++ b/src/server/collision/Maps/MapTree.cpp @@ -119,8 +119,9 @@ namespace VMAP return intersectionCallBack.result; } - StaticMapTree::StaticMapTree(uint32 mapID, const std::string &basePath) - : iMapID(mapID), iIsTiled(false), iTreeValues(0), iBasePath(basePath) + StaticMapTree::StaticMapTree(uint32 mapID, const std::string &basePath) : + iMapID(mapID), iIsTiled(false), iTreeValues(NULL), + iNTreeValues(0), iBasePath(basePath) { if (iBasePath.length() > 0 && iBasePath[iBasePath.length()-1] != '/' && iBasePath[iBasePath.length()-1] != '\\') { @@ -273,54 +274,49 @@ namespace VMAP bool StaticMapTree::InitMap(const std::string &fname, VMapManager2* vm) { VMAP_DEBUG_LOG(LOG_FILTER_MAPS, "StaticMapTree::InitMap() : initializing StaticMapTree '%s'", fname.c_str()); - bool success = true; + bool success = false; std::string fullname = iBasePath + fname; FILE* rf = fopen(fullname.c_str(), "rb"); if (!rf) return false; - else + + char chunk[8]; + char tiled = '\0'; + + if (readChunk(rf, chunk, VMAP_MAGIC, 8) && fread(&tiled, sizeof(char), 1, rf) == 1 && + readChunk(rf, chunk, "NODE", 4) && iTree.readFromFile(rf)) { - char chunk[8]; - //general info - if (!readChunk(rf, chunk, VMAP_MAGIC, 8)) success = false; - char tiled = '\0'; - if (success && fread(&tiled, sizeof(char), 1, rf) != 1) success = false; - iIsTiled = bool(tiled); - // Nodes - if (success && !readChunk(rf, chunk, "NODE", 4)) success = false; - if (success) success = iTree.readFromFile(rf); - if (success) - { - iNTreeValues = iTree.primCount(); - iTreeValues = new ModelInstance[iNTreeValues]; - } + iNTreeValues = iTree.primCount(); + iTreeValues = new ModelInstance[iNTreeValues]; + success = readChunk(rf, chunk, "GOBJ", 4); + } + + iIsTiled = bool(tiled); - if (success && !readChunk(rf, chunk, "GOBJ", 4)) success = false; - // global model spawns - // only non-tiled maps have them, and if so exactly one (so far at least...) - ModelSpawn spawn; + // global model spawns + // only non-tiled maps have them, and if so exactly one (so far at least...) + ModelSpawn spawn; #ifdef VMAP_DEBUG - TC_LOG_DEBUG(LOG_FILTER_MAPS, "StaticMapTree::InitMap() : map isTiled: %u", static_cast<uint32>(iIsTiled)); + TC_LOG_DEBUG(LOG_FILTER_MAPS, "StaticMapTree::InitMap() : map isTiled: %u", static_cast<uint32>(iIsTiled)); #endif - if (!iIsTiled && ModelSpawn::readFromFile(rf, spawn)) + if (!iIsTiled && ModelSpawn::readFromFile(rf, spawn)) + { + WorldModel* model = vm->acquireModelInstance(iBasePath, spawn.name); + VMAP_DEBUG_LOG(LOG_FILTER_MAPS, "StaticMapTree::InitMap() : loading %s", spawn.name.c_str()); + if (model) { - WorldModel* model = vm->acquireModelInstance(iBasePath, spawn.name); - VMAP_DEBUG_LOG(LOG_FILTER_MAPS, "StaticMapTree::InitMap() : loading %s", spawn.name.c_str()); - if (model) - { - // assume that global model always is the first and only tree value (could be improved...) - iTreeValues[0] = ModelInstance(spawn, model); - iLoadedSpawns[0] = 1; - } - else - { - success = false; - VMAP_ERROR_LOG(LOG_FILTER_GENERAL, "StaticMapTree::InitMap() : could not acquire WorldModel pointer for '%s'", spawn.name.c_str()); - } + // assume that global model always is the first and only tree value (could be improved...) + iTreeValues[0] = ModelInstance(spawn, model); + iLoadedSpawns[0] = 1; + } + else + { + success = false; + VMAP_ERROR_LOG(LOG_FILTER_GENERAL, "StaticMapTree::InitMap() : could not acquire WorldModel pointer for '%s'", spawn.name.c_str()); } - - fclose(rf); } + + fclose(rf); return success; } diff --git a/src/server/collision/Maps/MapTree.h b/src/server/collision/Maps/MapTree.h index e97c44d089e..c66893da82f 100644 --- a/src/server/collision/Maps/MapTree.h +++ b/src/server/collision/Maps/MapTree.h @@ -85,7 +85,8 @@ namespace VMAP struct AreaInfo { - AreaInfo(): result(false), ground_Z(-G3D::inf()) {} + AreaInfo(): result(false), ground_Z(-G3D::inf()), flags(0), adtId(0), + rootId(0), groupId(0) {} bool result; float ground_Z; uint32 flags; diff --git a/src/server/collision/Maps/TileAssembler.cpp b/src/server/collision/Maps/TileAssembler.cpp index a73e5ed4dc3..b2d381b0ffd 100644 --- a/src/server/collision/Maps/TileAssembler.cpp +++ b/src/server/collision/Maps/TileAssembler.cpp @@ -152,23 +152,25 @@ namespace VMAP uint32 x, y; StaticMapTree::unpackTileID(tile->first, x, y); tilefilename << std::setw(2) << x << '_' << std::setw(2) << y << ".vmtile"; - FILE* tilefile = fopen(tilefilename.str().c_str(), "wb"); - // file header - if (success && fwrite(VMAP_MAGIC, 1, 8, tilefile) != 8) success = false; - // write number of tile spawns - if (success && fwrite(&nSpawns, sizeof(uint32), 1, tilefile) != 1) success = false; - // write tile spawns - for (uint32 s=0; s<nSpawns; ++s) + if (FILE* tilefile = fopen(tilefilename.str().c_str(), "wb")) { - if (s) - ++tile; - const ModelSpawn &spawn2 = map_iter->second->UniqueEntries[tile->second]; - success = success && ModelSpawn::writeToFile(tilefile, spawn2); - // MapTree nodes to update when loading tile: - std::map<uint32, uint32>::iterator nIdx = modelNodeIdx.find(spawn2.ID); - if (success && fwrite(&nIdx->second, sizeof(uint32), 1, tilefile) != 1) success = false; + // file header + if (success && fwrite(VMAP_MAGIC, 1, 8, tilefile) != 8) success = false; + // write number of tile spawns + if (success && fwrite(&nSpawns, sizeof(uint32), 1, tilefile) != 1) success = false; + // write tile spawns + for (uint32 s=0; s<nSpawns; ++s) + { + if (s) + ++tile; + const ModelSpawn &spawn2 = map_iter->second->UniqueEntries[tile->second]; + success = success && ModelSpawn::writeToFile(tilefile, spawn2); + // MapTree nodes to update when loading tile: + std::map<uint32, uint32>::iterator nIdx = modelNodeIdx.find(spawn2.ID); + if (success && fwrite(&nIdx->second, sizeof(uint32), 1, tilefile) != 1) success = false; + } + fclose(tilefile); } - fclose(tilefile); } // break; //test, extract only first map; TODO: remvoe this line } diff --git a/src/server/collision/Maps/TileAssembler.h b/src/server/collision/Maps/TileAssembler.h index a11ce272d62..56cb7600e4f 100644 --- a/src/server/collision/Maps/TileAssembler.h +++ b/src/server/collision/Maps/TileAssembler.h @@ -40,6 +40,7 @@ namespace VMAP private: G3D::Matrix3 iRotation; public: + ModelPosition(): iScale(0.0f) { } G3D::Vector3 iPos; G3D::Vector3 iDir; float iScale; @@ -74,7 +75,8 @@ namespace VMAP std::vector<G3D::Vector3> vertexArray; class WmoLiquid* liquid; - GroupModel_Raw() : liquid(0) {} + GroupModel_Raw() : mogpflags(0), GroupWMOID(0), liquidflags(0), + liquid(NULL) {} ~GroupModel_Raw(); bool Read(FILE* f); diff --git a/src/server/collision/Models/WorldModel.cpp b/src/server/collision/Models/WorldModel.cpp index ca0f95c74e3..3c72cb80308 100644 --- a/src/server/collision/Models/WorldModel.cpp +++ b/src/server/collision/Models/WorldModel.cpp @@ -205,35 +205,48 @@ namespace VMAP bool WmoLiquid::writeToFile(FILE* wf) { - bool result = true; - if (result && fwrite(&iTilesX, sizeof(uint32), 1, wf) != 1) result = false; - if (result && fwrite(&iTilesY, sizeof(uint32), 1, wf) != 1) result = false; - if (result && fwrite(&iCorner, sizeof(Vector3), 1, wf) != 1) result = false; - if (result && fwrite(&iType, sizeof(uint32), 1, wf) != 1) result = false; - uint32 size = (iTilesX + 1)*(iTilesY + 1); - if (result && fwrite(iHeight, sizeof(float), size, wf) != size) result = false; - size = iTilesX*iTilesY; - if (result && fwrite(iFlags, sizeof(uint8), size, wf) != size) result = false; + bool result = false; + if (fwrite(&iTilesX, sizeof(uint32), 1, wf) == 1 && + fwrite(&iTilesY, sizeof(uint32), 1, wf) == 1 && + fwrite(&iCorner, sizeof(Vector3), 1, wf) == 1 && + fwrite(&iType, sizeof(uint32), 1, wf) == 1) + { + uint32 size = (iTilesX + 1) * (iTilesY + 1); + if (fwrite(iHeight, sizeof(float), size, wf) == size) + { + size = iTilesX*iTilesY; + result = fwrite(iFlags, sizeof(uint8), size, wf) == size; + } + } + return result; } bool WmoLiquid::readFromFile(FILE* rf, WmoLiquid* &out) { - bool result = true; + bool result = false; WmoLiquid* liquid = new WmoLiquid(); - if (result && fread(&liquid->iTilesX, sizeof(uint32), 1, rf) != 1) result = false; - if (result && fread(&liquid->iTilesY, sizeof(uint32), 1, rf) != 1) result = false; - if (result && fread(&liquid->iCorner, sizeof(Vector3), 1, rf) != 1) result = false; - if (result && fread(&liquid->iType, sizeof(uint32), 1, rf) != 1) result = false; - uint32 size = (liquid->iTilesX + 1)*(liquid->iTilesY + 1); - liquid->iHeight = new float[size]; - if (result && fread(liquid->iHeight, sizeof(float), size, rf) != size) result = false; - size = liquid->iTilesX * liquid->iTilesY; - liquid->iFlags = new uint8[size]; - if (result && fread(liquid->iFlags, sizeof(uint8), size, rf) != size) result = false; + + if (fread(&liquid->iTilesX, sizeof(uint32), 1, rf) == 1 && + fread(&liquid->iTilesY, sizeof(uint32), 1, rf) == 1 && + fread(&liquid->iCorner, sizeof(Vector3), 1, rf) == 1 && + fread(&liquid->iType, sizeof(uint32), 1, rf) == 1) + { + uint32 size = (liquid->iTilesX + 1) * (liquid->iTilesY + 1); + liquid->iHeight = new float[size]; + if (fread(liquid->iHeight, sizeof(float), size, rf) == size) + { + size = liquid->iTilesX * liquid->iTilesY; + liquid->iFlags = new uint8[size]; + result = fread(liquid->iFlags, sizeof(uint8), size, rf) == size; + } + } + if (!result) delete liquid; - out = liquid; + else + out = liquid; + return result; } diff --git a/src/server/game/AI/CoreAI/UnitAI.cpp b/src/server/game/AI/CoreAI/UnitAI.cpp index 0ab807466d5..70c4761e025 100644 --- a/src/server/game/AI/CoreAI/UnitAI.cpp +++ b/src/server/game/AI/CoreAI/UnitAI.cpp @@ -123,34 +123,45 @@ void UnitAI::DoCastToAllHostilePlayers(uint32 spellid, bool triggered) void UnitAI::DoCast(uint32 spellId) { Unit* target = NULL; - //TC_LOG_ERROR(LOG_FILTER_GENERAL, "aggre %u %u", spellId, (uint32)AISpellInfo[spellId].target); + switch (AISpellInfo[spellId].target) { default: - case AITARGET_SELF: target = me; break; - case AITARGET_VICTIM: target = me->getVictim(); break; + case AITARGET_SELF: + target = me; + break; + case AITARGET_VICTIM: + target = me->getVictim(); + break; case AITARGET_ENEMY: { - const SpellInfo* spellInfo = sSpellMgr->GetSpellInfo(spellId); - bool playerOnly = spellInfo->AttributesEx3 & SPELL_ATTR3_ONLY_TARGET_PLAYERS; - //float range = GetSpellMaxRange(spellInfo, false); - target = SelectTarget(SELECT_TARGET_RANDOM, 0, spellInfo->GetMaxRange(false), playerOnly); + if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId)) + { + bool playerOnly = spellInfo->AttributesEx3 & SPELL_ATTR3_ONLY_TARGET_PLAYERS; + target = SelectTarget(SELECT_TARGET_RANDOM, 0, spellInfo->GetMaxRange(false), playerOnly); + } break; } - case AITARGET_ALLY: target = me; break; - case AITARGET_BUFF: target = me; break; + case AITARGET_ALLY: + target = me; + break; + case AITARGET_BUFF: + target = me; + break; case AITARGET_DEBUFF: { - const SpellInfo* spellInfo = sSpellMgr->GetSpellInfo(spellId); - bool playerOnly = spellInfo->AttributesEx3 & SPELL_ATTR3_ONLY_TARGET_PLAYERS; - float range = spellInfo->GetMaxRange(false); - - DefaultTargetSelector targetSelector(me, range, playerOnly, -(int32)spellId); - if (!(spellInfo->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_VICTIM) - && targetSelector(me->getVictim())) - target = me->getVictim(); - else - target = SelectTarget(SELECT_TARGET_RANDOM, 0, targetSelector); + if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId)) + { + bool playerOnly = spellInfo->AttributesEx3 & SPELL_ATTR3_ONLY_TARGET_PLAYERS; + float range = spellInfo->GetMaxRange(false); + + DefaultTargetSelector targetSelector(me, range, playerOnly, -(int32)spellId); + if (!(spellInfo->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_VICTIM) + && targetSelector(me->getVictim())) + target = me->getVictim(); + else + target = SelectTarget(SELECT_TARGET_RANDOM, 0, targetSelector); + } break; } } diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp index 576d77a2e24..9d182ee6885 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.cpp +++ b/src/server/game/AI/SmartScripts/SmartScript.cpp @@ -657,9 +657,18 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u { if (IsUnit(*itr)) { - (*itr)->ToUnit()->SetFlag(UNIT_FIELD_FLAGS, e.action.unitFlag.flag); - TC_LOG_DEBUG(LOG_FILTER_DATABASE_AI, "SmartScript::ProcessAction:: SMART_ACTION_SET_UNIT_FLAG. Unit %u added flag %u to UNIT_FIELD_FLAGS", + if (!e.action.unitFlag.type) + { + (*itr)->ToUnit()->SetFlag(UNIT_FIELD_FLAGS, e.action.unitFlag.flag); + TC_LOG_DEBUG(LOG_FILTER_DATABASE_AI, "SmartScript::ProcessAction:: SMART_ACTION_SET_UNIT_FLAG. Unit %u added flag %u to UNIT_FIELD_FLAGS", + (*itr)->GetGUIDLow(), e.action.unitFlag.flag); + } + else + { + (*itr)->ToUnit()->SetFlag(UNIT_FIELD_FLAGS_2, e.action.unitFlag.flag); + TC_LOG_DEBUG(LOG_FILTER_DATABASE_AI, "SmartScript::ProcessAction:: SMART_ACTION_SET_UNIT_FLAG. Unit %u added flag %u to UNIT_FIELD_FLAGS_2", (*itr)->GetGUIDLow(), e.action.unitFlag.flag); + } } } @@ -676,9 +685,18 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u { if (IsUnit(*itr)) { - (*itr)->ToUnit()->RemoveFlag(UNIT_FIELD_FLAGS, e.action.unitFlag.flag); - TC_LOG_DEBUG(LOG_FILTER_DATABASE_AI, "SmartScript::ProcessAction:: SMART_ACTION_REMOVE_UNIT_FLAG. Unit %u removed flag %u to UNIT_FIELD_FLAGS", + if (!e.action.unitFlag.type) + { + (*itr)->ToUnit()->RemoveFlag(UNIT_FIELD_FLAGS, e.action.unitFlag.flag); + TC_LOG_DEBUG(LOG_FILTER_DATABASE_AI, "SmartScript::ProcessAction:: SMART_ACTION_REMOVE_UNIT_FLAG. Unit %u removed flag %u to UNIT_FIELD_FLAGS", + (*itr)->GetGUIDLow(), e.action.unitFlag.flag); + } + else + { + (*itr)->ToUnit()->RemoveFlag(UNIT_FIELD_FLAGS_2, e.action.unitFlag.flag); + TC_LOG_DEBUG(LOG_FILTER_DATABASE_AI, "SmartScript::ProcessAction:: SMART_ACTION_REMOVE_UNIT_FLAG. Unit %u removed flag %u to UNIT_FIELD_FLAGS_2", (*itr)->GetGUIDLow(), e.action.unitFlag.flag); + } } } diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.h b/src/server/game/AI/SmartScripts/SmartScriptMgr.h index 875a67d7f3c..d80b4816d4b 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.h +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.h @@ -828,6 +828,7 @@ struct SmartAction struct { uint32 flag; + uint32 type; } unitFlag; struct diff --git a/src/server/game/Achievements/AchievementMgr.cpp b/src/server/game/Achievements/AchievementMgr.cpp index f7811753147..888605b4745 100644 --- a/src/server/game/Achievements/AchievementMgr.cpp +++ b/src/server/game/Achievements/AchievementMgr.cpp @@ -406,8 +406,11 @@ void AchievementMgr<Player>::SendPacket(WorldPacket* data) const } template<class T> -void AchievementMgr<T>::RemoveCriteriaProgress(const AchievementCriteriaEntry* entry) +void AchievementMgr<T>::RemoveCriteriaProgress(AchievementCriteriaEntry const* entry) { + if (!entry) + return; + CriteriaProgressMap::iterator criteriaProgress = m_criteriaProgress.find(entry->ID); if (criteriaProgress == m_criteriaProgress.end()) return; @@ -420,8 +423,11 @@ void AchievementMgr<T>::RemoveCriteriaProgress(const AchievementCriteriaEntry* e } template<> -void AchievementMgr<Guild>::RemoveCriteriaProgress(const AchievementCriteriaEntry* entry) +void AchievementMgr<Guild>::RemoveCriteriaProgress(AchievementCriteriaEntry const* entry) { + if (!entry) + return; + CriteriaProgressMap::iterator criteriaProgress = m_criteriaProgress.find(entry->ID); if (criteriaProgress == m_criteriaProgress.end()) return; @@ -1448,6 +1454,9 @@ void AchievementMgr<T>::UpdateAchievementCriteria(AchievementCriteriaTypes type, template<class T> bool AchievementMgr<T>::IsCompletedCriteria(AchievementCriteriaEntry const* achievementCriteria, AchievementEntry const* achievement) { + if (!achievement) + return false; + // counter can never complete if (achievement->flags & ACHIEVEMENT_FLAG_COUNTER) return false; @@ -2049,10 +2058,14 @@ void AchievementMgr<T>::SendAllAchievementData(Player* /*receiver*/) const template<> void AchievementMgr<Guild>::SendAllAchievementData(Player* receiver) const { + VisibleAchievementPred isVisible; WorldPacket data(SMSG_GUILD_ACHIEVEMENT_DATA, m_completedAchievements.size() * (4 + 4) + 3); - data.WriteBits(m_completedAchievements.size(), 23); + data.WriteBits(std::count_if(m_completedAchievements.begin(), m_completedAchievements.end(), isVisible), 23); for (CompletedAchievementMap::const_iterator itr = m_completedAchievements.begin(); itr != m_completedAchievements.end(); ++itr) { + if (!isVisible(*itr)) + continue; + data.AppendPackedTime(itr->second.date); data << uint32(itr->first); } diff --git a/src/server/game/Battlefield/Zones/BattlefieldWG.h b/src/server/game/Battlefield/Zones/BattlefieldWG.h index 10d28118325..f2d96c1d1a0 100644 --- a/src/server/game/Battlefield/Zones/BattlefieldWG.h +++ b/src/server/game/Battlefield/Zones/BattlefieldWG.h @@ -1481,6 +1481,7 @@ struct WGWorkshop bf = _bf; workshopId = _workshopId; + teamControl = BATTLEFIELD_WG_TEAM_NEUTRAL; } void GiveControlTo(uint8 team, bool init /* for first call in setup*/) diff --git a/src/server/game/Battlegrounds/ArenaTeam.cpp b/src/server/game/Battlegrounds/ArenaTeam.cpp index 668858618cb..9639e36f204 100644 --- a/src/server/game/Battlegrounds/ArenaTeam.cpp +++ b/src/server/game/Battlegrounds/ArenaTeam.cpp @@ -271,6 +271,19 @@ bool ArenaTeam::LoadMembersFromDB(QueryResult result) return true; } +bool ArenaTeam::SetName(std::string const& name) +{ + if (TeamName == name || name.empty() || name.length() > 24 || sObjectMgr->IsReservedName(name) || !ObjectMgr::IsValidCharterName(name)) + return false; + + TeamName = name; + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_ARENA_TEAM_NAME); + stmt->setString(0, TeamName); + stmt->setUInt32(1, GetId()); + CharacterDatabase.Execute(stmt); + return true; +} + void ArenaTeam::SetCaptain(uint64 guid) { // Disable remove/promote buttons @@ -360,6 +373,29 @@ void ArenaTeam::Disband(WorldSession* session) sArenaTeamMgr->RemoveArenaTeam(TeamId); } +void ArenaTeam::Disband() +{ + // Remove all members from arena team + while (!Members.empty()) + DelMember(Members.front().Guid, false); + + // Update database + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + + PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ARENA_TEAM); + stmt->setUInt32(0, TeamId); + trans->Append(stmt); + + stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ARENA_TEAM_MEMBERS); + stmt->setUInt32(0, TeamId); + trans->Append(stmt); + + CharacterDatabase.CommitTransaction(trans); + + // Remove arena team from ObjectMgr + sArenaTeamMgr->RemoveArenaTeam(TeamId); +} + void ArenaTeam::Roster(WorldSession* session) { Player* player = NULL; diff --git a/src/server/game/Battlegrounds/ArenaTeam.h b/src/server/game/Battlegrounds/ArenaTeam.h index 59b1275a549..e25fbba235b 100644 --- a/src/server/game/Battlegrounds/ArenaTeam.h +++ b/src/server/game/Battlegrounds/ArenaTeam.h @@ -118,6 +118,7 @@ class ArenaTeam uint32 backgroundColor, uint8 emblemStyle, uint32 emblemColor, uint8 borderStyle, uint32 borderColor); void Disband(WorldSession* session); + void Disband(); typedef std::list<ArenaTeamMember> MemberList; @@ -134,6 +135,7 @@ class ArenaTeam uint32 GetAverageMMR(Group* group) const; void SetCaptain(uint64 guid); + bool SetName(std::string const& name); bool AddMember(uint64 PlayerGuid); void DelMember(uint64 guid, bool cleanDb); diff --git a/src/server/game/Chat/Chat.cpp b/src/server/game/Chat/Chat.cpp index d62f9e4eaa7..1515c75597f 100644 --- a/src/server/game/Chat/Chat.cpp +++ b/src/server/game/Chat/Chat.cpp @@ -143,7 +143,7 @@ bool ChatHandler::isAvailable(ChatCommand const& cmd) const return m_session->GetSecurity() >= AccountTypes(cmd.SecurityLevel); } - return m_session->HasPermission(permission); + return HasPermission(permission); } bool ChatHandler::HasLowerSecurity(Player* target, uint64 guid, bool strong) @@ -205,7 +205,7 @@ bool ChatHandler::hasStringAbbr(const char* name, const char* part) if (!*part) return false; - for (;;) + while (true) { if (!*part) return true; diff --git a/src/server/game/Chat/Chat.h b/src/server/game/Chat/Chat.h index 538273062ae..298bb91692b 100644 --- a/src/server/game/Chat/Chat.h +++ b/src/server/game/Chat/Chat.h @@ -86,6 +86,7 @@ class ChatHandler // function with different implementation for chat/console virtual bool isAvailable(ChatCommand const& cmd) const; + virtual bool HasPermission(uint32 permission) const { return m_session->HasPermission(permission); } virtual std::string GetNameLink() const { return GetNameLink(m_session->GetPlayer()); } virtual bool needReportToTarget(Player* chr) const; virtual LocaleConstant GetSessionDbcLocale() const; @@ -149,6 +150,7 @@ class CliHandler : public ChatHandler // overwrite functions const char *GetTrinityString(int32 entry) const; bool isAvailable(ChatCommand const& cmd) const; + bool HasPermission(uint32 /*permission*/) const { return true; } void SendSysMessage(const char *str); std::string GetNameLink() const; bool needReportToTarget(Player* chr) const; diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index cf8a01a765e..79beab4f7e6 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -2451,19 +2451,18 @@ uint32 Creature::GetVendorItemCurrentCount(VendorItem const* vItem) time_t ptime = time(NULL); if (time_t(vCount->lastIncrementTime + vItem->incrtime) <= ptime) - { - ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(vItem->item); - - uint32 diff = uint32((ptime - vCount->lastIncrementTime)/vItem->incrtime); - if ((vCount->count + diff * pProto->BuyCount) >= vItem->maxcount) + if (ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(vItem->item)) { - m_vendorItemCounts.erase(itr); - return vItem->maxcount; - } + uint32 diff = uint32((ptime - vCount->lastIncrementTime)/vItem->incrtime); + if ((vCount->count + diff * pProto->BuyCount) >= vItem->maxcount) + { + m_vendorItemCounts.erase(itr); + return vItem->maxcount; + } - vCount->count += diff * pProto->BuyCount; - vCount->lastIncrementTime = ptime; - } + vCount->count += diff * pProto->BuyCount; + vCount->lastIncrementTime = ptime; + } return vCount->count; } @@ -2490,15 +2489,14 @@ uint32 Creature::UpdateVendorItemCurrentCount(VendorItem const* vItem, uint32 us time_t ptime = time(NULL); if (time_t(vCount->lastIncrementTime + vItem->incrtime) <= ptime) - { - ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(vItem->item); - - uint32 diff = uint32((ptime - vCount->lastIncrementTime)/vItem->incrtime); - if ((vCount->count + diff * pProto->BuyCount) < vItem->maxcount) - vCount->count += diff * pProto->BuyCount; - else - vCount->count = vItem->maxcount; - } + if (ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(vItem->item)) + { + uint32 diff = uint32((ptime - vCount->lastIncrementTime)/vItem->incrtime); + if ((vCount->count + diff * pProto->BuyCount) < vItem->maxcount) + vCount->count += diff * pProto->BuyCount; + else + vCount->count = vItem->maxcount; + } vCount->count = vCount->count > used_count ? vCount->count-used_count : 0; vCount->lastIncrementTime = ptime; diff --git a/src/server/game/Entities/Creature/GossipDef.cpp b/src/server/game/Entities/Creature/GossipDef.cpp index c6d9bd52e18..3cefc5881e9 100644 --- a/src/server/game/Entities/Creature/GossipDef.cpp +++ b/src/server/game/Entities/Creature/GossipDef.cpp @@ -184,7 +184,9 @@ void PlayerMenu::SendGossipMenu(uint32 titleTextId, uint64 objectGUID) const data << item.BoxMessage; // accept text (related to money) pop up box, 2.0.3 } - data << uint32(_questMenu.GetMenuItemCount()); // max count 0x20 + size_t count_pos = data.wpos(); + data << uint32(0); // max count 0x20 + uint32 count = 0; // Store this instead of checking the Singleton every loop iteration bool questLevelInTitle = sWorld->getBoolConfig(CONFIG_UI_QUESTLEVELS_IN_DIALOGS); @@ -193,26 +195,29 @@ void PlayerMenu::SendGossipMenu(uint32 titleTextId, uint64 objectGUID) const { QuestMenuItem const& item = _questMenu.GetItem(i); uint32 questID = item.QuestId; - Quest const* quest = sObjectMgr->GetQuestTemplate(questID); - - data << uint32(questID); - data << uint32(item.QuestIcon); - data << int32(quest->GetQuestLevel()); - data << uint32(quest->GetFlags()); // 3.3.3 quest flags - data << uint8(0); // 3.3.3 changes icon: blue question or yellow exclamation - std::string title = quest->GetTitle(); + if (Quest const* quest = sObjectMgr->GetQuestTemplate(questID)) + { + ++count; + data << uint32(questID); + data << uint32(item.QuestIcon); + data << int32(quest->GetQuestLevel()); + data << uint32(quest->GetFlags()); // 3.3.3 quest flags + data << uint8(0); // 3.3.3 changes icon: blue question or yellow exclamation + std::string title = quest->GetTitle(); - int32 locale = _session->GetSessionDbLocaleIndex(); - if (locale >= 0) - if (QuestLocale const* localeData = sObjectMgr->GetQuestLocale(questID)) - ObjectMgr::GetLocaleString(localeData->Title, locale, title); + int32 locale = _session->GetSessionDbLocaleIndex(); + if (locale >= 0) + if (QuestLocale const* localeData = sObjectMgr->GetQuestLocale(questID)) + ObjectMgr::GetLocaleString(localeData->Title, locale, title); - if (questLevelInTitle) - AddQuestLevelToTitle(title, quest->GetQuestLevel()); + if (questLevelInTitle) + AddQuestLevelToTitle(title, quest->GetQuestLevel()); - data << title; // max 0x200 + data << title; // max 0x200 + } } + data.put<uint8>(count_pos, count); _session->SendPacket(&data); } @@ -300,20 +305,21 @@ void PlayerMenu::SendQuestGiverQuestList(QEmote eEmote, const std::string& Title data << uint32(eEmote._Emote); // NPC emote size_t count_pos = data.wpos(); - data << uint8 (_questMenu.GetMenuItemCount()); + data << uint8 (0); uint32 count = 0; // Store this instead of checking the Singleton every loop iteration bool questLevelInTitle = sWorld->getBoolConfig(CONFIG_UI_QUESTLEVELS_IN_DIALOGS); - for (; count < _questMenu.GetMenuItemCount(); ++count) + for (uint32 i = 0; i < _questMenu.GetMenuItemCount(); ++i) { - QuestMenuItem const& qmi = _questMenu.GetItem(count); + QuestMenuItem const& qmi = _questMenu.GetItem(i); uint32 questID = qmi.QuestId; if (Quest const* quest = sObjectMgr->GetQuestTemplate(questID)) { + ++count; std::string title = quest->GetTitle(); int32 locale = _session->GetSessionDbLocaleIndex(); diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index ff74c6921f7..8d15e6ab39a 100644 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -87,7 +87,10 @@ bool GameObject::AIM_Initialize() std::string GameObject::GetAIName() const { - return sObjectMgr->GetGameObjectTemplate(GetEntry())->AIName; + if (GameObjectTemplate const* got = sObjectMgr->GetGameObjectTemplate(GetEntry())) + return got->AIName; + + return ""; } void GameObject::CleanupsBeforeDelete(bool /*finalCleanup*/) diff --git a/src/server/game/Entities/Item/Item.cpp b/src/server/game/Entities/Item/Item.cpp index a25bd463a55..86d02132eca 100644 --- a/src/server/game/Entities/Item/Item.cpp +++ b/src/server/game/Entities/Item/Item.cpp @@ -858,16 +858,26 @@ bool Item::IsFitToSpellRequirements(SpellInfo const* spellInfo) const return true; } -void Item::SetEnchantment(EnchantmentSlot slot, uint32 id, uint32 duration, uint32 charges) +void Item::SetEnchantment(EnchantmentSlot slot, uint32 id, uint32 duration, uint32 charges, uint64 caster /*= 0*/) { // Better lost small time at check in comparison lost time at item save to DB. if ((GetEnchantmentId(slot) == id) && (GetEnchantmentDuration(slot) == duration) && (GetEnchantmentCharges(slot) == charges)) return; + Player* owner = GetOwner(); + if (slot < MAX_INSPECTED_ENCHANTMENT_SLOT) + { + if (uint32 oldEnchant = GetEnchantmentId(slot)) + owner->GetSession()->SendEnchantmentLog(GetOwnerGUID(), 0, GetEntry(), oldEnchant); + + if (id) + owner->GetSession()->SendEnchantmentLog(GetOwnerGUID(), caster, GetEntry(), id); + } + SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1 + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_ID_OFFSET, id); SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1 + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_DURATION_OFFSET, duration); SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1 + slot*MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_CHARGES_OFFSET, charges); - SetState(ITEM_CHANGED, GetOwner()); + SetState(ITEM_CHANGED, owner); } void Item::SetEnchantmentDuration(EnchantmentSlot slot, uint32 duration, Player* owner) @@ -984,6 +994,16 @@ bool Item::IsLimitedToAnotherMapOrZone(uint32 cur_mapId, uint32 cur_zoneId) cons return proto && ((proto->Map && proto->Map != cur_mapId) || (proto->Area && proto->Area != cur_zoneId)); } +void Item::SendUpdateSockets() +{ + WorldPacket data(SMSG_SOCKET_GEMS_RESULT, 8+4+4+4+4); + data << uint64(GetGUID()); + for (uint32 i = SOCK_ENCHANTMENT_SLOT; i <= BONUS_ENCHANTMENT_SLOT; ++i) + data << uint32(GetEnchantmentId(EnchantmentSlot(i))); + + GetOwner()->GetSession()->SendPacket(&data); +} + // Though the client has the information in the item's data field, // we have to send SMSG_ITEM_TIME_UPDATE to display the remaining // time. diff --git a/src/server/game/Entities/Item/Item.h b/src/server/game/Entities/Item/Item.h index f69ac0f8965..cdc79d96d67 100644 --- a/src/server/game/Entities/Item/Item.h +++ b/src/server/game/Entities/Item/Item.h @@ -295,7 +295,7 @@ class Item : public Object void SetItemRandomProperties(int32 randomPropId); void UpdateItemSuffixFactor(); static int32 GenerateItemRandomPropertyId(uint32 item_id); - void SetEnchantment(EnchantmentSlot slot, uint32 id, uint32 duration, uint32 charges); + void SetEnchantment(EnchantmentSlot slot, uint32 id, uint32 duration, uint32 charges, uint64 caster = 0); void SetEnchantmentDuration(EnchantmentSlot slot, uint32 duration, Player* owner); void SetEnchantmentCharges(EnchantmentSlot slot, uint32 charges); void ClearEnchantment(EnchantmentSlot slot); @@ -306,6 +306,8 @@ class Item : public Object std::string const& GetText() const { return m_text; } void SetText(std::string const& text) { m_text = text; } + void SendUpdateSockets(); + void SendTimeUpdate(Player* owner); void UpdateDuration(Player* owner, uint32 diff); diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 10004862b74..718223304da 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -8017,6 +8017,10 @@ void Player::DuelComplete(DuelCompleteType type) if (getClass() == CLASS_DEATH_KNIGHT && duel->opponent->GetQuestStatus(12733) == QUEST_STATUS_INCOMPLETE) duel->opponent->CastSpell(duel->opponent, 52994, true); + // Honor points after duel (the winner) - ImpConfig + if (uint32 amount = sWorld->getIntConfig(CONFIG_HONOR_AFTER_DUEL)) + duel->opponent->RewardHonor(NULL, 1, amount); + break; default: break; @@ -8063,10 +8067,6 @@ void Player::DuelComplete(DuelCompleteType type) else if (duel->opponent->GetComboTarget() == GetPetGUID()) duel->opponent->ClearComboPoints(); - // Honor points after duel (the winner) - ImpConfig - if (uint32 amount = sWorld->getIntConfig(CONFIG_HONOR_AFTER_DUEL)) - duel->opponent->RewardHonor(NULL, 1, amount); - //cleanups SetUInt64Value(PLAYER_DUEL_ARBITER, 0); SetUInt32Value(PLAYER_DUEL_TEAM, 0); @@ -9885,6 +9885,16 @@ void Player::SendInitWorldStates(uint32 zoneid, uint32 areaid) bf->FillInitialWorldStates(data); break; } + case 4820: + if (instance && mapid == 668) + instance->FillInitialWorldStates(data); + else + { + data << uint32(4884) << uint32(0); // 9 WORLD_STATE_HOR_WAVES_ENABLED + data << uint32(4882) << uint32(0); // 10 WORLD_STATE_HOR_WAVE_COUNT + } + break; + // No break here, intended. default: data << uint32(0x914) << uint32(0x0); // 7 @@ -22711,7 +22721,7 @@ void Player::UpdateTriggerVisibility() if (!obj || !(obj->isTrigger() || obj->HasAuraType(SPELL_AURA_TRANSFORM))) // can transform into triggers continue; - obj->BuildCreateUpdateBlockForPlayer(&udata, this); + obj->BuildValuesUpdateBlockForPlayer(&udata, this); } } @@ -23681,7 +23691,7 @@ void Player::UpdateForQuestWorldObjects() if (buildUpdateBlock) { - obj->BuildCreateUpdateBlockForPlayer(&udata, this); + obj->BuildValuesUpdateBlockForPlayer(&udata, this); break; } } diff --git a/src/server/game/Entities/Transport/Transport.cpp b/src/server/game/Entities/Transport/Transport.cpp index 43664a7853e..3ed41781982 100644 --- a/src/server/game/Entities/Transport/Transport.cpp +++ b/src/server/game/Entities/Transport/Transport.cpp @@ -691,30 +691,34 @@ void Transport::UpdatePassengerPositions() float x, y, z, o; npc->m_movementInfo.t_pos.GetPosition(x, y, z, o); - CalculatePassengerPosition(x, y, z, o); + CalculatePassengerPosition(x, y, z, &o); GetMap()->CreatureRelocation(npc, x, y, z, o, false); npc->GetTransportHomePosition(x, y, z, o); - CalculatePassengerPosition(x, y, z, o); + CalculatePassengerPosition(x, y, z, &o); npc->SetHomePosition(x, y, z, o); } } -void Transport::CalculatePassengerPosition(float& x, float& y, float& z, float& o) const +void Transport::CalculatePassengerPosition(float& x, float& y, float& z, float* o /*= NULL*/) const { - float inx = x, iny = y, inz = z, ino = o; - o = GetOrientation() + ino; + float inx = x, iny = y, inz = z; + if (o) + *o = Position::NormalizeOrientation(GetOrientation() + *o); + x = GetPositionX() + inx * std::cos(GetOrientation()) - iny * std::sin(GetOrientation()); y = GetPositionY() + iny * std::cos(GetOrientation()) + inx * std::sin(GetOrientation()); z = GetPositionZ() + inz; } -void Transport::CalculatePassengerOffset(float& x, float& y, float& z, float& o) const +void Transport::CalculatePassengerOffset(float& x, float& y, float& z, float* o /*= NULL*/) const { - o -= GetOrientation(); + if (o) + *o = Position::NormalizeOrientation(*o - GetOrientation()); + z -= GetPositionZ(); y -= GetPositionY(); // y = searchedY * std::cos(o) + searchedX * std::sin(o) x -= GetPositionX(); // x = searchedX * std::cos(o) + searchedY * std::sin(o + pi) float inx = x, iny = y; - y = (iny - inx * tan(GetOrientation())) / (cos(GetOrientation()) + std::sin(GetOrientation()) * tan(GetOrientation())); - x = (inx + iny * tan(GetOrientation())) / (cos(GetOrientation()) + std::sin(GetOrientation()) * tan(GetOrientation())); + y = (iny - inx * std::tan(GetOrientation())) / (std::cos(GetOrientation()) + std::sin(GetOrientation()) * std::tan(GetOrientation())); + x = (inx + iny * std::tan(GetOrientation())) / (std::cos(GetOrientation()) + std::sin(GetOrientation()) * std::tan(GetOrientation())); } diff --git a/src/server/game/Entities/Transport/Transport.h b/src/server/game/Entities/Transport/Transport.h index bae09335f62..445bec456fd 100644 --- a/src/server/game/Entities/Transport/Transport.h +++ b/src/server/game/Entities/Transport/Transport.h @@ -50,10 +50,10 @@ class Transport : public GameObject, public TransportBase void UpdatePassengerPositions(); /// This method transforms supplied transport offsets into global coordinates - void CalculatePassengerPosition(float& x, float& y, float& z, float& o) const; + void CalculatePassengerPosition(float& x, float& y, float& z, float* o = NULL) const; /// This method transforms supplied global coordinates into local offsets - void CalculatePassengerOffset(float& x, float& y, float& z, float& o) const; + void CalculatePassengerOffset(float& x, float& y, float& z, float* o = NULL) const; void BuildStartMovePacket(Map const* targetMap); void BuildStopMovePacket(Map const* targetMap); diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index a0aea414cef..8fa929131e2 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -416,15 +416,8 @@ void Unit::UpdateSplinePosition() pos.m_positionZ = loc.z; pos.SetOrientation(loc.orientation); - if (Unit* vehicle = GetVehicleBase()) - { - loc.x += vehicle->GetPositionX(); - loc.y += vehicle->GetPositionY(); - loc.z += vehicle->GetPositionZMinusOffset(); - loc.orientation = vehicle->GetOrientation(); - } - else if (TransportBase* transport = GetDirectTransport()) - transport->CalculatePassengerPosition(loc.x, loc.y, loc.z, loc.orientation); + if (TransportBase* transport = GetDirectTransport()) + transport->CalculatePassengerPosition(loc.x, loc.y, loc.z, &loc.orientation); } if (HasUnitState(UNIT_STATE_CANNOT_TURN)) @@ -11246,7 +11239,7 @@ void Unit::setDeathState(DeathState s) SetPower(getPowerType(), 0); // players in instance don't have ZoneScript, but they have InstanceScript - if (ZoneScript* zoneScript = GetZoneScript() ? GetZoneScript() : (ZoneScript*)GetInstanceScript()) + if (ZoneScript* zoneScript = GetZoneScript() ? GetZoneScript() : GetInstanceScript()) zoneScript->OnUnitDeath(this); } else if (s == JUST_RESPAWNED) diff --git a/src/server/game/Entities/Vehicle/Vehicle.cpp b/src/server/game/Entities/Vehicle/Vehicle.cpp index 214a47a6611..503d89a8e82 100644 --- a/src/server/game/Entities/Vehicle/Vehicle.cpp +++ b/src/server/game/Entities/Vehicle/Vehicle.cpp @@ -556,7 +556,7 @@ void Vehicle::RelocatePassengers() float px, py, pz, po; passenger->m_movementInfo.t_pos.GetPosition(px, py, pz, po); - CalculatePassengerPosition(px, py, pz, po); + CalculatePassengerPosition(px, py, pz, &po); passenger->UpdatePosition(px, py, pz, po); } @@ -675,24 +675,28 @@ uint8 Vehicle::GetAvailableSeatCount() const return ret; } -void Vehicle::CalculatePassengerPosition(float& x, float& y, float& z, float& o) const +void Vehicle::CalculatePassengerPosition(float& x, float& y, float& z, float* o /*= NULL*/) const { - float inx = x, iny = y, inz = z, ino = o; - o = GetBase()->GetOrientation() + ino; + float inx = x, iny = y, inz = z; + if (o) + *o = Position::NormalizeOrientation(GetBase()->GetOrientation() + *o); + x = GetBase()->GetPositionX() + inx * std::cos(GetBase()->GetOrientation()) - iny * std::sin(GetBase()->GetOrientation()); y = GetBase()->GetPositionY() + iny * std::cos(GetBase()->GetOrientation()) + inx * std::sin(GetBase()->GetOrientation()); z = GetBase()->GetPositionZ() + inz; } -void Vehicle::CalculatePassengerOffset(float& x, float& y, float& z, float& o) const +void Vehicle::CalculatePassengerOffset(float& x, float& y, float& z, float* o /*= NULL*/) const { - o -= GetBase()->GetOrientation(); + if (o) + *o = Position::NormalizeOrientation(*o - GetBase()->GetOrientation()); + z -= GetBase()->GetPositionZ(); y -= GetBase()->GetPositionY(); // y = searchedY * std::cos(o) + searchedX * std::sin(o) x -= GetBase()->GetPositionX(); // x = searchedX * std::cos(o) + searchedY * std::sin(o + pi) float inx = x, iny = y; - y = (iny - inx * tan(GetBase()->GetOrientation())) / (cos(GetBase()->GetOrientation()) + std::sin(GetBase()->GetOrientation()) * tan(GetBase()->GetOrientation())); - x = (inx + iny * tan(GetBase()->GetOrientation())) / (cos(GetBase()->GetOrientation()) + std::sin(GetBase()->GetOrientation()) * tan(GetBase()->GetOrientation())); + y = (iny - inx * std::tan(GetBase()->GetOrientation())) / (std::cos(GetBase()->GetOrientation()) + std::sin(GetBase()->GetOrientation()) * std::tan(GetBase()->GetOrientation())); + x = (inx + iny * std::tan(GetBase()->GetOrientation())) / (std::cos(GetBase()->GetOrientation()) + std::sin(GetBase()->GetOrientation()) * std::tan(GetBase()->GetOrientation())); } /** diff --git a/src/server/game/Entities/Vehicle/Vehicle.h b/src/server/game/Entities/Vehicle/Vehicle.h index 3e4a2fd3a78..c83a9fa5f33 100644 --- a/src/server/game/Entities/Vehicle/Vehicle.h +++ b/src/server/game/Entities/Vehicle/Vehicle.h @@ -89,10 +89,10 @@ class Vehicle : public TransportBase void InitMovementInfoForBase(); /// This method transforms supplied transport offsets into global coordinates - void CalculatePassengerPosition(float& x, float& y, float& z, float& o) const; + void CalculatePassengerPosition(float& x, float& y, float& z, float* o = NULL) const; /// This method transforms supplied global coordinates into local offsets - void CalculatePassengerOffset(float& x, float& y, float& z, float& o) const; + void CalculatePassengerOffset(float& x, float& y, float& z, float* o = NULL) const; void RemovePendingEvent(VehicleJoinEvent* e); void RemovePendingEventsForSeat(int8 seatId); diff --git a/src/server/game/Entities/Vehicle/VehicleDefines.h b/src/server/game/Entities/Vehicle/VehicleDefines.h index 9db8c15f697..55c47df86ad 100644 --- a/src/server/game/Entities/Vehicle/VehicleDefines.h +++ b/src/server/game/Entities/Vehicle/VehicleDefines.h @@ -105,10 +105,10 @@ protected: public: /// This method transforms supplied transport offsets into global coordinates - virtual void CalculatePassengerPosition(float& x, float& y, float& z, float& o) const = 0; + virtual void CalculatePassengerPosition(float& x, float& y, float& z, float* o = NULL) const = 0; /// This method transforms supplied global coordinates into local offsets - virtual void CalculatePassengerOffset(float& x, float& y, float& z, float& o) const = 0; + virtual void CalculatePassengerOffset(float& x, float& y, float& z, float* o = NULL) const = 0; }; #endif diff --git a/src/server/game/Handlers/ItemHandler.cpp b/src/server/game/Handlers/ItemHandler.cpp index d7be695e142..f23a1c9632f 100644 --- a/src/server/game/Handlers/ItemHandler.cpp +++ b/src/server/game/Handlers/ItemHandler.cpp @@ -891,14 +891,14 @@ void WorldSession::HandleAutoStoreBankItemOpcode(WorldPacket& recvPacket) } } -void WorldSession::SendEnchantmentLog(uint64 Target, uint64 Caster, uint32 ItemID, uint32 SpellID) +void WorldSession::SendEnchantmentLog(uint64 target, uint64 caster, uint32 itemId, uint32 enchantId) { - WorldPacket data(SMSG_ENCHANTMENTLOG, (8+8+4+4+1)); // last check 4.3.4 - data.appendPackGUID(Target); - data.appendPackGUID(Caster); - data << uint32(ItemID); - data << uint32(SpellID); - SendPacket(&data); + WorldPacket data(SMSG_ENCHANTMENTLOG, (8+8+4+4)); + data.appendPackGUID(target); + data.appendPackGUID(caster); + data << uint32(itemId); + data << uint32(enchantId); + GetPlayer()->SendMessageToSet(&data, true); } void WorldSession::SendItemEnchantTimeUpdate(uint64 Playerguid, uint64 Itemguid, uint32 slot, uint32 Duration) @@ -1201,10 +1201,12 @@ void WorldSession::HandleSocketOpcode(WorldPacket& recvData) { if (GemEnchants[i]) { - uint32 gemCount = 1; - itemTarget->SetEnchantment(EnchantmentSlot(SOCK_ENCHANTMENT_SLOT+i), GemEnchants[i], 0, 0); + itemTarget->SetEnchantment(EnchantmentSlot(SOCK_ENCHANTMENT_SLOT+i), GemEnchants[i], 0, 0, _player->GetGUID()); if (Item* guidItem = _player->GetItemByGuid(gem_guids[i])) + { + uint32 gemCount = 1; _player->DestroyItemCount(guidItem, gemCount, true); + } } } @@ -1215,7 +1217,7 @@ void WorldSession::HandleSocketOpcode(WorldPacket& recvData) if (SocketBonusActivated ^ SocketBonusToBeActivated) //if there was a change... { _player->ApplyEnchantment(itemTarget, BONUS_ENCHANTMENT_SLOT, false); - itemTarget->SetEnchantment(BONUS_ENCHANTMENT_SLOT, (SocketBonusToBeActivated ? itemTarget->GetTemplate()->socketBonus : 0), 0, 0); + itemTarget->SetEnchantment(BONUS_ENCHANTMENT_SLOT, (SocketBonusToBeActivated ? itemTarget->GetTemplate()->socketBonus : 0), 0, 0, _player->GetGUID()); _player->ApplyEnchantment(itemTarget, BONUS_ENCHANTMENT_SLOT, true); //it is not displayed, client has an inbuilt system to determine if the bonus is activated } @@ -1224,6 +1226,8 @@ void WorldSession::HandleSocketOpcode(WorldPacket& recvData) _player->RemoveTradeableItem(itemTarget); itemTarget->ClearSoulboundTradeable(_player); // clear tradeable flag + + itemTarget->SendUpdateSockets(); } void WorldSession::HandleCancelTempEnchantmentOpcode(WorldPacket& recvData) diff --git a/src/server/game/Handlers/MailHandler.cpp b/src/server/game/Handlers/MailHandler.cpp index cea83bbfa93..d34ea534753 100644 --- a/src/server/game/Handlers/MailHandler.cpp +++ b/src/server/game/Handlers/MailHandler.cpp @@ -307,10 +307,10 @@ void WorldSession::HandleSendMail(WorldPacket& recvData) Item* item = items[i]; if (log) { - sLog->outCommand(GetAccountId(), "GM %s (Account: %u) mail item: %s (Entry: %u Count: %u) " - "to player: %s (Account: %u)", GetPlayerName().c_str(), GetAccountId(), + sLog->outCommand(GetAccountId(), "GM %s (GUID: %u) (Account: %u) mail item: %s (Entry: %u Count: %u) " + "to player: %s (GUID: %u) (Account: %u)", GetPlayerName().c_str(), GetGuidLow(), GetAccountId(), item->GetTemplate()->Name1.c_str(), item->GetEntry(), item->GetCount(), - receiverName.c_str(), receiverAccountId); + receiverName.c_str(), GUID_LOPART(receiverGuid), receiverAccountId); } item->SetNotRefundable(GetPlayer()); // makes the item no longer refundable @@ -329,8 +329,8 @@ void WorldSession::HandleSendMail(WorldPacket& recvData) if (log && money > 0) { - sLog->outCommand(GetAccountId(), "GM %s (Account: %u) mail money: " UI64FMTD " to player: %s (Account: %u)", - GetPlayerName().c_str(), GetAccountId(), money, receiverName.c_str(), receiverAccountId); + sLog->outCommand(GetAccountId(), "GM %s (GUID: %u) (Account: %u) mail money: " UI64FMTD " to player: %s (GUID: %u) (Account: %u)", + GetPlayerName().c_str(), GetGuidLow(), GetAccountId(), money, receiverName.c_str(), GUID_LOPART(receiverGuid), receiverAccountId); } } diff --git a/src/server/game/Handlers/QuestHandler.cpp b/src/server/game/Handlers/QuestHandler.cpp index c785684cf0e..45be13ae776 100644 --- a/src/server/game/Handlers/QuestHandler.cpp +++ b/src/server/game/Handlers/QuestHandler.cpp @@ -603,7 +603,7 @@ void WorldSession::HandlePushQuestToParty(WorldPacket& recvPacket) continue; } - player->PlayerTalkClass->SendQuestGiverQuestDetails(quest, player->GetGUID(), true); + player->PlayerTalkClass->SendQuestGiverQuestDetails(quest, _player->GetGUID(), true); player->SetDivider(_player->GetGUID()); } } diff --git a/src/server/game/Miscellaneous/Language.h b/src/server/game/Miscellaneous/Language.h index c26bbc1dfc9..f3323682e1b 100644 --- a/src/server/game/Miscellaneous/Language.h +++ b/src/server/game/Miscellaneous/Language.h @@ -452,7 +452,7 @@ enum TrinityStrings LANG_COMMAND_GRAVEYARDALRLINKED = 450, LANG_COMMAND_GRAVEYARDLINKED = 451, LANG_COMMAND_GRAVEYARDWRONGZONE = 452, - // = 453, see LANG_PINFO_BAN + // = 453, see LANG_PINFO_PLAYER LANG_COMMAND_GRAVEYARDERROR = 454, LANG_COMMAND_GRAVEYARD_NOTEAM = 455, LANG_COMMAND_GRAVEYARD_ANY = 456, @@ -563,13 +563,9 @@ enum TrinityStrings LANG_NPCINFO_TRAINER = 546, LANG_NPCINFO_DUNGEON_ID = 547, - LANG_PINFO_ACCOUNT = 548, - LANG_PINFO_LEVEL = 549, - LANG_PINFO_MUTE = 550, - LANG_PINFO_BAN = 453, - LANG_PINFO_MAP_ONLINE = 714, - LANG_PINFO_MAP_OFFLINE = 716, - LANG_PINFO_GUILD_INFO = 749, + // = 548, see LANG_PINFO_GM_ACTIVE + // = 549, see LANG_PINFO_BANNED + // = 550, see LANG_PINFO_MUTED LANG_YOU_SET_EXPLORE_ALL = 551, LANG_YOU_SET_EXPLORE_NOTHING = 552, @@ -717,9 +713,9 @@ enum TrinityStrings LANG_BG_QUEUE_ANNOUNCE_SELF = 711, LANG_BG_QUEUE_ANNOUNCE_WORLD = 712, LANG_YOUR_ARENA_LEVEL_REQ_ERROR = 713, -// = 714, see LANG_PINFO_MAP_ONLINE +// = 714, see LANG_PINFO_ACC_ACCOUNT LANG_YOUR_BG_LEVEL_REQ_ERROR = 715, -// = 716, see LANG_PINFO_MAP_OFFLINE +// = 716, see LANG_PINFO_ACC_LASTLOGIN LANG_BG_STARTED_ANNOUNCE_WORLD = 717, LANG_ARENA_QUEUE_ANNOUNCE_WORLD_JOIN= 718, LANG_ARENA_QUEUE_ANNOUNCE_WORLD_EXIT= 719, @@ -754,10 +750,10 @@ enum TrinityStrings // LANG_DIST_ARENA_POINTS_END = 746, LANG_BG_DISABLED = 747, LANG_ARENA_DISABLED = 748, -// = 749, not used +// = 749, see LANG_PINFO_ACC_OS LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING = 750, // "Not enough players. This game will close in %u mins." LANG_BATTLEGROUND_PREMATURE_FINISH_WARNING_SECS = 751, // "Not enough players. This game will close in %u seconds." -// = 752, not used +// = 752, see LANG_PINFO_ACC_IP // LANG_BG_WS_START_TWO_MINUTES = 753, - defined above // LANG_BG_AB_START_TWO_MINUTES = 754, - defined above // LANG_BG_EY_START_TWO_MINUTES = 755, - defined above @@ -815,7 +811,46 @@ enum TrinityStrings LANG_NPCINFO_MAILBOX = 841, LANG_NPCINFO_PLAYER_VEHICLE = 842, - // Room for in-game strings 843-999 not used + // Pinfo commands + LANG_PINFO_PLAYER = 453, + LANG_PINFO_GM_ACTIVE = 548, + LANG_PINFO_BANNED = 549, + LANG_PINFO_MUTED = 550, + LANG_PINFO_ACC_ACCOUNT = 714, + LANG_PINFO_ACC_LASTLOGIN = 716, + LANG_PINFO_ACC_OS = 749, + LANG_PINFO_ACC_IP = 752, + LANG_PINFO_CHR_LEVEL = 843, + LANG_PINFO_CHR_RACE = 844, + LANG_PINFO_CHR_ALIVE = 845, + LANG_PINFO_CHR_PHASE = 846, + LANG_PINFO_CHR_MONEY = 847, + LANG_PINFO_CHR_MAP = 848, + LANG_PINFO_CHR_GUILD = 849, + LANG_PINFO_CHR_GUILD_RANK = 850, + LANG_PINFO_CHR_GUILD_NOTE = 851, + LANG_PINFO_CHR_GUILD_ONOTE = 852, + LANG_PINFO_CHR_PLAYEDTIME = 853, + LANG_PINFO_CHR_MAILS = 854, + + LANG_CHARACTER_GENDER_MALE = 855, + LANG_CHARACTER_GENDER_FEMALE = 856, + + LANG_ARENA_ERROR_NOT_FOUND = 857, + LANG_ARENA_ERROR_NAME_EXISTS = 858, + LANG_ARENA_ERROR_SIZE = 859, + LANG_ARENA_ERROR_COMBAT = 860, + LANG_AREAN_ERROR_NAME_NOT_FOUND = 861, + LANG_ARENA_ERROR_NOT_MEMBER = 862, + LANG_ARENA_ERROR_CAPTAIN = 863, + LANG_ARENA_CREATE = 864, + LANG_ARENA_DISBAND = 865, + LANG_ARENA_RENAME = 866, + LANG_ARENA_CAPTAIN = 867, + LANG_ARENA_INFO_HEADER = 868, + LANG_ARENA_INFO_MEMBERS = 869, + LANG_ARENA_LOOKUP = 870, + // Room for in-game strings 870-999 not used // Level 4 (CLI only commands) LANG_COMMAND_EXIT = 1000, diff --git a/src/server/game/Movement/MotionMaster.h b/src/server/game/Movement/MotionMaster.h index f2f3959dba5..156813f56fb 100644 --- a/src/server/game/Movement/MotionMaster.h +++ b/src/server/game/Movement/MotionMaster.h @@ -153,8 +153,8 @@ class MotionMaster //: private std::stack<MovementGenerator *> void MoveChase(Unit* target, float dist = 0.0f, float angle = 0.0f); void MoveConfused(); void MoveFleeing(Unit* enemy, uint32 time = 0); - void MovePoint(uint32 id, const Position &pos) - { MovePoint(id, pos.m_positionX, pos.m_positionY, pos.m_positionZ); } + void MovePoint(uint32 id, Position const& pos, bool generatePath = true) + { MovePoint(id, pos.m_positionX, pos.m_positionY, pos.m_positionZ, generatePath); } void MovePoint(uint32 id, float x, float y, float z, bool generatePath = true); // These two movement types should only be used with creatures having landing/takeoff animations diff --git a/src/server/game/Movement/Spline/MoveSplineInit.cpp b/src/server/game/Movement/Spline/MoveSplineInit.cpp index d42df898a7e..8a60ae05f41 100644 --- a/src/server/game/Movement/Spline/MoveSplineInit.cpp +++ b/src/server/game/Movement/Spline/MoveSplineInit.cpp @@ -207,13 +207,8 @@ namespace Movement Vector3 TransportPathTransform::operator()(Vector3 input) { if (_transformForTransport) - { if (TransportBase* transport = _owner->GetDirectTransport()) - { - float unused = 0.0f; // need reference - transport->CalculatePassengerOffset(input.x, input.y, input.z, unused); - } - } + transport->CalculatePassengerOffset(input.x, input.y, input.z); return input; } diff --git a/src/server/game/Scripting/ScriptLoader.cpp b/src/server/game/Scripting/ScriptLoader.cpp index ec1b7ac609e..b566f9dabe1 100644 --- a/src/server/game/Scripting/ScriptLoader.cpp +++ b/src/server/game/Scripting/ScriptLoader.cpp @@ -46,6 +46,7 @@ void AddSC_SmartSCripts(); //Commands void AddSC_account_commandscript(); void AddSC_achievement_commandscript(); +void AddSC_arena_commandscript(); void AddSC_ban_commandscript(); void AddSC_bf_commandscript(); void AddSC_cast_commandscript(); @@ -680,6 +681,7 @@ void AddCommandScripts() { AddSC_account_commandscript(); AddSC_achievement_commandscript(); + AddSC_arena_commandscript(); AddSC_ban_commandscript(); AddSC_bf_commandscript(); AddSC_cast_commandscript(); diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp index 7572bfcc860..5e66efea913 100644 --- a/src/server/game/Server/Protocol/Opcodes.cpp +++ b/src/server/game/Server/Protocol/Opcodes.cpp @@ -1166,6 +1166,7 @@ void OpcodeTable::Initialize() DEFINE_OPCODE_HANDLER(SMSG_SHOWTAXINODES, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); DEFINE_OPCODE_HANDLER(SMSG_SHOW_BANK, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); DEFINE_OPCODE_HANDLER(SMSG_SHOW_RATINGS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); + DEFINE_OPCODE_HANDLER(SMSG_SOCKET_GEMS_RESULT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); DEFINE_OPCODE_HANDLER(SMSG_SOR_START_EXPERIENCE_INCOMPLETE, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); DEFINE_OPCODE_HANDLER(SMSG_SPELLBREAKLOG, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); DEFINE_OPCODE_HANDLER(SMSG_SPELLDAMAGESHIELD, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); @@ -1263,7 +1264,6 @@ void OpcodeTable::Initialize() DEFINE_OPCODE_HANDLER(SMSG_UPDATE_DUNGEON_ENCOUNTER_FOR_LOOT, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); DEFINE_OPCODE_HANDLER(SMSG_UPDATE_INSTANCE_ENCOUNTER_UNIT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); DEFINE_OPCODE_HANDLER(SMSG_UPDATE_INSTANCE_OWNERSHIP, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - DEFINE_OPCODE_HANDLER(SMSG_UPDATE_ITEM_ENCHANTMENTS, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); DEFINE_OPCODE_HANDLER(SMSG_UPDATE_LAST_INSTANCE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); DEFINE_OPCODE_HANDLER(SMSG_UPDATE_OBJECT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); DEFINE_OPCODE_HANDLER(SMSG_UPDATE_SERVER_PLAYER_POSITION, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); @@ -1440,13 +1440,10 @@ void OpcodeTable::Initialize() //DEFINE_OPCODE_HANDLER(CMSG_MOVE_CHARM_PORT_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); //DEFINE_OPCODE_HANDLER(CMSG_MOVE_CHARM_TELEPORT_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); //DEFINE_OPCODE_HANDLER(CMSG_MOVE_ENABLE_SWIM_TO_FLY_TRANS_ACK, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); - //DEFINE_OPCODE_HANDLER(CMSG_MOVE_SET_FLY, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes ); //DEFINE_OPCODE_HANDLER(CMSG_MOVE_SET_RELATIVE_POSITION, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); - //DEFINE_OPCODE_HANDLER(CMSG_MOVE_SET_RUN_SPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); //DEFINE_OPCODE_HANDLER(CMSG_MOVE_SET_VEHICLE_REC_ID_ACK, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); //DEFINE_OPCODE_HANDLER(CMSG_MOVE_START_SWIM_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); //DEFINE_OPCODE_HANDLER(CMSG_MOVE_STOP_SWIM_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); - //DEFINE_OPCODE_HANDLER(CMSG_MOVE_TOGGLE_COLLISION_ACK, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); //DEFINE_OPCODE_HANDLER(CMSG_NEW_SPELL_SLOT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); //DEFINE_OPCODE_HANDLER(CMSG_NO_SPELL_VARIANCE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); //DEFINE_OPCODE_HANDLER(CMSG_PERFORM_ACTION_SET, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); @@ -1557,18 +1554,12 @@ void OpcodeTable::Initialize() //DEFINE_OPCODE_HANDLER(MSG_GM_RESETINSTANCELIMIT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); //DEFINE_OPCODE_HANDLER(MSG_GM_SHOWLABEL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); //DEFINE_OPCODE_HANDLER(MSG_GM_SUMMON, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); - //DEFINE_OPCODE_HANDLER(MSG_MOVE_FEATHER_FALL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); - //DEFINE_OPCODE_HANDLER(MSG_MOVE_GRAVITY_CHNG, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); - //DEFINE_OPCODE_HANDLER(MSG_MOVE_HOVER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); - //DEFINE_OPCODE_HANDLER(MSG_MOVE_ROOT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); //DEFINE_OPCODE_HANDLER(MSG_MOVE_SET_ALL_SPEED_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); - //DEFINE_OPCODE_HANDLER(MSG_MOVE_SET_COLLISION_HEIGHT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); //DEFINE_OPCODE_HANDLER(MSG_MOVE_SET_FLIGHT_BACK_SPEED_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); //DEFINE_OPCODE_HANDLER(MSG_MOVE_SET_FLIGHT_SPEED_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); //DEFINE_OPCODE_HANDLER(MSG_MOVE_SET_PITCH_RATE_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); //DEFINE_OPCODE_HANDLER(MSG_MOVE_SET_RAW_POSITION_ACK, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); //DEFINE_OPCODE_HANDLER(MSG_MOVE_SET_RUN_BACK_SPEED_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); - //DEFINE_OPCODE_HANDLER(MSG_MOVE_SET_RUN_SPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); //DEFINE_OPCODE_HANDLER(MSG_MOVE_SET_RUN_SPEED_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); //DEFINE_OPCODE_HANDLER(MSG_MOVE_SET_SWIM_BACK_SPEED_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); //DEFINE_OPCODE_HANDLER(MSG_MOVE_SET_SWIM_SPEED_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); @@ -1578,10 +1569,6 @@ void OpcodeTable::Initialize() //DEFINE_OPCODE_HANDLER(MSG_MOVE_STOP_SWIM_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); //DEFINE_OPCODE_HANDLER(MSG_MOVE_TOGGLE_FALL_LOGGING, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); //DEFINE_OPCODE_HANDLER(MSG_MOVE_TOGGLE_LOGGING, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); - //DEFINE_OPCODE_HANDLER(MSG_MOVE_UPDATE_CAN_FLY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); - //DEFINE_OPCODE_HANDLER(MSG_MOVE_UPDATE_CAN_TRANSITION_BETWEEN_SWIM_AND_FLY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); - //DEFINE_OPCODE_HANDLER(MSG_MOVE_UPDATE_MOUSE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); - //DEFINE_OPCODE_HANDLER(MSG_MOVE_WATER_WALK, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); //DEFINE_OPCODE_HANDLER(MSG_NULL_ACTION, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); //DEFINE_OPCODE_HANDLER(MSG_PVP_LOG_DATA, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePVPLogDataOpcode ); //DEFINE_OPCODE_HANDLER(MSG_VIEW_PHASE_SHIFT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); @@ -1602,11 +1589,6 @@ void OpcodeTable::Initialize() //DEFINE_OPCODE_HANDLER(SMSG_COMBAT_LOG_MULTIPLE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //DEFINE_OPCODE_HANDLER(SMSG_COMMENTATOR_GET_PLAYER_INFO, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //DEFINE_OPCODE_HANDLER(SMSG_COMPLETION_NPC_RESPONCE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - //DEFINE_OPCODE_HANDLER(SMSG_COMPRESSED_ACHIEVEMENT_DATA, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - //DEFINE_OPCODE_HANDLER(SMSG_COMPRESSED_CHAR_ENUM, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - //DEFINE_OPCODE_HANDLER(SMSG_COMPRESSED_GUILD_ROSTER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - //DEFINE_OPCODE_HANDLER(SMSG_COMPRESSED_UNKNOWN_1310, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - //DEFINE_OPCODE_HANDLER(SMSG_COMPRESSED_UPDATE_OBJECT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //DEFINE_OPCODE_HANDLER(SMSG_CORPSE_IS_NOT_IN_INSTANCE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //DEFINE_OPCODE_HANDLER(SMSG_DAMAGE_DONE_OBSOLETE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //DEFINE_OPCODE_HANDLER(SMSG_DBLOOKUP, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); @@ -1647,15 +1629,10 @@ void OpcodeTable::Initialize() //DEFINE_OPCODE_HANDLER(SMSG_MEETINGSTONE_SETQUEUE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //DEFINE_OPCODE_HANDLER(SMSG_MINIGAME_MOVE_FAILED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //DEFINE_OPCODE_HANDLER(SMSG_MOVE_CHARACTER_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - //DEFINE_OPCODE_HANDLER(SMSG_MOVE_DISABLE_COLLISION, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - //DEFINE_OPCODE_HANDLER(SMSG_MOVE_DISABLE_GRAVITY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - //DEFINE_OPCODE_HANDLER(SMSG_MOVE_ENABLE_COLLISION, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - //DEFINE_OPCODE_HANDLER(SMSG_MOVE_ENABLE_GRAVITY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //DEFINE_OPCODE_HANDLER(SMSG_MOVE_SET_VEHICLE_REC_ID, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //DEFINE_OPCODE_HANDLER(SMSG_MOVE_SET_WALK_IN_AIR, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //DEFINE_OPCODE_HANDLER(SMSG_MOVE_SKIP_TIME, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //DEFINE_OPCODE_HANDLER(SMSG_MOVE_UNSET_WALK_IN_AIR, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - //DEFINE_OPCODE_HANDLER(SMSG_MOVE_UPDATE_TELEPORT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //DEFINE_OPCODE_HANDLER(SMSG_NPC_WONT_TALK, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //DEFINE_OPCODE_HANDLER(SMSG_PET_UNLEARN_CONFIRM, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //DEFINE_OPCODE_HANDLER(SMSG_PLAYER_UNK_DEAD_ALIVE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); @@ -1680,18 +1657,6 @@ void OpcodeTable::Initialize() //DEFINE_OPCODE_HANDLER(SMSG_SHOW_MAILBOX, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //DEFINE_OPCODE_HANDLER(SMSG_SPELL_CHANCE_PROC_LOG, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //DEFINE_OPCODE_HANDLER(SMSG_SPELL_CHANCE_RESIST_PUSHBACK, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - //DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_LAND_WALK, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - //DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_NORMAL_FALL, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - //DEFINE_OPCODE_HANDLER(SMSG_SPLINE_MOVE_SET_WATER_WALK, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - //DEFINE_OPCODE_HANDLER(SMSG_SPLINE_SET_FLIGHT_BACK_SPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - //DEFINE_OPCODE_HANDLER(SMSG_SPLINE_SET_FLIGHT_SPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - //DEFINE_OPCODE_HANDLER(SMSG_SPLINE_SET_PITCH_RATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - //DEFINE_OPCODE_HANDLER(SMSG_SPLINE_SET_RUN_BACK_SPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - //DEFINE_OPCODE_HANDLER(SMSG_SPLINE_SET_RUN_SPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - //DEFINE_OPCODE_HANDLER(SMSG_SPLINE_SET_SWIM_BACK_SPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - //DEFINE_OPCODE_HANDLER(SMSG_SPLINE_SET_SWIM_SPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - //DEFINE_OPCODE_HANDLER(SMSG_SPLINE_SET_TURN_RATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); - //DEFINE_OPCODE_HANDLER(SMSG_SPLINE_SET_WALK_SPEED, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //DEFINE_OPCODE_HANDLER(SMSG_VOICE_SESSION_ADJUST_PRIORITY, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //DEFINE_OPCODE_HANDLER(SMSG_VOICE_SESSION_ENABLE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); //DEFINE_OPCODE_HANDLER(SMSG_ZONE_MAP, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_ServerSide ); diff --git a/src/server/game/Server/Protocol/Opcodes.h b/src/server/game/Server/Protocol/Opcodes.h index d7c1cfdd3e1..ad3ced93210 100644 --- a/src/server/game/Server/Protocol/Opcodes.h +++ b/src/server/game/Server/Protocol/Opcodes.h @@ -1250,6 +1250,7 @@ enum Opcodes SMSG_SHOWTAXINODES = 0x2A36, SMSG_SHOW_BANK = 0x2627, SMSG_SHOW_RATINGS = 0x11B4, + SMSG_SOCKET_GEMS_RESULT = 0x6014, SMSG_SOR_START_EXPERIENCE_INCOMPLETE = 0x7CA7, SMSG_SPELLBREAKLOG = 0x6B17, SMSG_SPELLDAMAGESHIELD = 0x2927, @@ -1348,7 +1349,6 @@ enum Opcodes SMSG_UPDATE_DUNGEON_ENCOUNTER_FOR_LOOT = 0x3CB5, SMSG_UPDATE_INSTANCE_ENCOUNTER_UNIT = 0x4007, SMSG_UPDATE_INSTANCE_OWNERSHIP = 0x4915, - SMSG_UPDATE_ITEM_ENCHANTMENTS = 0x6014, SMSG_UPDATE_LAST_INSTANCE = 0x0437, SMSG_UPDATE_OBJECT = 0x4715, SMSG_UPDATE_SERVER_PLAYER_POSITION = 0x74A3, diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index d4c4e5ef477..bc8718ef721 100644 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -328,7 +328,7 @@ class WorldSession void SendAuctionRemovedNotification(uint32 auctionId, uint32 itemEntry, int32 randomPropertyId); //Item Enchantment - void SendEnchantmentLog(uint64 Target, uint64 Caster, uint32 ItemID, uint32 SpellID); + void SendEnchantmentLog(uint64 target, uint64 caster, uint32 itemId, uint32 enchantId); void SendItemEnchantTimeUpdate(uint64 Playerguid, uint64 Itemguid, uint32 slot, uint32 Duration); //Taxi diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index 4be79d4b52b..80eadb9ac0e 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -2602,7 +2602,7 @@ void Spell::EffectEnchantItemPerm(SpellEffIndex effIndex) // remove old enchanting before applying new if equipped item_owner->ApplyEnchantment(itemTarget, PERM_ENCHANTMENT_SLOT, false); - itemTarget->SetEnchantment(PERM_ENCHANTMENT_SLOT, enchant_id, 0, 0); + itemTarget->SetEnchantment(PERM_ENCHANTMENT_SLOT, enchant_id, 0, 0, m_caster->GetGUID()); // add new enchanting if equipped item_owner->ApplyEnchantment(itemTarget, PERM_ENCHANTMENT_SLOT, true); @@ -2667,7 +2667,7 @@ void Spell::EffectEnchantItemPrismatic(SpellEffIndex effIndex) // remove old enchanting before applying new if equipped item_owner->ApplyEnchantment(itemTarget, PRISMATIC_ENCHANTMENT_SLOT, false); - itemTarget->SetEnchantment(PRISMATIC_ENCHANTMENT_SLOT, enchant_id, 0, 0); + itemTarget->SetEnchantment(PRISMATIC_ENCHANTMENT_SLOT, enchant_id, 0, 0, m_caster->GetGUID()); // add new enchanting if equipped item_owner->ApplyEnchantment(itemTarget, PRISMATIC_ENCHANTMENT_SLOT, true); @@ -2749,7 +2749,7 @@ void Spell::EffectEnchantItemTmp(SpellEffIndex effIndex) // remove old enchanting before applying new if equipped item_owner->ApplyEnchantment(itemTarget, TEMP_ENCHANTMENT_SLOT, false); - itemTarget->SetEnchantment(TEMP_ENCHANTMENT_SLOT, enchant_id, duration * 1000, 0); + itemTarget->SetEnchantment(TEMP_ENCHANTMENT_SLOT, enchant_id, duration * 1000, 0, m_caster->GetGUID()); // add new enchanting if equipped item_owner->ApplyEnchantment(itemTarget, TEMP_ENCHANTMENT_SLOT, true); @@ -4243,7 +4243,7 @@ void Spell::EffectEnchantHeldItem(SpellEffIndex effIndex) if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER) return; - Player* item_owner = (Player*)unitTarget; + Player* item_owner = unitTarget->ToPlayer(); Item* item = item_owner->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND); if (!item) @@ -4274,7 +4274,7 @@ void Spell::EffectEnchantHeldItem(SpellEffIndex effIndex) return; // Apply the temporary enchantment - item->SetEnchantment(slot, enchant_id, duration*IN_MILLISECONDS, 0); + item->SetEnchantment(slot, enchant_id, duration*IN_MILLISECONDS, 0, m_caster->GetGUID()); item_owner->ApplyEnchantment(item, slot, true); } } diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index a2a4a85808a..3ee6266b0d2 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -499,6 +499,9 @@ uint32 SpellMgr::GetSpellIdForDifficulty(uint32 spellId, Unit const* caster) con SpellInfo const* SpellMgr::GetSpellForDifficultyFromSpell(SpellInfo const* spell, Unit const* caster) const { + if (!spell) + return NULL; + uint32 newSpellId = GetSpellIdForDifficulty(spell->Id, caster); SpellInfo const* newSpell = GetSpellInfo(newSpellId); if (!newSpell) diff --git a/src/server/scripts/Commands/CMakeLists.txt b/src/server/scripts/Commands/CMakeLists.txt index 15e16c2caf1..ce31fa1f4d3 100644 --- a/src/server/scripts/Commands/CMakeLists.txt +++ b/src/server/scripts/Commands/CMakeLists.txt @@ -12,6 +12,7 @@ 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 diff --git a/src/server/scripts/Commands/cs_arena.cpp b/src/server/scripts/Commands/cs_arena.cpp new file mode 100644 index 00000000000..82a1109efd2 --- /dev/null +++ b/src/server/scripts/Commands/cs_arena.cpp @@ -0,0 +1,347 @@ +/* + * 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/>. + */ + +/* ScriptData +Name: arena_commandscript +%Complete: 100 +Comment: All arena team related commands +Category: commandscripts +EndScriptData */ + +#include "ObjectMgr.h" +#include "Chat.h" +#include "Language.h" +#include "ArenaTeamMgr.h" +#include "Player.h" +#include "ScriptMgr.h" + +class arena_commandscript : public CommandScript +{ +public: + arena_commandscript() : CommandScript("arena_commandscript") { } + + ChatCommand* GetCommands() const + { + 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 } + }; + static ChatCommand commandTable[] = + { + { "arena", SEC_GAMEMASTER, false, NULL, "", arenaCommandTable }, + { NULL, SEC_PLAYER, false, NULL, "", NULL } + }; + return commandTable; + } + + static bool HandleArenaCreateCommand(ChatHandler* handler, char const* args) + { + if (!*args) + return false; + + Player* target; + if (!handler->extractPlayerTarget(*args != '"' ? (char*)args : NULL, &target)) + return false; + + char* tailStr = *args != '"' ? strtok(NULL, "") : (char*)args; + if (!tailStr) + return false; + + char* name = handler->extractQuotedArg(tailStr); + if (!name) + return false; + char* typeStr = strtok(NULL, ""); + if (!typeStr) + return false; + int8 type = atoi(typeStr); + if (sArenaTeamMgr->GetArenaTeamByName(name)) + { + handler->PSendSysMessage(LANG_ARENA_ERROR_NAME_EXISTS, name); + handler->SetSentErrorMessage(true); + return false; + } + + if (type == 2 || type == 3 || type == 5 ) + { + if (Player::GetArenaTeamIdFromDB(target->GetGUID(), type) != 0) + { + handler->PSendSysMessage(LANG_ARENA_ERROR_SIZE, target->GetName().c_str()); + handler->SetSentErrorMessage(true); + return false; + } + + ArenaTeam* Arena = new ArenaTeam(); + + if (!Arena->Create(target->GetGUID(), type, name, 4293102085, 101, 4293253939, 4, 4284049911)) + { + delete Arena; + handler->SendSysMessage(LANG_BAD_VALUE); + handler->SetSentErrorMessage(true); + return false; + } + + sArenaTeamMgr->AddArenaTeam(Arena); + handler->PSendSysMessage(LANG_ARENA_CREATE, Arena->GetName().c_str(), Arena->GetId(), Arena->GetType(), Arena->GetCaptain()); + } + else + { + handler->SendSysMessage(LANG_BAD_VALUE); + handler->SetSentErrorMessage(true); + return false; + } + return true; + } + + static bool HandleArenaDisbandCommand(ChatHandler* handler, char const* args) + { + if (!*args) + return false; + + uint32 teamId = atoi((char*)args); + if (!teamId) + return false; + + ArenaTeam* Arena = sArenaTeamMgr->GetArenaTeamById(teamId); + + if (!Arena) + { + handler->PSendSysMessage(LANG_ARENA_ERROR_NOT_FOUND, teamId); + handler->SetSentErrorMessage(true); + return false; + } + + if (Arena->IsFighting()) + { + handler->SendSysMessage(LANG_ARENA_ERROR_COMBAT); + handler->SetSentErrorMessage(true); + return false; + } + std::string name = Arena->GetName(); + Arena->Disband(); + if (handler->GetSession()) + TC_LOG_DEBUG(LOG_FILTER_ARENAS, "GameMaster: %s [GUID: %u] disbanded arena team type: %u [Id: %u].", + handler->GetSession()->GetPlayer()->GetName().c_str(), handler->GetSession()->GetPlayer()->GetGUIDLow(), Arena->GetType(), teamId); + else + TC_LOG_DEBUG(LOG_FILTER_ARENAS, "Console: disbanded arena team type: %u [Id: %u].", Arena->GetType(), teamId); + delete(Arena); + handler->PSendSysMessage(LANG_ARENA_DISBAND, name.c_str(), teamId); + return true; + } + + static bool HandleArenaRenameCommand(ChatHandler* handler, char const* _args) + { + if (!*_args) + return false; + + char* args = (char *)_args; + + char const* oldArenaStr = handler->extractQuotedArg(args); + if (!oldArenaStr) + { + handler->SendSysMessage(LANG_BAD_VALUE); + handler->SetSentErrorMessage(true); + return false; + } + + char const* newArenaStr = handler->extractQuotedArg(strtok(NULL, "")); + if (!newArenaStr) + { + handler->SendSysMessage(LANG_BAD_VALUE); + handler->SetSentErrorMessage(true); + return false; + } + + ArenaTeam* Arena = sArenaTeamMgr->GetArenaTeamByName(oldArenaStr); + if (!Arena) + { + handler->PSendSysMessage(LANG_AREAN_ERROR_NAME_NOT_FOUND, oldArenaStr); + handler->SetSentErrorMessage(true); + return false; + } + + if (sArenaTeamMgr->GetArenaTeamByName(newArenaStr)) + { + handler->PSendSysMessage(LANG_ARENA_ERROR_NAME_EXISTS, oldArenaStr); + handler->SetSentErrorMessage(true); + return false; + } + + if (Arena->IsFighting()) + { + handler->SendSysMessage(LANG_ARENA_ERROR_COMBAT); + handler->SetSentErrorMessage(true); + return false; + } + + if (!Arena->SetName(newArenaStr)) + { + handler->SendSysMessage(LANG_BAD_VALUE); + handler->SetSentErrorMessage(true); + return false; + } + handler->PSendSysMessage(LANG_ARENA_RENAME, Arena->GetId(), oldArenaStr, newArenaStr); + if (handler->GetSession()) + TC_LOG_DEBUG(LOG_FILTER_ARENAS, "GameMaster: %s [GUID: %u] rename arena team \"%s\"[Id: %u] to \"%s\"", + handler->GetSession()->GetPlayer()->GetName().c_str(), handler->GetSession()->GetPlayer()->GetGUIDLow(), oldArenaStr, Arena->GetId(), newArenaStr); + else + TC_LOG_DEBUG(LOG_FILTER_ARENAS, "Console: rename arena team \"%s\"[Id: %u] to \"%s\"", oldArenaStr, Arena->GetId(), newArenaStr); + return true; + } + + static bool HandleArenaCaptainCommand(ChatHandler* handler, char const* args) + { + if (!*args) + return false; + + char* idStr; + char* nameStr; + handler->extractOptFirstArg((char*)args, &idStr, &nameStr); + if (!idStr) + return false; + + uint32 teamId = atoi(idStr); + if (!teamId) + return false; + + Player* target; + uint64 targetGuid; + if (!handler->extractPlayerTarget(nameStr, &target, &targetGuid)) + return false; + + ArenaTeam* Arena = sArenaTeamMgr->GetArenaTeamById(teamId); + + if (!Arena) + { + handler->PSendSysMessage(LANG_ARENA_ERROR_NOT_FOUND, teamId); + handler->SetSentErrorMessage(true); + return false; + } + + if (!target) + { + handler->PSendSysMessage(LANG_PLAYER_NOT_EXIST_OR_OFFLINE, nameStr); + handler->SetSentErrorMessage(true); + return false; + } + + if (Arena->IsFighting()) + { + handler->SendSysMessage(LANG_ARENA_ERROR_COMBAT); + handler->SetSentErrorMessage(true); + return false; + } + + if (!Arena->IsMember(targetGuid)) + { + handler->PSendSysMessage(LANG_ARENA_ERROR_NOT_MEMBER, nameStr, Arena->GetName().c_str()); + handler->SetSentErrorMessage(true); + return false; + } + + if (Arena->GetCaptain() == targetGuid) + { + handler->PSendSysMessage(LANG_ARENA_ERROR_CAPTAIN, nameStr, Arena->GetName().c_str()); + handler->SetSentErrorMessage(true); + return false; + } + + Player* oldCaptain = sObjectMgr->GetPlayerByLowGUID(Arena->GetCaptain()); + Arena->SetCaptain(targetGuid); + handler->PSendSysMessage(LANG_ARENA_CAPTAIN, Arena->GetName().c_str(), Arena->GetId(), oldCaptain->GetName().c_str(), target->GetName().c_str()); + if (handler->GetSession()) + TC_LOG_DEBUG(LOG_FILTER_ARENAS, "GameMaster: %s [GUID: %u] promoted player: %s [GUID: %u] to leader of arena team \"%s\"[Id: %u]", + handler->GetSession()->GetPlayer()->GetName().c_str(), handler->GetSession()->GetPlayer()->GetGUIDLow(), target->GetName().c_str(), target->GetGUIDLow(), Arena->GetName().c_str(), Arena->GetId()); + else + TC_LOG_DEBUG(LOG_FILTER_ARENAS, "Console: promoted player: %s [GUID: %u] to leader of arena team \"%s\"[Id: %u]", + target->GetName().c_str(), target->GetGUIDLow(), Arena->GetName().c_str(), Arena->GetId()); + return true; + } + + static bool HandleArenaInfoCommand(ChatHandler* handler, char const* args) + { + if (!*args) + return false; + + uint32 teamId = atoi((char*)args); + if (!teamId) + return false; + + ArenaTeam* Arena = sArenaTeamMgr->GetArenaTeamById(teamId); + + if (!Arena) + { + handler->PSendSysMessage(LANG_ARENA_ERROR_NOT_FOUND, teamId); + handler->SetSentErrorMessage(true); + return false; + } + + handler->PSendSysMessage(LANG_ARENA_INFO_HEADER, Arena->GetName().c_str(), Arena->GetId(), Arena->GetRating(), Arena->GetType(), Arena->GetType()); + for (ArenaTeam::MemberList::iterator itr = Arena->m_membersBegin(); itr != Arena->m_membersEnd(); ++itr) + { + handler->PSendSysMessage(LANG_ARENA_INFO_MEMBERS, itr->Name.c_str(), GUID_LOPART(itr->Guid), itr->PersonalRating, (Arena->GetCaptain() == itr->Guid ? "- Captain" : "")); + } + return true; + } + + static bool HandleArenaLookupCommand(ChatHandler* handler, char const* args) + { + if (!*args) + return false; + + std::string namepart = args; + std::wstring wnamepart; + + if (!Utf8toWStr(namepart, wnamepart)) + return false; + + wstrToLower(wnamepart); + + bool found = false; + ArenaTeamMgr::ArenaTeamContainer::const_iterator i = sArenaTeamMgr->GetArenaTeamMapBegin(); + for (; i != sArenaTeamMgr->GetArenaTeamMapEnd(); ++i) + { + ArenaTeam* Arena = i->second; + + if (Utf8FitTo(Arena->GetName(), wnamepart)) + { + if (handler->GetSession()) + handler->PSendSysMessage(LANG_ARENA_LOOKUP, Arena->GetName().c_str(), Arena->GetId(), Arena->GetType(), Arena->GetType()); + + if (!found) + found = true; + + continue; + } + } + + if (!found) + handler->PSendSysMessage(LANG_AREAN_ERROR_NAME_NOT_FOUND, namepart.c_str()); + + return true; + } +}; + +void AddSC_arena_commandscript() +{ + new arena_commandscript(); +} diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp index 489c11e0f94..46eda11bfed 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -1472,37 +1472,124 @@ public: return true; } - // show info of player + + /** + * @name Player command: .pinfo + * @date 05/19/2013 + * + * @brief Prints information about a character and it's linked account to the commander + * + * Non-applying information, e.g. a character that is not in gm mode right now or + * that is not banned/muted, is not printed + * + * This can be done either by giving a name or by targeting someone, else, it'll use the commander + * + * @param args name Prints information according to the given name to the commander + * target Prints information on the target to the commander + * none No given args results in printing information on the commander + * + * @return Several pieces of information about the character and the account + **/ + static bool HandlePInfoCommand(ChatHandler* handler, char const* args) { + // Define ALL the player variables! Player* target; uint64 targetGuid; std::string targetName; + // To make sure we get a target, we convert our guid to an omniversal... uint32 parseGUID = MAKE_NEW_GUID(atol((char*)args), 0, HIGHGUID_PLAYER); + // ... and make sure we get a target, somehow. if (sObjectMgr->GetPlayerNameByGUID(parseGUID, targetName)) { target = sObjectMgr->GetPlayerByLowGUID(parseGUID); targetGuid = parseGUID; } + // if not, then return false. Which shouldn't happen, now should it ? else if (!handler->extractPlayerTarget((char*)args, &target, &targetGuid, &targetName)) return false; - uint32 accId = 0; - uint32 money = 0; - uint32 totalPlayerTime = 0; - uint8 level = 0; - uint32 latency = 0; - uint8 race; - uint8 Class; - int64 muteTime = 0; - int64 banTime = -1; + /* The variables we extract for the command. They are + * default as "does not exist" to prevent problems + * The output is printed in the follow manner: + * + * Player %s %s (guid: %u) - I. LANG_PINFO_PLAYER + * ** GM Mode active, Phase: -1 - II. LANG_PINFO_GM_ACTIVE (if GM) + * ** Banned: (Type, Reason, Time, By) - III. LANG_PINFO_BANNED (if banned) + * ** 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) + * + * Not all of them can be moved to the top. These should + * place the most important ones to the head, though. + * + * For a cleaner overview, I segment each output in Roman numerals + */ + + // Account data print variables + std::string userName = handler->GetTrinityString(LANG_ERROR); + uint32 accId = 0; + uint32 lowguid = GUID_LOPART(targetGuid); + std::string eMail = handler->GetTrinityString(LANG_ERROR); + uint32 security = 0; + std::string lastIp = handler->GetTrinityString(LANG_ERROR); + uint8 locked = 0; + std::string lastLogin = handler->GetTrinityString(LANG_ERROR); + uint32 failedLogins = 0; + uint32 latency = 0; + std::string OS = "None"; + + // Mute data print variables + int64 muteTime = -1; + std::string muteReason = "unknown"; + std::string muteBy = "unknown"; + + // Ban data print variables + int64 banTime = -1; + std::string banType = "None"; + std::string banReason = "Unknown"; + std::string bannedBy = "Unknown"; + + // Character data print variables + uint8 raceid, classid = 0; //RACE_NONE, CLASS_NONE + std::string raceStr, classStr = "None"; + uint8 gender = 0; + int8 locale = handler->GetSessionDbcLocale(); + std::string genderStr = handler->GetTrinityString(LANG_ERROR); + uint32 totalPlayerTime = 0; + uint8 level = 0; + std::string alive = handler->GetTrinityString(LANG_ERROR); + uint32 money = 0; + uint32 xp = 0; + uint32 xptotal = 0; + + // Position data print uint32 mapId; uint32 areaId; uint32 phase = 0; + std::string areaName = "<unknown>"; + std::string zoneName = "<unknown>"; + + // Guild data print is only defined if part of Guild + + // Mail data print is only defined if you have a mail - // get additional information from Player object if (target) { // check online security @@ -1514,11 +1601,13 @@ public: totalPlayerTime = target->GetTotalPlayedTime(); level = target->getLevel(); latency = target->GetSession()->GetLatency(); - race = target->getRace(); - Class = target->getClass(); + raceid = target->getRace(); + classid = target->getClass(); muteTime = target->GetSession()->m_muteTime; mapId = target->GetMapId(); areaId = target->GetAreaId(); + alive = target->isAlive() ? "Yes" : "No"; + gender = target->getGender(); phase = target->GetPhaseMask(); } // get additional information from DB @@ -1528,8 +1617,9 @@ public: if (handler->HasLowerSecurity(NULL, targetGuid)) return false; + // Query informations from the DB PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_PINFO); - stmt->setUInt32(0, GUID_LOPART(targetGuid)); + stmt->setUInt32(0, lowguid); PreparedQueryResult result = CharacterDatabase.Query(stmt); if (!result) @@ -1540,20 +1630,20 @@ public: level = fields[1].GetUInt8(); money = fields[2].GetUInt32(); accId = fields[3].GetUInt32(); - race = fields[4].GetUInt8(); - Class = fields[5].GetUInt8(); + raceid = fields[4].GetUInt8(); + classid = fields[5].GetUInt8(); mapId = fields[6].GetUInt16(); areaId = fields[7].GetUInt16(); + gender = fields[8].GetUInt8(); + uint32 health = fields[9].GetUInt32(); + uint32 playerFlags = fields[10].GetUInt32(); + if (!health || playerFlags & PLAYER_FLAGS_GHOST) + alive = "No"; + else + alive = "Yes"; } - std::string userName = handler->GetTrinityString(LANG_ERROR); - std::string eMail = handler->GetTrinityString(LANG_ERROR); - std::string muteReason = ""; - std::string muteBy = ""; - std::string lastIp = handler->GetTrinityString(LANG_ERROR); - uint32 security = 0; - std::string lastLogin = handler->GetTrinityString(LANG_ERROR); - + // Query the prepared statement for login data PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_PINFO); stmt->setInt32(0, int32(realmID)); stmt->setUInt32(1, accId); @@ -1565,23 +1655,18 @@ public: userName = fields[0].GetString(); security = fields[1].GetUInt8(); eMail = fields[2].GetString(); - muteTime = fields[5].GetUInt64(); - muteReason = fields[6].GetString(); - muteBy = fields[7].GetString(); - - if (eMail.empty()) - eMail = "-"; + // Only fetch these fields if commander has sufficient rights AND is online (prevent cheating) + /// @TODO: Add RBAC for "Can query ip and login data" if (!handler->GetSession() || handler->GetSession()->GetSecurity() >= AccountTypes(security)) { lastIp = fields[3].GetString(); lastLogin = fields[4].GetString(); uint32 ip = inet_addr(lastIp.c_str()); -#if TRINITY_ENDIAN == BIGENDIAN EndianConvertReverse(ip); -#endif + // If ip2nation table is populated, it displays the country PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_IP2NATION_COUNTRY); stmt->setUInt32(0, ip); if (PreparedQueryResult result2 = LoginDatabase.Query(stmt)) @@ -1592,27 +1677,26 @@ public: lastIp.append(")"); } } - else - { - lastIp = "-"; - lastLogin = "-"; - } + muteTime = fields[5].GetUInt64(); + muteReason = fields[6].GetString(); + muteBy = fields[7].GetString(); + failedLogins = fields[8].GetUInt32(); + locked = fields[9].GetUInt8(); + OS = fields[10].GetString(); } + // Creates a chat link to the character. Returns nameLink std::string nameLink = handler->playerLink(targetName); - handler->PSendSysMessage(LANG_PINFO_ACCOUNT, (target ? "" : handler->GetTrinityString(LANG_OFFLINE)), nameLink.c_str(), GUID_LOPART(targetGuid), userName.c_str(), accId, eMail.c_str(), security, lastIp.c_str(), lastLogin.c_str(), latency); - - std::string bannedby = "unknown"; - std::string banreason = ""; - - stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_PINFO_BANS); - stmt->setUInt32(0, accId); - PreparedQueryResult result2 = LoginDatabase.Query(stmt); + // Returns banType, banTime, bannedBy, banreason + PreparedStatement* stmt2 = LoginDatabase.GetPreparedStatement(LOGIN_SEL_PINFO_BANS); + stmt2->setUInt32(0, accId); + PreparedQueryResult result2 = LoginDatabase.Query(stmt2); if (!result2) { + banType = "Character"; stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PINFO_BANS); - stmt->setUInt32(0, GUID_LOPART(targetGuid)); + stmt->setUInt32(0, lowguid); result2 = CharacterDatabase.Query(stmt); } @@ -1620,49 +1704,19 @@ public: { Field* fields = result2->Fetch(); banTime = int64(fields[1].GetUInt64() ? 0 : fields[0].GetUInt32()); - bannedby = fields[2].GetString(); - banreason = fields[3].GetString(); + bannedBy = fields[2].GetString(); + banReason = fields[3].GetString(); } - if (muteTime > 0) - handler->PSendSysMessage(LANG_PINFO_MUTE, secsToTimeString(muteTime - time(NULL), true).c_str(), muteBy.c_str(), muteReason.c_str()); - - if (banTime >= 0) - handler->PSendSysMessage(LANG_PINFO_BAN, banTime > 0 ? secsToTimeString(banTime - time(NULL), true).c_str() : "permanently", bannedby.c_str(), banreason.c_str()); + // Can be used to query data from World database + stmt2 = WorldDatabase.GetPreparedStatement(WORLD_SEL_REQ_XP); + stmt2->setUInt8(0, level); + PreparedQueryResult result3 = WorldDatabase.Query(stmt2); - std::string raceStr, ClassStr; - switch (race) + if (result3) { - case RACE_HUMAN: - raceStr = "Human"; - break; - case RACE_ORC: - raceStr = "Orc"; - break; - case RACE_DWARF: - raceStr = "Dwarf"; - break; - case RACE_NIGHTELF: - raceStr = "Night Elf"; - break; - case RACE_UNDEAD_PLAYER: - raceStr = "Undead"; - break; - case RACE_TAUREN: - raceStr = "Tauren"; - break; - case RACE_GNOME: - raceStr = "Gnome"; - break; - case RACE_TROLL: - raceStr = "Troll"; - break; - case RACE_BLOODELF: - raceStr = "Blood Elf"; - break; - case RACE_DRAENEI: - raceStr = "Draenei"; - break; + Field* fields = result3->Fetch(); + xptotal = fields[0].GetUInt32(); case RACE_GOBLIN: raceStr = "Goblin"; break; @@ -1671,52 +1725,68 @@ public: break; } - switch (Class) + // Can be used to query data from Characters database + stmt2 = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PINFO_XP); + stmt2->setUInt32(0, lowguid); + PreparedQueryResult result4 = CharacterDatabase.Query(stmt2); + + if (result4) { - case CLASS_WARRIOR: - ClassStr = "Warrior"; - break; - case CLASS_PALADIN: - ClassStr = "Paladin"; - break; - case CLASS_HUNTER: - ClassStr = "Hunter"; - break; - case CLASS_ROGUE: - ClassStr = "Rogue"; - break; - case CLASS_PRIEST: - ClassStr = "Priest"; - break; - case CLASS_DEATH_KNIGHT: - ClassStr = "Death Knight"; - break; - case CLASS_SHAMAN: - ClassStr = "Shaman"; - break; - case CLASS_MAGE: - ClassStr = "Mage"; - break; - case CLASS_WARLOCK: - ClassStr = "Warlock"; - break; - case CLASS_DRUID: - ClassStr = "Druid"; - break; + Field* fields = result4->Fetch(); + xp = fields[0].GetUInt32(); } - std::string timeStr = secsToTimeString(totalPlayerTime, true, true); - uint32 gold = money /GOLD; - uint32 silv = (money % GOLD) / SILVER; - uint32 copp = (money % GOLD) % SILVER; - handler->PSendSysMessage(LANG_PINFO_LEVEL, raceStr.c_str(), ClassStr.c_str(), timeStr.c_str(), level, gold, silv, copp); + // Initiate output + // Output I. LANG_PINFO_PLAYER + handler->PSendSysMessage(LANG_PINFO_PLAYER, target ? "" : handler->GetTrinityString(LANG_OFFLINE), nameLink.c_str(), lowguid); - // Add map, zone, subzone and phase to output - std::string areaName = "<unknown>"; - std::string zoneName = ""; + // Output II. LANG_PINFO_GM_ACTIVE + if (target && target->isGameMaster()) + handler->PSendSysMessage(LANG_PINFO_GM_ACTIVE); - MapEntry const* map = sMapStore.LookupEntry(mapId); + // Output III. LANG_PINFO_BANNED if ban exists and is applied + if (banTime >= 0) + handler->PSendSysMessage(LANG_PINFO_BANNED, banType.c_str(), banTime > 0 ? secsToTimeString(banTime - time(NULL), true).c_str() : "permanently", banReason.c_str(), bannedBy.c_str()); + + // Output IV. LANG_PINFO_MUTED if mute is applied + if (muteTime > 0) + handler->PSendSysMessage(LANG_PINFO_MUTED, secsToTimeString(muteTime - time(NULL), true).c_str(), muteReason.c_str(), muteBy.c_str()); + + // Output V. LANG_PINFO_ACC_ACCOUNT + handler->PSendSysMessage(LANG_PINFO_ACC_ACCOUNT, userName.c_str(), accId, security); + + // 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 IX. LANG_PINFO_ACC_IP + handler->PSendSysMessage(LANG_PINFO_ACC_IP, lastIp.c_str(), locked ? "Yes" : "No"); + + // Output X. LANG_PINFO_CHR_LEVEL + handler->PSendSysMessage(LANG_PINFO_CHR_LEVEL, level, xp, xptotal, (xptotal - xp)); + + // Output XI. LANG_PINFO_CHR_RACE + raceStr = GetRaceName(raceid, locale); + classStr = GetClassName(classid, locale); + handler->PSendSysMessage(LANG_PINFO_CHR_RACE, (gender == 0 ? handler->GetTrinityString(LANG_CHARACTER_GENDER_MALE) : handler->GetTrinityString(LANG_CHARACTER_GENDER_FEMALE)), raceStr.c_str(), classStr.c_str()); + + // Output XII. LANG_PINFO_CHR_ALIVE + handler->PSendSysMessage(LANG_PINFO_CHR_ALIVE, alive.c_str()); + + // Output XIII. LANG_PINFO_CHR_PHASE if player is not in GM mode (GM is in every phase) + if (target && !target->isGameMaster()) // IsInWorld() returns false on loadingscreen, so it's more + handler->PSendSysMessage(LANG_PINFO_CHR_PHASE, phase); // precise than just target (safer ?). + // However, as we usually just require a target here, we use target instead. + // Output XIV. LANG_PINFO_CHR_MONEY + uint32 gold = money / GOLD; + uint32 silv = (money % GOLD) / SILVER; + uint32 copp = (money % GOLD) % SILVER; + handler->PSendSysMessage(LANG_PINFO_CHR_MONEY, gold, silv, copp); + + // Position data + MapEntry const* map = sMapStore.LookupEntry(mapId); AreaTableEntry const* area = GetAreaEntryByAreaID(areaId); if (area) { @@ -1728,30 +1798,55 @@ public: } if (target) - { - if (!zoneName.empty()) - handler->PSendSysMessage(LANG_PINFO_MAP_ONLINE, map->name, zoneName.c_str(), areaName.c_str(), phase); - else - handler->PSendSysMessage(LANG_PINFO_MAP_ONLINE, map->name, areaName.c_str(), "<unknown>", phase); + handler->PSendSysMessage(LANG_PINFO_CHR_MAP, map->name[locale], (!zoneName.empty() ? zoneName.c_str() : "<Unknown>"), (!areaName.empty() ? areaName.c_str() : "<Unknown>")); + + // Guild Data - an own query, because it may not happen. + PreparedStatement* stmt3 = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GUILD_MEMBER_EXTENDED); + stmt3->setUInt32(0, lowguid); + PreparedQueryResult result5 = CharacterDatabase.Query(stmt3); + if (result5) + { + Field* fields = result5->Fetch(); + uint32 guildId = fields[0].GetUInt32(); + std::string guildName = fields[1].GetString(); + std::string guildRank = fields[2].GetString(); + std::string note = fields[3].GetString(); + std::string officeNote = fields[4].GetString(); + + // Output XVII. - XX. + handler->PSendSysMessage(LANG_PINFO_CHR_GUILD, guildName.c_str(), guildId); + handler->PSendSysMessage(LANG_PINFO_CHR_GUILD_RANK, guildRank.c_str()); + // Only output XIX and XX if they are not empty + if (!note.empty()) + handler->PSendSysMessage(LANG_PINFO_CHR_GUILD_NOTE, note.c_str()); + if (!officeNote.empty()) + handler->PSendSysMessage(LANG_PINFO_CHR_GUILD_ONOTE, officeNote.c_str()); } - else - handler->PSendSysMessage(LANG_PINFO_MAP_OFFLINE, map->name, areaName.c_str()); - stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GUILD_MEMBER_EXTENDED); - stmt->setUInt32(0, GUID_LOPART(targetGuid)); + // Output XXI. LANG_PINFO_CHR_PLAYEDTIME + handler->PSendSysMessage(LANG_PINFO_CHR_PLAYEDTIME, (secsToTimeString(totalPlayerTime, true, true)).c_str()); - result = CharacterDatabase.Query(stmt); - if (result) + // Mail Data - an own query, because it may or may not be useful. + // SQL: "SELECT SUM(CASE WHEN (checked & 1) THEN 1 ELSE 0 END) AS 'readmail', COUNT(*) AS 'totalmail' FROM mail WHERE `receiver` = ?" + stmt3 = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PINFO_MAILS); + stmt3->setUInt32(0, lowguid); + PreparedQueryResult result6 = CharacterDatabase.Query(stmt3); + if (result6) { - Field* fields = result->Fetch(); + // Define the variables, so the compiler knows they exist + uint32 rmailint = 0; - uint32 guildId = fields[0].GetUInt32(); - std::string guildName = fields[1].GetString(); - std::string guildRank = fields[2].GetString(); - std::string note = fields[3].GetString(); - std::string officeNote = fields[4].GetString(); + // Fetch the fields - readmail is a SUM(x) and given out as char! Thus... + Field* fields = result6->Fetch(); + std::string readmail = fields[0].GetString(); + uint64 totalmail = fields[1].GetUInt64(); - handler->PSendSysMessage(LANG_PINFO_GUILD_INFO, guildName.c_str(), guildId, guildRank.c_str(), note.c_str(), officeNote.c_str()); + // ... 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 mails is given + if (totalmail >= 1) + handler->PSendSysMessage(LANG_PINFO_CHR_MAILS, rmailint, totalmail); } return true; @@ -1789,6 +1884,7 @@ public: return true; } + // mute player for some times static bool HandleMuteCommand(ChatHandler* handler, char const* args) { diff --git a/src/server/scripts/Commands/cs_server.cpp b/src/server/scripts/Commands/cs_server.cpp index 309380a9cbb..11b4ebf33ae 100644 --- a/src/server/scripts/Commands/cs_server.cpp +++ b/src/server/scripts/Commands/cs_server.cpp @@ -338,7 +338,8 @@ public: } else sWorld->ShutdownServ(time, SHUTDOWN_MASK_IDLE, SHUTDOWN_EXIT_CODE); - return true; + + return true; } // Exit the realm diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kalecgos.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kalecgos.cpp index 9e312ef8f94..b6b701c513d 100644 --- a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kalecgos.cpp +++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kalecgos.cpp @@ -716,27 +716,27 @@ public: if (CheckTimer <= diff) { Creature* Kalec = Unit::GetCreature(*me, KalecGUID); - if (!Kalec || (Kalec && !Kalec->isAlive())) + if (!Kalec || !Kalec->isAlive()) { if (Creature* Kalecgos = Unit::GetCreature(*me, KalecgosGUID)) Kalecgos->AI()->EnterEvadeMode(); - return; + return; } + if (HealthBelowPct(10) && !isEnraged) { if (Creature* Kalecgos = Unit::GetCreature(*me, KalecgosGUID)) Kalecgos->AI()->DoAction(DO_ENRAGE); DoAction(DO_ENRAGE); } + Creature* Kalecgos = Unit::GetCreature(*me, KalecgosGUID); - if (Kalecgos) + if (Kalecgos && !Kalecgos->isInCombat()) { - if (!Kalecgos->isInCombat()) - { - me->AI()->EnterEvadeMode(); - return; - } + me->AI()->EnterEvadeMode(); + return; } + if (!isBanished && HealthBelowPct(1)) { if (Kalecgos) @@ -746,8 +746,7 @@ public: me->DealDamage(me, me->GetHealth()); return; } - else - DoAction(DO_BANISH); + DoAction(DO_BANISH); } else { diff --git a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/boss_falric.cpp b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/boss_falric.cpp index 58dc74d0f0a..9d266c77b77 100644 --- a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/boss_falric.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/boss_falric.cpp @@ -19,7 +19,7 @@ #include "ScriptedCreature.h" #include "halls_of_reflection.h" -enum Yells +enum Texts { SAY_AGGRO = 0, SAY_SLAY = 1, @@ -68,14 +68,14 @@ public: uiHopelessnessCount = 0; if (instance) - instance->SetData(DATA_FALRIC_EVENT, NOT_STARTED); + instance->SetBossState(DATA_FALRIC_EVENT, NOT_STARTED); } void EnterCombat(Unit* /*who*/) { Talk(SAY_AGGRO); if (instance) - instance->SetData(DATA_FALRIC_EVENT, IN_PROGRESS); + instance->SetBossState(DATA_FALRIC_EVENT, IN_PROGRESS); events.ScheduleEvent(EVENT_QUIVERING_STRIKE, 23000); events.ScheduleEvent(EVENT_IMPENDING_DESPAIR, 9000); @@ -87,7 +87,7 @@ public: Talk(SAY_DEATH); if (instance) - instance->SetData(DATA_FALRIC_EVENT, DONE); + instance->SetBossState(DATA_FALRIC_EVENT, DONE); } void KilledUnit(Unit* /*victim*/) diff --git a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/boss_marwyn.cpp b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/boss_marwyn.cpp index 08d5cf70ee1..e82f0d48ebd 100644 --- a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/boss_marwyn.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/boss_marwyn.cpp @@ -19,7 +19,7 @@ #include "ScriptedCreature.h" #include "halls_of_reflection.h" -enum Yells +enum Texts { SAY_AGGRO = 0, SAY_SLAY = 1, @@ -63,14 +63,14 @@ public: boss_horAI::Reset(); if (instance) - instance->SetData(DATA_MARWYN_EVENT, NOT_STARTED); + instance->SetBossState(DATA_MARWYN_EVENT, NOT_STARTED); } void EnterCombat(Unit* /*who*/) { Talk(SAY_AGGRO); if (instance) - instance->SetData(DATA_MARWYN_EVENT, IN_PROGRESS); + instance->SetBossState(DATA_MARWYN_EVENT, IN_PROGRESS); events.ScheduleEvent(EVENT_OBLITERATE, 30000); /// @todo Check timer events.ScheduleEvent(EVENT_WELL_OF_CORRUPTION, 13000); @@ -83,7 +83,7 @@ public: Talk(SAY_DEATH); if (instance) - instance->SetData(DATA_MARWYN_EVENT, DONE); + instance->SetBossState(DATA_MARWYN_EVENT, DONE); } void KilledUnit(Unit* /*victim*/) 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 b140801d8f1..a64f2cf5467 100644 --- a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp @@ -18,10 +18,10 @@ #include "ScriptMgr.h" #include "ScriptedCreature.h" #include "ScriptedGossip.h" -#include "halls_of_reflection.h" #include "Player.h" +#include "halls_of_reflection.h" -enum Yells +enum Text { SAY_JAINA_INTRO_1 = 0, SAY_JAINA_INTRO_2 = 1, @@ -66,17 +66,19 @@ enum Yells SAY_LK_INTRO_1 = 0, SAY_LK_INTRO_2 = 1, SAY_LK_INTRO_3 = 2, + SAY_LK_JAINA_INTRO_END = 3, + SAY_LK_SYLVANAS_INTRO_END = 4, SAY_FALRIC_INTRO_1 = 5, SAY_FALRIC_INTRO_2 = 6, - SAY_MARWYN_INTRO_1 = 4 + SAY_MARWYN_INTRO_1 = 4, }; enum Events { - EVENT_NONE, - + EVENT_WALK_INTRO1 = 1, + EVENT_WALK_INTRO2, EVENT_START_INTRO, EVENT_SKIP_INTRO, @@ -125,8 +127,13 @@ enum Events EVENT_INTRO_LK_7, EVENT_INTRO_LK_8, EVENT_INTRO_LK_9, + EVENT_INTRO_LK_10, + EVENT_INTRO_LK_11, EVENT_INTRO_END, + + EVENT_OPEN_FROSTWORN_DOOR, + EVENT_CLOSE_FROSTWORN_DOOR, }; enum eEnum @@ -140,6 +147,17 @@ enum eEnum QUEST_WRATH_OF_THE_LICH_KING_H2 = 24802, }; +enum Spells +{ + SPELL_CAST_VISUAL = 65633, // Jaina/Sylavana + SPELL_BOSS_SPAWN_AURA = 72712, // Falric and Marwyn + SPELL_UTHER_DESPAWN = 70693, + SPELL_TAKE_FROSTMOURNE = 72729, + SPELL_FROSTMOURNE_DESPAWN = 72726, + SPELL_FROSTMOURNE_VISUAL = 73220, + SPELL_FROSTMOURNE_SOUNDS = 70667, +}; + const Position HallsofReflectionLocs[]= { {5283.234863f, 1990.946777f, 707.695679f, 0.929097f}, // 2 Loralen Follows @@ -147,7 +165,7 @@ const Position HallsofReflectionLocs[]= {5401.866699f, 2110.837402f, 707.695251f, 0.800610f}, // 10 Loralen follows }; -const Position SpawnPos = {5262.540527f, 1949.693726f, 707.695007f, 0.808736f}; // Jaina/Sylvanas Beginning Position +const Position IntroPos = {5265.89f, 1952.98f, 707.6978f, 0.0f}; // Jaina/Sylvanas Intro Start Position const Position MoveThronePos = {5306.952148f, 1998.499023f, 709.341431f, 1.277278f}; // Jaina/Sylvanas walks to throne const Position UtherSpawnPos = {5308.310059f, 2003.857178f, 709.341431f, 4.650315f}; const Position LichKingSpawnPos = {5362.917480f, 2062.307129f, 707.695374f, 3.945812f}; @@ -156,58 +174,10 @@ const Position LichKingMoveAwayPos = {5400.069824f, 2102.7131689f, 707.69525f, class npc_jaina_or_sylvanas_hor : public CreatureScript { -private: - bool m_isSylvana; - -public: - npc_jaina_or_sylvanas_hor(bool isSylvana, const char* name) : CreatureScript(name), m_isSylvana(isSylvana) { } - - bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) - { - player->PlayerTalkClass->ClearMenus(); - switch (action) - { - case GOSSIP_ACTION_INFO_DEF+1: - player->CLOSE_GOSSIP_MENU(); - if (creature->AI()) - creature->AI()->DoAction(ACTION_START_INTRO); - creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - break; - case GOSSIP_ACTION_INFO_DEF+2: - player->CLOSE_GOSSIP_MENU(); - if (creature->AI()) - creature->AI()->DoAction(ACTION_SKIP_INTRO); - creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - break; - } + public: + npc_jaina_or_sylvanas_hor() : CreatureScript("npc_jaina_or_sylvanas_hor") { } - return true; - } - - bool OnGossipHello(Player* player, Creature* creature) - { - if (creature->isQuestGiver()) - player->PrepareQuestMenu(creature->GetGUID()); - - QuestStatus status = player->GetQuestStatus(m_isSylvana ? QUEST_DELIVRANCE_FROM_THE_PIT_H2 : QUEST_DELIVRANCE_FROM_THE_PIT_A2); - if (status == QUEST_STATUS_COMPLETE || status == QUEST_STATUS_REWARDED) - player->ADD_GOSSIP_ITEM( 0, "Can you remove the sword?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - // once last quest is completed, she offers this shortcut of the starting event - status = player->GetQuestStatus(m_isSylvana ? QUEST_WRATH_OF_THE_LICH_KING_H2 : QUEST_WRATH_OF_THE_LICH_KING_A2); - if (status == QUEST_STATUS_COMPLETE || status == QUEST_STATUS_REWARDED) - player->ADD_GOSSIP_ITEM( 0, "Dark Lady, I think I hear Arthas coming. Whatever you're going to do, do it quickly.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - - player->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE, creature->GetGUID()); - return true; - } - - CreatureAI* GetAI(Creature* creature) const - { - return new npc_jaina_or_sylvanas_horAI(creature); - } - - // AI of Part1: handle the intro till start of gauntlet event. + // AI of Part1 struct npc_jaina_or_sylvanas_horAI : public ScriptedAI { npc_jaina_or_sylvanas_horAI(Creature* creature) : ScriptedAI(creature) @@ -221,6 +191,24 @@ public: EventMap events; + void sGossipSelect(Player* player, uint32 /*sender*/, uint32 action) + { + player->PlayerTalkClass->ClearMenus(); + switch (action) + { + case 0: + player->CLOSE_GOSSIP_MENU(); + events.ScheduleEvent(EVENT_START_INTRO, 1000); + me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP|UNIT_NPC_FLAG_QUESTGIVER); + break; + case 1: + player->CLOSE_GOSSIP_MENU(); + events.ScheduleEvent(EVENT_SKIP_INTRO, 1000); + me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP|UNIT_NPC_FLAG_QUESTGIVER); + break; + } + } + void Reset() { events.Reset(); @@ -228,22 +216,9 @@ public: utherGUID = 0; lichkingGUID = 0; - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP|UNIT_NPC_FLAG_QUESTGIVER); me->SetStandState(UNIT_STAND_STATE_STAND); - me->SetVisible(true); - } - - void DoAction(int32 actionId) - { - switch (actionId) - { - case ACTION_START_INTRO: - events.ScheduleEvent(EVENT_START_INTRO, 0); - break; - case ACTION_SKIP_INTRO: - events.ScheduleEvent(EVENT_SKIP_INTRO, 0); - break; - } + events.ScheduleEvent(EVENT_WALK_INTRO1, 3000); } void UpdateAI(uint32 diff) @@ -251,6 +226,26 @@ public: events.Update(diff); switch (events.ExecuteEvent()) { + case EVENT_WALK_INTRO1: + me->GetMotionMaster()->MovePoint(0, IntroPos); + if (instance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE) + { + Talk(SAY_JAINA_INTRO_1); + events.ScheduleEvent(EVENT_WALK_INTRO2, 7000); + } + else + { + Talk(SAY_SYLVANAS_INTRO_1); + events.ScheduleEvent(EVENT_WALK_INTRO2, 9000); + } + break; + case EVENT_WALK_INTRO2: + if (instance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE) + Talk(SAY_JAINA_INTRO_2); + else + Talk(SAY_SYLVANAS_INTRO_2); + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP|UNIT_NPC_FLAG_QUESTGIVER); + break; case EVENT_START_INTRO: me->GetMotionMaster()->MovePoint(0, MoveThronePos); // Begining of intro is differents between fActions as the speech sequence and timers are differents. @@ -259,27 +254,25 @@ public: else events.ScheduleEvent(EVENT_INTRO_H2_1, 0); break; - - // A2 Intro Events + // A2 Intro Events case EVENT_INTRO_A2_1: Talk(SAY_JAINA_INTRO_3); - events.ScheduleEvent(EVENT_INTRO_A2_2, 5000); + events.ScheduleEvent(EVENT_INTRO_A2_2, 7000); break; case EVENT_INTRO_A2_2: Talk(SAY_JAINA_INTRO_4); events.ScheduleEvent(EVENT_INTRO_A2_3, 10000); break; case EVENT_INTRO_A2_3: - /// @todo she's doing some kind of spell casting emote + me->CastSpell(me, SPELL_CAST_VISUAL, false); + me->CastSpell(me, SPELL_FROSTMOURNE_SOUNDS, true); instance->HandleGameObject(instance->GetData64(DATA_FROSTMOURNE), true); events.ScheduleEvent(EVENT_INTRO_A2_4, 10000); break; case EVENT_INTRO_A2_4: - // spawn UTHER during speach 2 if (Creature* uther = me->SummonCreature(NPC_UTHER, UtherSpawnPos, TEMPSUMMON_MANUAL_DESPAWN)) { uther->GetMotionMaster()->MoveIdle(); - uther->SetReactState(REACT_PASSIVE); // be sure he will not aggro arthas utherGUID = uther->GetGUID(); } events.ScheduleEvent(EVENT_INTRO_A2_5, 2000); @@ -291,57 +284,57 @@ public: break; case EVENT_INTRO_A2_6: Talk(SAY_JAINA_INTRO_5); - events.ScheduleEvent(EVENT_INTRO_A2_7, 6000); + events.ScheduleEvent(EVENT_INTRO_A2_7, 7000); break; case EVENT_INTRO_A2_7: if (Creature* uther = me->GetCreature(*me, utherGUID)) uther->AI()->Talk(SAY_UTHER_INTRO_A2_2); - events.ScheduleEvent(EVENT_INTRO_A2_8, 6500); + events.ScheduleEvent(EVENT_INTRO_A2_8, 7000); break; case EVENT_INTRO_A2_8: Talk(SAY_JAINA_INTRO_6); - events.ScheduleEvent(EVENT_INTRO_A2_9, 2000); + events.ScheduleEvent(EVENT_INTRO_A2_9, 1200); break; case EVENT_INTRO_A2_9: if (Creature* uther = me->GetCreature(*me, utherGUID)) uther->AI()->Talk(SAY_UTHER_INTRO_A2_3); - events.ScheduleEvent(EVENT_INTRO_A2_10, 9000); + events.ScheduleEvent(EVENT_INTRO_A2_10, 11000); break; case EVENT_INTRO_A2_10: Talk(SAY_JAINA_INTRO_7); - events.ScheduleEvent(EVENT_INTRO_A2_11, 5000); + events.ScheduleEvent(EVENT_INTRO_A2_11, 6000); break; case EVENT_INTRO_A2_11: if (Creature* uther = me->GetCreature(*me, utherGUID)) uther->AI()->Talk(SAY_UTHER_INTRO_A2_4); - events.ScheduleEvent(EVENT_INTRO_A2_12, 11000); + events.ScheduleEvent(EVENT_INTRO_A2_12, 12000); break; case EVENT_INTRO_A2_12: Talk(SAY_JAINA_INTRO_8); - events.ScheduleEvent(EVENT_INTRO_A2_13, 4000); + events.ScheduleEvent(EVENT_INTRO_A2_13, 6000); break; case EVENT_INTRO_A2_13: if (Creature* uther = me->GetCreature(*me, utherGUID)) uther->AI()->Talk(SAY_UTHER_INTRO_A2_5); - events.ScheduleEvent(EVENT_INTRO_A2_14, 12500); + events.ScheduleEvent(EVENT_INTRO_A2_14, 13000); break; case EVENT_INTRO_A2_14: Talk(SAY_JAINA_INTRO_9); - events.ScheduleEvent(EVENT_INTRO_A2_15, 10000); + events.ScheduleEvent(EVENT_INTRO_A2_15, 12000); break; case EVENT_INTRO_A2_15: if (Creature* uther = me->GetCreature(*me, utherGUID)) uther->AI()->Talk(SAY_UTHER_INTRO_A2_6); - events.ScheduleEvent(EVENT_INTRO_A2_16, 22000); + events.ScheduleEvent(EVENT_INTRO_A2_16, 25000); break; case EVENT_INTRO_A2_16: if (Creature* uther = me->GetCreature(*me, utherGUID)) uther->AI()->Talk(SAY_UTHER_INTRO_A2_7); - events.ScheduleEvent(EVENT_INTRO_A2_17, 4000); + events.ScheduleEvent(EVENT_INTRO_A2_17, 6000); break; case EVENT_INTRO_A2_17: Talk(SAY_JAINA_INTRO_10); - events.ScheduleEvent(EVENT_INTRO_A2_18, 2000); + events.ScheduleEvent(EVENT_INTRO_A2_18, 5000); break; case EVENT_INTRO_A2_18: if (Creature* uther = me->GetCreature(*me, utherGUID)) @@ -349,14 +342,13 @@ public: uther->HandleEmoteCommand(EMOTE_ONESHOT_NO); uther->AI()->Talk(SAY_UTHER_INTRO_A2_8); } - events.ScheduleEvent(EVENT_INTRO_A2_19, 11000); + events.ScheduleEvent(EVENT_INTRO_A2_19, 12000); break; case EVENT_INTRO_A2_19: Talk(SAY_JAINA_INTRO_11); - events.ScheduleEvent(EVENT_INTRO_LK_1, 2000); + events.ScheduleEvent(EVENT_INTRO_LK_1, 3000); break; - - // H2 Intro Events + // H2 Intro Events case EVENT_INTRO_H2_1: Talk(SAY_SYLVANAS_INTRO_1); events.ScheduleEvent(EVENT_INTRO_H2_2, 8000); @@ -367,7 +359,9 @@ public: break; case EVENT_INTRO_H2_3: Talk(SAY_SYLVANAS_INTRO_3); - /// @todo she's doing some kind of spell casting emote + me->CastSpell(me, SPELL_CAST_VISUAL, false); + me->CastSpell(me, SPELL_FROSTMOURNE_SOUNDS, true); + instance->HandleGameObject(instance->GetData64(DATA_FROSTMOURNE), true); events.ScheduleEvent(EVENT_INTRO_H2_4, 6000); break; case EVENT_INTRO_H2_4: @@ -375,7 +369,6 @@ public: if (Creature* uther = me->SummonCreature(NPC_UTHER, UtherSpawnPos, TEMPSUMMON_MANUAL_DESPAWN)) { uther->GetMotionMaster()->MoveIdle(); - uther->SetReactState(REACT_PASSIVE); // be sure he will not aggro arthas utherGUID = uther->GetGUID(); } events.ScheduleEvent(EVENT_INTRO_H2_5, 2000); @@ -433,126 +426,159 @@ public: Talk(SAY_SYLVANAS_INTRO_8); events.ScheduleEvent(EVENT_INTRO_LK_1, 2000); break; - - // Remaining Intro Events common for both faction + // Remaining Intro Events common for both faction case EVENT_INTRO_LK_1: // Spawn LK in front of door, and make him move to the sword. - if (Creature* lichking = me->SummonCreature(NPC_LICH_KING_EVENT, LichKingSpawnPos, TEMPSUMMON_MANUAL_DESPAWN)) + if (Creature* lichking = me->SummonCreature(NPC_LICH_KING_PART1, LichKingSpawnPos, TEMPSUMMON_MANUAL_DESPAWN)) { + lichking->SetUnitMovementFlags(MOVEMENTFLAG_WALKING); lichking->GetMotionMaster()->MovePoint(0, LichKingMoveThronePos); - lichking->SetReactState(REACT_PASSIVE); + //lichking->SetReactState(REACT_PASSIVE); lichkingGUID = lichking->GetGUID(); + events.ScheduleEvent(EVENT_OPEN_FROSTWORN_DOOR, 0); + events.ScheduleEvent(EVENT_CLOSE_FROSTWORN_DOOR, 4000); } - if (Creature* uther = me->GetCreature(*me, utherGUID)) { + uther->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_COWER); if (instance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE) uther->AI()->Talk(SAY_UTHER_INTRO_A2_9); else uther->AI()->Talk(SAY_UTHER_INTRO_H2_7); } - - events.ScheduleEvent(EVENT_INTRO_LK_2, 11000); + events.ScheduleEvent(EVENT_INTRO_LK_2, 10000); break; - case EVENT_INTRO_LK_2: - if (Creature* lichking = me->GetCreature(*me, lichkingGUID)) - lichking->AI()->Talk(SAY_LK_INTRO_1); - events.ScheduleEvent(EVENT_INTRO_LK_3, 2000); - break; - + if (Creature* lichking = me->GetCreature(*me, lichkingGUID)) + lichking->AI()->Talk(SAY_LK_INTRO_1); + events.ScheduleEvent(EVENT_INTRO_LK_3, 1000); + break; case EVENT_INTRO_LK_3: - // The Lich King banishes Uther to the abyss. - if (Creature* uther = me->GetCreature(*me, utherGUID)) - { - uther->DisappearAndDie(); - utherGUID = 0; - } - - // He steps forward and removes the runeblade from the heap of skulls. - - events.ScheduleEvent(EVENT_INTRO_LK_4, 4000); - break; - + // The Lich King banishes Uther to the abyss. + if (Creature* uther = me->GetCreature(*me, utherGUID)) + { + uther->CastSpell(uther, SPELL_UTHER_DESPAWN, true); + uther->DespawnOrUnsummon(5000); + utherGUID = 0; + } + events.ScheduleEvent(EVENT_INTRO_LK_4, 9000); + break; case EVENT_INTRO_LK_4: - if (Creature* lichking = me->GetCreature(*me, lichkingGUID)) - lichking->AI()->Talk(SAY_LK_INTRO_2); - events.ScheduleEvent(EVENT_INTRO_LK_5, 10000); + // He steps forward and removes the runeblade from the heap of skulls. + if (Creature* lichking = me->GetCreature(*me, lichkingGUID)) + { + if (GameObject* frostmourne = ObjectAccessor::GetGameObject(*me, instance->GetData64(DATA_FROSTMOURNE))) + frostmourne->SetPhaseMask(2, true); + lichking->CastSpell(lichking, SPELL_TAKE_FROSTMOURNE, true); + lichking->CastSpell(lichking, SPELL_FROSTMOURNE_VISUAL, true); + } + events.ScheduleEvent(EVENT_INTRO_LK_5, 8000); break; - case EVENT_INTRO_LK_5: + if (Creature* lichking = me->GetCreature(*me, lichkingGUID)) + lichking->AI()->Talk(SAY_LK_INTRO_2); + events.ScheduleEvent(EVENT_INTRO_LK_6, 8000); + break; + case EVENT_INTRO_LK_6: // summon Falric and Marwyn. then go back to the door - if (Creature* pFalric = me->GetCreature(*me, instance->GetData64(DATA_FALRIC))) - pFalric->SetVisible(true); - if (Creature* pMarwyn = me->GetCreature(*me, instance->GetData64(DATA_MARWYN))) - pMarwyn->SetVisible(true); - + if (Creature* falric = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_FALRIC_EVENT))) + { + falric->CastSpell(falric, SPELL_BOSS_SPAWN_AURA, true); + falric->SetVisible(true); + } + if (Creature* marwyn = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_MARWYN_EVENT))) + { + marwyn->CastSpell(marwyn, SPELL_BOSS_SPAWN_AURA, true); + marwyn->SetVisible(true); + } if (Creature* lichking = me->GetCreature(*me, lichkingGUID)) { - lichking->GetMotionMaster()->MovePoint(0, LichKingSpawnPos); lichking->AI()->Talk(SAY_LK_INTRO_3); + lichking->SetUnitMovementFlags(MOVEMENTFLAG_WALKING); + lichking->GetMotionMaster()->MovePoint(0, LichKingMoveAwayPos); } - - events.ScheduleEvent(EVENT_INTRO_LK_6, 8000); - break; - - case EVENT_INTRO_LK_6: - if (Creature* falric = me->GetCreature(*me, instance->GetData64(DATA_FALRIC))) - falric->AI()->Talk(SAY_FALRIC_INTRO_1); - - events.ScheduleEvent(EVENT_INTRO_LK_7, 2000); + events.ScheduleEvent(EVENT_INTRO_LK_7, 10000); + events.ScheduleEvent(EVENT_OPEN_FROSTWORN_DOOR, 5000); break; - case EVENT_INTRO_LK_7: - if (Creature* marwyn = me->GetCreature(*me, instance->GetData64(DATA_MARWYN))) + if (Creature* marwyn = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_MARWYN_EVENT))) marwyn->AI()->Talk(SAY_MARWYN_INTRO_1); - - events.ScheduleEvent(EVENT_INTRO_LK_8, 2000); + events.ScheduleEvent(EVENT_INTRO_LK_8, 1000); break; - case EVENT_INTRO_LK_8: - if (Creature* falric = me->GetCreature(*me, instance->GetData64(DATA_FALRIC))) - falric->AI()->Talk(SAY_FALRIC_INTRO_2); - + if (Creature* falric = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_FALRIC_EVENT))) + falric->AI()->Talk(SAY_FALRIC_INTRO_1); events.ScheduleEvent(EVENT_INTRO_LK_9, 5000); break; - case EVENT_INTRO_LK_9: + if (Creature* falric = ObjectAccessor::GetCreature(*me, instance->GetData64(DATA_FALRIC_EVENT))) + falric->AI()->Talk(SAY_FALRIC_INTRO_2); + events.ScheduleEvent(EVENT_INTRO_LK_10, 7000); + break; + case EVENT_INTRO_LK_10: if (instance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE) Talk(SAY_JAINA_INTRO_END); else Talk(SAY_SYLVANAS_INTRO_END); - - me->GetMotionMaster()->MovePoint(0, LichKingSpawnPos); + me->GetMotionMaster()->MovePoint(0, LichKingMoveAwayPos); /// @todo Loralen/Koreln shall run also - events.ScheduleEvent(EVENT_INTRO_END, 10000); + events.ScheduleEvent(EVENT_INTRO_LK_11, 5000); + break; + case EVENT_INTRO_LK_11: + if (Creature* lichking = me->GetCreature(*me, lichkingGUID)) + { + if (instance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE) + lichking->AI()->Talk(SAY_LK_JAINA_INTRO_END); + else + lichking->AI()->Talk(SAY_LK_SYLVANAS_INTRO_END); + } + events.ScheduleEvent(EVENT_INTRO_END, 5000); break; - case EVENT_INTRO_END: if (instance) - instance->SetData(DATA_WAVE_COUNT, SPECIAL); // start first wave - + { + instance->SetData(DATA_INTRO_EVENT, DONE); + instance->ProcessEvent(0, EVENT_SPAWN_WAVES); + } // Loralen or Koreln disappearAndDie() - me->DisappearAndDie(); + if (Creature* lichking = me->GetCreature(*me, lichkingGUID)) + { + lichking->DespawnOrUnsummon(5000); + lichkingGUID = 0; + } + me->DespawnOrUnsummon(10000); + events.ScheduleEvent(EVENT_CLOSE_FROSTWORN_DOOR, 7000); break; - case EVENT_SKIP_INTRO: - /// @todo implement - - if (Creature* pFalric = me->GetCreature(*me, instance->GetData64(DATA_FALRIC))) - pFalric->SetVisible(true); - if (Creature* pMarwyn = me->GetCreature(*me, instance->GetData64(DATA_MARWYN))) - pMarwyn->SetVisible(true); - - me->GetMotionMaster()->MovePoint(0, LichKingSpawnPos); + me->GetMotionMaster()->MovePoint(0, MoveThronePos); /// @todo Loralen/Koreln shall run also - - events.ScheduleEvent(EVENT_INTRO_END, 15000); + if (Creature* lichking = me->SummonCreature(NPC_LICH_KING_PART1, LichKingSpawnPos, TEMPSUMMON_MANUAL_DESPAWN)) + { + lichking->SetUnitMovementFlags(MOVEMENTFLAG_WALKING); + lichking->GetMotionMaster()->MovePoint(0, LichKingMoveThronePos); + lichking->SetReactState(REACT_PASSIVE); + lichkingGUID = lichking->GetGUID(); + events.ScheduleEvent(EVENT_OPEN_FROSTWORN_DOOR, 0); + events.ScheduleEvent(EVENT_CLOSE_FROSTWORN_DOOR, 4000); + } + events.ScheduleEvent(EVENT_INTRO_LK_4, 15000); + break; + case EVENT_OPEN_FROSTWORN_DOOR: + if (GameObject* gate = ObjectAccessor::GetGameObject(*me, instance->GetData64(DATA_FROSTWORN_DOOR))) + instance->HandleGameObject(0 ,true, gate); + break; + case EVENT_CLOSE_FROSTWORN_DOOR: + if (GameObject* gate = ObjectAccessor::GetGameObject(*me, instance->GetData64(DATA_FROSTWORN_DOOR))) + instance->HandleGameObject(0 ,false, gate); break; } } }; + CreatureAI* GetAI(Creature* creature) const + { + return new npc_jaina_or_sylvanas_horAI(creature); + } }; enum TrashSpells @@ -626,27 +652,56 @@ enum TrashEvents EVENT_ICE_SHOT, }; -class npc_ghostly_priest : public CreatureScript +struct npc_gauntlet_trash : public ScriptedAI { -public: - npc_ghostly_priest() : CreatureScript("npc_ghostly_priest") { } + npc_gauntlet_trash(Creature* creature) : ScriptedAI(creature), + instance(creature->GetInstanceScript()) + { + } - CreatureAI* GetAI(Creature* creature) const + void Reset() { - return new npc_ghostly_priestAI(creature); + me->CastSpell(me, SPELL_WELL_OF_SOULS, true); + events.Reset(); } - struct npc_ghostly_priestAI: public ScriptedAI + void EnterEvadeMode() { - npc_ghostly_priestAI(Creature* creature) : ScriptedAI(creature) - { - } + if (instance->GetData(DATA_WAVE_COUNT) != NOT_STARTED) + instance->SetData(DATA_WAVE_COUNT, NOT_STARTED); + } - EventMap events; + void SetData(uint32 type, uint32 value) + { + if (type) + return; - void Reset() + InternalWaveId = value; + } + + uint32 GetData(uint32 type) const + { + if (type) + return 0; + + return InternalWaveId; + } + +protected: + EventMap events; + InstanceScript* instance; + uint32 InternalWaveId; +}; + +class npc_ghostly_priest : public CreatureScript +{ +public: + npc_ghostly_priest() : CreatureScript("npc_ghostly_priest") { } + + struct npc_ghostly_priestAI : public npc_gauntlet_trash + { + npc_ghostly_priestAI(Creature* creature) : npc_gauntlet_trash(creature) { - events.Reset(); } void EnterCombat(Unit* /*who*/) @@ -667,45 +722,46 @@ public: if (me->HasUnitState(UNIT_STATE_CASTING)) return; - while (uint32 eventId = events.ExecuteEvent()) + switch (events.ExecuteEvent()) { - switch (eventId) - { - case EVENT_SHADOW_WORD_PAIN: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM)) - DoCast(target, SPELL_SHADOW_WORD_PAIN); - events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, 8000); - return; - case EVENT_CIRCLE_OF_DESTRUCTION: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM)) - DoCast(target, SPELL_CIRCLE_OF_DESTRUCTION); - events.ScheduleEvent(EVENT_CIRCLE_OF_DESTRUCTION, 12000); - return; - case EVENT_COWER_IN_FEAR: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM)) - DoCast(target, SPELL_COWER_IN_FEAR); - events.ScheduleEvent(EVENT_COWER_IN_FEAR, 10000); - return; - case EVENT_DARK_MENDING: - // find an ally with missing HP - if (Unit* target = DoSelectLowestHpFriendly(40, DUNGEON_MODE(30000, 50000))) - { - DoCast(target, SPELL_DARK_MENDING); - events.ScheduleEvent(EVENT_DARK_MENDING, 20000); - } - else - { - // no friendly unit with missing hp. re-check in just 5 sec. - events.ScheduleEvent(EVENT_DARK_MENDING, 5000); - } - return; - } + case EVENT_SHADOW_WORD_PAIN: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(target, SPELL_SHADOW_WORD_PAIN); + events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, 8000); + break; + case EVENT_CIRCLE_OF_DESTRUCTION: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(target, SPELL_CIRCLE_OF_DESTRUCTION); + events.ScheduleEvent(EVENT_CIRCLE_OF_DESTRUCTION, 12000); + break; + case EVENT_COWER_IN_FEAR: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(target, SPELL_COWER_IN_FEAR); + events.ScheduleEvent(EVENT_COWER_IN_FEAR, 10000); + break; + case EVENT_DARK_MENDING: + // find an ally with missing HP + if (Unit* target = DoSelectLowestHpFriendly(40, DUNGEON_MODE(30000, 50000))) + { + DoCast(target, SPELL_DARK_MENDING); + events.ScheduleEvent(EVENT_DARK_MENDING, 20000); + } + else + { + // no friendly unit with missing hp. re-check in just 5 sec. + events.ScheduleEvent(EVENT_DARK_MENDING, 5000); + } + break; } DoMeleeAttackIfReady(); } }; + CreatureAI* GetAI(Creature* creature) const + { + return new npc_ghostly_priestAI(creature); + } }; class npc_phantom_mage : public CreatureScript @@ -713,22 +769,10 @@ class npc_phantom_mage : public CreatureScript public: npc_phantom_mage() : CreatureScript("npc_phantom_mage") { } - CreatureAI* GetAI(Creature* creature) const - { - return new npc_phantom_mageAI(creature); - } - - struct npc_phantom_mageAI: public ScriptedAI + struct npc_phantom_mageAI : public npc_gauntlet_trash { - npc_phantom_mageAI(Creature* creature) : ScriptedAI(creature) - { - } - - EventMap events; - - void Reset() + npc_phantom_mageAI(Creature* creature) : npc_gauntlet_trash(creature) { - events.Reset(); } void EnterCombat(Unit* /*who*/) @@ -750,39 +794,40 @@ public: if (me->HasUnitState(UNIT_STATE_CASTING)) return; - while (uint32 eventId = events.ExecuteEvent()) + switch (events.ExecuteEvent()) { - switch (eventId) - { - case EVENT_FIREBALL: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM)) - DoCast(target, SPELL_FIREBALL); - events.ScheduleEvent(EVENT_FIREBALL, 15000); - return; - case EVENT_FLAMESTRIKE: - DoCast(SPELL_FLAMESTRIKE); - events.ScheduleEvent(EVENT_FLAMESTRIKE, 15000); - return; - case EVENT_FROSTBOLT: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM)) - DoCast(target, SPELL_FROSTBOLT); - events.ScheduleEvent(EVENT_FROSTBOLT, 15000); - return; - case EVENT_CHAINS_OF_ICE: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM)) - DoCast(target, SPELL_CHAINS_OF_ICE); - events.ScheduleEvent(EVENT_CHAINS_OF_ICE, 15000); - return; - case EVENT_HALLUCINATION: - DoCast(SPELL_HALLUCINATION); - return; - } + case EVENT_FIREBALL: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(target, SPELL_FIREBALL); + events.ScheduleEvent(EVENT_FIREBALL, 15000); + break; + case EVENT_FLAMESTRIKE: + DoCast(SPELL_FLAMESTRIKE); + events.ScheduleEvent(EVENT_FLAMESTRIKE, 15000); + break; + case EVENT_FROSTBOLT: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(target, SPELL_FROSTBOLT); + events.ScheduleEvent(EVENT_FROSTBOLT, 15000); + break; + case EVENT_CHAINS_OF_ICE: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(target, SPELL_CHAINS_OF_ICE); + events.ScheduleEvent(EVENT_CHAINS_OF_ICE, 15000); + break; + case EVENT_HALLUCINATION: + DoCast(SPELL_HALLUCINATION); + break; } DoMeleeAttackIfReady(); } }; + CreatureAI* GetAI(Creature* creature) const + { + return new npc_phantom_mageAI(creature); + } }; class npc_phantom_hallucination : public CreatureScript @@ -790,16 +835,9 @@ class npc_phantom_hallucination : public CreatureScript public: npc_phantom_hallucination() : CreatureScript("npc_phantom_hallucination") { } - CreatureAI* GetAI(Creature* creature) const - { - return new npc_phantom_hallucinationAI(creature); - } - struct npc_phantom_hallucinationAI : public npc_phantom_mage::npc_phantom_mageAI { - npc_phantom_hallucinationAI(Creature* creature) : npc_phantom_mage::npc_phantom_mageAI(creature) - { - } + npc_phantom_hallucinationAI(Creature* creature) : npc_phantom_mage::npc_phantom_mageAI(creature) {} void JustDied(Unit* /*killer*/) { @@ -807,6 +845,10 @@ public: } }; + CreatureAI* GetAI(Creature* creature) const + { + return new npc_phantom_hallucinationAI(creature); + } }; class npc_shadowy_mercenary : public CreatureScript @@ -814,22 +856,10 @@ class npc_shadowy_mercenary : public CreatureScript public: npc_shadowy_mercenary() : CreatureScript("npc_shadowy_mercenary") { } - CreatureAI* GetAI(Creature* creature) const + struct npc_shadowy_mercenaryAI : public npc_gauntlet_trash { - return new npc_shadowy_mercenaryAI(creature); - } - - struct npc_shadowy_mercenaryAI: public ScriptedAI - { - npc_shadowy_mercenaryAI(Creature* creature) : ScriptedAI(creature) - { - } - - EventMap events; - - void Reset() + npc_shadowy_mercenaryAI(Creature* creature) : npc_gauntlet_trash(creature) { - events.Reset(); } void EnterCombat(Unit* /*who*/) @@ -850,34 +880,35 @@ public: if (me->HasUnitState(UNIT_STATE_CASTING)) return; - while (uint32 eventId = events.ExecuteEvent()) + switch (events.ExecuteEvent()) { - switch (eventId) - { - case EVENT_SHADOW_STEP: - DoCast(SPELL_SHADOW_STEP); - events.ScheduleEvent(EVENT_SHADOW_STEP, 8000); - return; - case EVENT_DEADLY_POISON: - DoCast(me->getVictim(), SPELL_DEADLY_POISON); - events.ScheduleEvent(EVENT_DEADLY_POISON, 10000); - return; - case EVENT_ENVENOMED_DAGGER_THROW: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM)) - DoCast(target, SPELL_ENVENOMED_DAGGER_THROW); - events.ScheduleEvent(EVENT_ENVENOMED_DAGGER_THROW, 10000); - return; - case EVENT_KIDNEY_SHOT: - DoCast(me->getVictim(), SPELL_KIDNEY_SHOT); - events.ScheduleEvent(EVENT_KIDNEY_SHOT, 10000); - return; - } + case EVENT_SHADOW_STEP: + DoCast(SPELL_SHADOW_STEP); + events.ScheduleEvent(EVENT_SHADOW_STEP, 8000); + break; + case EVENT_DEADLY_POISON: + DoCast(me->getVictim(), SPELL_DEADLY_POISON); + events.ScheduleEvent(EVENT_DEADLY_POISON, 10000); + break; + case EVENT_ENVENOMED_DAGGER_THROW: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(target, SPELL_ENVENOMED_DAGGER_THROW); + events.ScheduleEvent(EVENT_ENVENOMED_DAGGER_THROW, 10000); + break; + case EVENT_KIDNEY_SHOT: + DoCast(me->getVictim(), SPELL_KIDNEY_SHOT); + events.ScheduleEvent(EVENT_KIDNEY_SHOT, 10000); + break; } DoMeleeAttackIfReady(); } }; + CreatureAI* GetAI(Creature* creature) const + { + return new npc_shadowy_mercenaryAI(creature); + } }; class npc_spectral_footman : public CreatureScript @@ -885,29 +916,176 @@ class npc_spectral_footman : public CreatureScript public: npc_spectral_footman() : CreatureScript("npc_spectral_footman") { } + struct npc_spectral_footmanAI : public npc_gauntlet_trash + { + npc_spectral_footmanAI(Creature* creature) : npc_gauntlet_trash(creature) + { + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_SPECTRAL_STRIKE, 5000); /// @todo adjust timers + events.ScheduleEvent(EVENT_SHIELD_BASH, 10000); + events.ScheduleEvent(EVENT_TORTURED_ENRAGE, 15000); + } + + void UpdateAI(uint32 diff) + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + switch (events.ExecuteEvent()) + { + case EVENT_SPECTRAL_STRIKE: + DoCast(me->getVictim(), SPELL_SPECTRAL_STRIKE); + events.ScheduleEvent(EVENT_SPECTRAL_STRIKE, 5000); + break; + case EVENT_SHIELD_BASH: + DoCast(me->getVictim(), SPELL_SHIELD_BASH); + events.ScheduleEvent(EVENT_SHIELD_BASH, 5000); + break; + case EVENT_TORTURED_ENRAGE: + DoCast(SPELL_TORTURED_ENRAGE); + events.ScheduleEvent(EVENT_TORTURED_ENRAGE, 15000); + break; + } + + DoMeleeAttackIfReady(); + } + }; + CreatureAI* GetAI(Creature* creature) const { return new npc_spectral_footmanAI(creature); } +}; + +class npc_tortured_rifleman : public CreatureScript +{ +public: + npc_tortured_rifleman() : CreatureScript("npc_tortured_rifleman") { } - struct npc_spectral_footmanAI: public ScriptedAI + struct npc_tortured_riflemanAI : public npc_gauntlet_trash { - npc_spectral_footmanAI(Creature* creature) : ScriptedAI(creature) + npc_tortured_riflemanAI(Creature* creature) : npc_gauntlet_trash(creature) { } + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_SHOOT, 2000); /// @todo adjust timers + events.ScheduleEvent(EVENT_CURSED_ARROW, 10000); + events.ScheduleEvent(EVENT_FROST_TRAP, 1000); + events.ScheduleEvent(EVENT_ICE_SHOT, 15000); + } + + void UpdateAI(uint32 diff) + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + switch (events.ExecuteEvent()) + { + case EVENT_SHOOT: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(target, SPELL_SHOOT); + events.ScheduleEvent(EVENT_SHOOT, 2000); + break; + case EVENT_CURSED_ARROW: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(target, SPELL_CURSED_ARROW); + events.ScheduleEvent(EVENT_CURSED_ARROW, 10000); + break; + case EVENT_FROST_TRAP: + DoCast(SPELL_FROST_TRAP); + events.ScheduleEvent(EVENT_FROST_TRAP, 30000); + break; + case EVENT_ICE_SHOT: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(target, SPELL_ICE_SHOT); + events.ScheduleEvent(EVENT_ICE_SHOT, 15000); + break; + } + + DoMeleeAttackIfReady(); + } + }; + + CreatureAI* GetAI(Creature* creature) const + { + return new npc_tortured_riflemanAI(creature); + } +}; + + +enum GeneralEvents +{ + //General + EVENT_SHIELD = 0, + EVENT_SPIKE = 1, + EVENT_CLONE = 2, + + SAY_AGGRO = 0, + SAY_DEATH = 1, + + SPELL_SHIELD_THROWN = 69222, // 73076 on hc + SPELL_SPIKE = 69184, // 70399 on hc + SPELL_CLONE_NAME = 57507, + SPELL_CLONE_MODEL = 45204, + + // Reflection + EVENT_BALEFUL_STRIKE = 0, + + SPELL_BALEFUL_STRIKE = 69933, // 70400 on hc + SPELL_SPIRIT_BURST = 69900, // 73046 on hc +}; + +class npc_frostworn_general : public CreatureScript +{ +public: + npc_frostworn_general() : CreatureScript("npc_frostworn_general") { } + + struct npc_frostworn_generalAI : public ScriptedAI + { + npc_frostworn_generalAI(Creature* creature) : ScriptedAI(creature) + { + instance = me->GetInstanceScript(); + Reset(); + } + + InstanceScript* instance; + EventMap events; void Reset() { events.Reset(); + instance->SetData(DATA_FROSWORN_EVENT, NOT_STARTED); } - void EnterCombat(Unit* /*who*/) + void JustDied(Unit* /*killer*/) { - events.ScheduleEvent(EVENT_SPECTRAL_STRIKE, 5000); /// @todo adjust timers - events.ScheduleEvent(EVENT_SHIELD_BASH, 10000); - events.ScheduleEvent(EVENT_TORTURED_ENRAGE, 15000); + Talk(SAY_DEATH); + instance->SetData(DATA_FROSWORN_EVENT, DONE); + } + + void EnterCombat(Unit* /*victim*/) + { + Talk(SAY_AGGRO); + events.ScheduleEvent(EVENT_SHIELD, 5000); + events.ScheduleEvent(EVENT_SPIKE, 14000); + events.ScheduleEvent(EVENT_CLONE, 22000); + instance->SetData(DATA_FROSWORN_EVENT, IN_PROGRESS); } void UpdateAI(uint32 diff) @@ -920,45 +1098,61 @@ public: if (me->HasUnitState(UNIT_STATE_CASTING)) return; - while (uint32 eventId = events.ExecuteEvent()) + switch (events.ExecuteEvent()) { - switch (eventId) - { - case EVENT_SPECTRAL_STRIKE: - DoCast(me->getVictim(), SPELL_SPECTRAL_STRIKE); - events.ScheduleEvent(EVENT_SPECTRAL_STRIKE, 5000); - return; - case EVENT_SHIELD_BASH: - DoCast(me->getVictim(), SPELL_SHIELD_BASH); - events.ScheduleEvent(EVENT_SHIELD_BASH, 5000); - return; - case EVENT_TORTURED_ENRAGE: - DoCast(SPELL_TORTURED_ENRAGE); - events.ScheduleEvent(EVENT_TORTURED_ENRAGE, 15000); - return; - } + case EVENT_SHIELD: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) + DoCast(target, SPELL_SHIELD_THROWN); + events.ScheduleEvent(EVENT_SHIELD, urand(8000, 12000)); + break; + case EVENT_SPIKE: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) + DoCast(target, SPELL_SPIKE); + events.ScheduleEvent(EVENT_SPIKE, urand(15000, 20000)); + break; + case EVENT_CLONE: + SummonClones(); + events.ScheduleEvent(EVENT_CLONE, 60000); + break; } DoMeleeAttackIfReady(); } - }; -}; + void SummonClones() + { + std::list<Unit *> playerList; + SelectTargetList(playerList, 5, SELECT_TARGET_TOPAGGRO, 0, true); + for (std::list<Unit*>::const_iterator itr = playerList.begin(); itr != playerList.end(); ++itr) + { + Unit* temp = (*itr); + Creature* reflection = me->SummonCreature(NPC_REFLECTION, temp->GetPositionX(), temp->GetPositionY(), temp->GetPositionZ(), temp->GetOrientation(), TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 3000); + reflection->SetName(temp->GetName()); + temp->CastSpell(reflection, SPELL_CLONE_NAME, true); + temp->CastSpell(reflection, SPELL_CLONE_MODEL, true); + reflection->setFaction(me->getFaction()); + reflection->AI()->AttackStart(temp); + } -class npc_tortured_rifleman : public CreatureScript -{ -public: - npc_tortured_rifleman() : CreatureScript("npc_tortured_rifleman") { } + } + }; CreatureAI* GetAI(Creature* creature) const { - return new npc_tortured_riflemanAI(creature); + return new npc_frostworn_generalAI(creature); } +}; + +class npc_spiritual_reflection : public CreatureScript +{ +public: + npc_spiritual_reflection() : CreatureScript("npc_spiritual_reflection") { } - struct npc_tortured_riflemanAI : public ScriptedAI + struct npc_spiritual_reflectionAI : public ScriptedAI { - npc_tortured_riflemanAI(Creature* creature) : ScriptedAI(creature) + npc_spiritual_reflectionAI(Creature *creature) : ScriptedAI(creature) { + Reset(); } EventMap events; @@ -968,12 +1162,14 @@ public: events.Reset(); } - void EnterCombat(Unit* /*who*/) + void EnterCombat(Unit* /*victim*/) { - events.ScheduleEvent(EVENT_SHOOT, 2000); /// @todo adjust timers - events.ScheduleEvent(EVENT_CURSED_ARROW, 10000); - events.ScheduleEvent(EVENT_FROST_TRAP, 1000); - events.ScheduleEvent(EVENT_ICE_SHOT, 15000); + events.ScheduleEvent(EVENT_BALEFUL_STRIKE, 3000); + } + + void JustDied(Unit* killer) + { + DoCast(killer, SPELL_SPIRIT_BURST); } void UpdateAI(uint32 diff) @@ -986,46 +1182,90 @@ public: if (me->HasUnitState(UNIT_STATE_CASTING)) return; - while (uint32 eventId = events.ExecuteEvent()) + switch (events.ExecuteEvent()) { - switch (eventId) - { - case EVENT_SHOOT: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM)) - DoCast(target, SPELL_SHOOT); - events.ScheduleEvent(EVENT_SHOOT, 2000); - return; - case EVENT_CURSED_ARROW: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM)) - DoCast(target, SPELL_CURSED_ARROW); - events.ScheduleEvent(EVENT_CURSED_ARROW, 10000); - return; - case EVENT_FROST_TRAP: - DoCast(SPELL_FROST_TRAP); - events.ScheduleEvent(EVENT_FROST_TRAP, 30000); - return; - case EVENT_ICE_SHOT: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM)) - DoCast(target, SPELL_ICE_SHOT); - events.ScheduleEvent(EVENT_ICE_SHOT, 15000); - return; - } + case EVENT_BALEFUL_STRIKE: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) + DoCast(target, SPELL_BALEFUL_STRIKE); + events.ScheduleEvent(EVENT_BALEFUL_STRIKE, urand(3000, 8000)); } DoMeleeAttackIfReady(); } }; + CreatureAI* GetAI(Creature* creature) const + { + return new npc_spiritual_reflectionAI(creature); + } +}; + +class at_hor_intro_start : public AreaTriggerScript +{ +public: + at_hor_intro_start() : AreaTriggerScript("at_hor_intro_start") {} + + bool OnTrigger(Player* player, AreaTriggerEntry const* /*trigger*/) + { + InstanceScript* instance = player->GetInstanceScript(); + + if (player->isGameMaster()) + return true; + + if (instance->GetData(DATA_INTRO_EVENT) == NOT_STARTED) + { + instance->SetData(DATA_INTRO_EVENT, IN_PROGRESS); + } + + return true; + } +}; + +class at_hor_waves_restarter : public AreaTriggerScript +{ +public: + at_hor_waves_restarter() : AreaTriggerScript("at_hor_waves_restarter") {} + + bool OnTrigger(Player* player, AreaTriggerEntry const* /*trigger*/) + { + InstanceScript* instance = player->GetInstanceScript(); + + if (player->isGameMaster()) + return true; + + if (instance->GetData(DATA_WAVE_COUNT)) + return true; + + if (instance->GetData(DATA_INTRO_EVENT) == DONE && instance->GetBossState(DATA_MARWYN_EVENT) != DONE) + { + instance->ProcessEvent(0, EVENT_SPAWN_WAVES); + + if (Creature* falric = player->GetCreature(*player, instance->GetData64(DATA_FALRIC_EVENT))) + { + falric->CastSpell(falric, SPELL_BOSS_SPAWN_AURA, true); + falric->SetVisible(true); + } + if (Creature* marwyn = player->GetCreature(*player, instance->GetData64(DATA_MARWYN_EVENT))) + { + marwyn->CastSpell(marwyn, SPELL_BOSS_SPAWN_AURA, true); + marwyn->SetVisible(true); + } + } + return true; + } }; void AddSC_halls_of_reflection() { - new npc_jaina_or_sylvanas_hor(true, "npc_sylvanas_hor_part1"); - new npc_jaina_or_sylvanas_hor(false, "npc_jaina_hor_part1"); + new npc_jaina_or_sylvanas_hor(); new npc_ghostly_priest(); new npc_phantom_mage(); new npc_phantom_hallucination(); new npc_shadowy_mercenary(); new npc_spectral_footman(); new npc_tortured_rifleman(); + new at_hor_intro_start(); + new at_hor_waves_restarter(); + new npc_frostworn_general(); + new npc_spiritual_reflection(); } diff --git a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.h b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.h index 2cab1cca214..4787a6b9fdc 100644 --- a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.h +++ b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.h @@ -18,54 +18,83 @@ #ifndef DEF_HALLS_OF_REFLECTION_H #define DEF_HALLS_OF_REFLECTION_H -enum Data -{ - DATA_FALRIC_EVENT, - DATA_MARWYN_EVENT, - DATA_LICHKING_EVENT, - DATA_WAVE_COUNT, - DATA_TEAM_IN_INSTANCE, -}; +#define HoRScriptName "instance_halls_of_reflection" +#define MAX_ENCOUNTER 3 -enum Data64 +/* Halls of Reflection encounters: +0- Falric +1- Marwyn +2- The Lich King +*/ + +enum Data { - DATA_FALRIC, - DATA_MARWYN, - DATA_LICHKING, - DATA_FROSTMOURNE, + DATA_FALRIC_EVENT = 0, + DATA_MARWYN_EVENT = 1, + DATA_LICHKING_EVENT = 2, + DATA_INTRO_EVENT = 3, + DATA_FROSWORN_EVENT = 4, + + DATA_WAVE_COUNT = 5, + DATA_TEAM_IN_INSTANCE = 6, + DATA_FROSTMOURNE = 7, + DATA_FROSTWORN_DOOR = 8, }; enum Creatures { - NPC_FALRIC = 38112, - NPC_MARWYN = 38113, - NPC_LICH_KING_EVENT = 37226, - NPC_LICH_KING_BOSS = 36954, - - NPC_UTHER = 37225, NPC_JAINA_PART1 = 37221, - NPC_JAINA_PART2 = 36955, NPC_SYLVANAS_PART1 = 37223, - NPC_SYLVANAS_PART2 = 37554, + NPC_UTHER = 37225, + NPC_LICH_KING_PART1 = 37226, + NPC_LORALEN = 37779, + NPC_KORELN = 37582, + NPC_FALRIC = 38112, + NPC_MARWYN = 38113, NPC_WAVE_MERCENARY = 38177, NPC_WAVE_FOOTMAN = 38173, NPC_WAVE_RIFLEMAN = 38176, NPC_WAVE_PRIEST = 38175, NPC_WAVE_MAGE = 38172, + + NPC_FROSTWORN_GENERAL = 36723, + NPC_REFLECTION = 37068, // 37107 for tank only? + + NPC_JAINA_PART2 = 36955, + NPC_SYLVANAS_PART2 = 37554, + NPC_LICH_KING_PART2 = 36954, + NPC_BARTLETT = 37182, // High Captain Justin Bartlett + NPC_KORM = 37833, // Sky-Reaver Korm Blackscar + NPC_ICE_WALL = 37014, // Ice Wall Target }; enum GameObjects { GO_FROSTMOURNE = 202302, - GO_FROSTMOURNE_ALTAR = 202236, - GO_FRONT_DOOR = 201976, - GO_ARTHAS_DOOR = 197341, + GO_ENTRANCE_DOOR = 201976, + GO_FROSTWORN_DOOR = 197341, + GO_ARTHAS_DOOR = 197342, + //GO_ESCAPE_DOOR = 197343, // always open ? + + GO_ICE_WALL = 201385, + GO_CAVE = 201596, + + GO_STAIRS_SKYBREAKER = 201709, + GO_SKYBREAKER = 201598, + GO_STAIRS_ORGRIM_HAMMER = 202211, + GO_ORGRIM_HAMMER = 201599, + GO_PORTAL = 202079, + + GO_CAPTAIN_CHEST_1 = 202212, //3145 + GO_CAPTAIN_CHEST_2 = 201710, //30357 + GO_CAPTAIN_CHEST_3 = 202337, //3246 + GO_CAPTAIN_CHEST_4 = 202336, //3333 }; enum HorWorldStates { - WORLD_STATE_HOR = 4884, + WORLD_STATE_HOR_WAVES_ENABLED = 4884, WORLD_STATE_HOR_WAVE_COUNT = 4882, }; @@ -75,6 +104,21 @@ enum Actions ACTION_ENTER_COMBAT, }; +enum TrashGeneralSpells +{ + // General spells + SPELL_WELL_OF_SOULS = 72630, // cast when spawn(become visible) + SPELL_SPIRIT_ACTIVATE = 72130, // cast when unit activates +}; + +enum InstanceEvents +{ + EVENT_SPAWN_WAVES = 1, + EVENT_NEXT_WAVE = 2, + EVENT_DO_WIPE = 3, + EVENT_ADD_WAVE = 4, +}; + // Base class for FALRIC and MARWYN // handled the summonList and the notification events to/from the InstanceScript struct boss_horAI : ScriptedAI @@ -92,14 +136,10 @@ struct boss_horAI : ScriptedAI { events.Reset(); me->SetVisible(false); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_IMMUNE_TO_NPC); me->SetReactState(REACT_PASSIVE); - } - - void DamageTaken(Unit* /*who*/, uint32 &uiDamage) - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - uiDamage = 0; + if (instance->GetData(DATA_WAVE_COUNT) != NOT_STARTED) + instance->ProcessEvent(0, EVENT_DO_WIPE); } void DoAction(int32 actionID) @@ -107,11 +147,7 @@ struct boss_horAI : ScriptedAI switch (actionID) { case ACTION_ENTER_COMBAT: // called by InstanceScript when boss shall enter in combat. - // Just in case. Should have been done by InstanceScript - me->SetVisible(true); - - // Reset flags - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_IMMUNE_TO_NPC); me->SetReactState(REACT_AGGRESSIVE); if (Unit* unit = me->SelectNearestTarget()) @@ -125,32 +161,6 @@ struct boss_horAI : ScriptedAI void JustSummoned(Creature* summoned) { summons.Summon(summoned); - - if (Unit* target = summoned->SelectNearestTarget()) - { - if (summoned->AI()) - summoned->AI()->AttackStart(target); - else - { - summoned->GetMotionMaster()->MoveChase(target); - summoned->Attack(target, true); - } - } - - if (summoned->AI()) - summoned->AI()->DoZoneInCombat(); - } - - void SummonedCreatureDespawn(Creature* summoned) - { - summons.Despawn(summoned); - if (summons.empty()) - { - if (summoned->isAlive()) - instance->SetData(DATA_WAVE_COUNT, NOT_STARTED); - else - instance->SetData(DATA_WAVE_COUNT, SPECIAL); - } } }; 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 dde3f7acc67..bff18b508d5 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 @@ -18,85 +18,50 @@ #include "ScriptMgr.h" #include "ScriptedCreature.h" #include "InstanceScript.h" -#include "halls_of_reflection.h" #include "Player.h" +#include "WorldPacket.h" +#include "halls_of_reflection.h" -#define MAX_ENCOUNTER 3 - -/* Halls of Reflection encounters: -0- Falric -1- Marwyn -2- The Lich King -*/ - -enum eEnum -{ - ENCOUNTER_WAVE_MERCENARY = 6, - ENCOUNTER_WAVE_FOOTMAN = 10, - ENCOUNTER_WAVE_RIFLEMAN = 6, - ENCOUNTER_WAVE_PRIEST = 6, - ENCOUNTER_WAVE_MAGE = 6, -}; - -enum Events -{ - EVENT_NONE, - EVENT_NEXT_WAVE, - EVENT_START_LICH_KING, -}; - -static Position PriestSpawnPos[ENCOUNTER_WAVE_PRIEST] = -{ - {5277.74f, 2016.88f, 707.778f, 5.96903f}, - {5295.88f, 2040.34f, 707.778f, 5.07891f}, - {5320.37f, 1980.13f, 707.778f, 2.00713f}, - {5280.51f, 1997.84f, 707.778f, 0.296706f}, - {5302.45f, 2042.22f, 707.778f, 4.90438f}, - {5306.57f, 1977.47f, 707.778f, 1.50098f}, -}; - -static Position MageSpawnPos[ENCOUNTER_WAVE_MAGE] = -{ - {5312.75f, 2037.12f, 707.778f, 4.59022f}, - {5309.58f, 2042.67f, 707.778f, 4.69494f}, - {5275.08f, 2008.72f, 707.778f, 6.21337f}, - {5279.65f, 2004.66f, 707.778f, 0.069813f}, - {5275.48f, 2001.14f, 707.778f, 0.174533f}, - {5316.7f, 2041.55f, 707.778f, 4.50295f}, -}; - -static Position MercenarySpawnPos[ENCOUNTER_WAVE_MERCENARY] = -{ - {5302.25f, 1972.41f, 707.778f, 1.37881f}, - {5311.03f, 1972.23f, 707.778f, 1.64061f}, - {5277.36f, 1993.23f, 707.778f, 0.401426f}, - {5318.7f, 2036.11f, 707.778f, 4.2237f}, - {5335.72f, 1996.86f, 707.778f, 2.74017f}, - {5299.43f, 1979.01f, 707.778f, 1.23918f}, -}; +Position const JainaSpawnPos = {5236.659f, 1929.894f, 707.7781f, 0.8726646f}; // Jaina Spawn Position +Position const SylvanasSpawnPos = {5236.667f, 1929.906f, 707.7781f, 0.8377581f}; // Sylvanas Spawn Position +Position const GeneralSpawnPos = {5415.538f, 2117.842f, 707.7781f, 3.944444f}; // Frostsworn General -static Position FootmenSpawnPos[ENCOUNTER_WAVE_FOOTMAN] = +Position const SpawnPos[] = { - {5306.06f, 2037, 707.778f, 4.81711f}, - {5344.15f, 2007.17f, 707.778f, 3.15905f}, - {5337.83f, 2010.06f, 707.778f, 3.22886f}, - {5343.29f, 1999.38f, 707.778f, 2.9147f}, - {5340.84f, 1992.46f, 707.778f, 2.75762f}, - {5325.07f, 1977.6f, 707.778f, 2.07694f}, - {5336.6f, 2017.28f, 707.778f, 3.47321f}, - {5313.82f, 1978.15f, 707.778f, 1.74533f}, - {5280.63f, 2012.16f, 707.778f, 6.05629f}, - {5322.96f, 2040.29f, 707.778f, 4.34587f}, -}; - -static Position RiflemanSpawnPos[ENCOUNTER_WAVE_RIFLEMAN] = -{ - {5343.47f, 2015.95f, 707.778f, 3.49066f}, - {5337.86f, 2003.4f, 707.778f, 2.98451f}, - {5319.16f, 1974, 707.778f, 1.91986f}, - {5299.25f, 2036, 707.778f, 5.02655f}, - {5295.64f, 1973.76f, 707.778f, 1.18682f}, - {5282.9f, 2019.6f, 707.778f, 5.88176f}, + {5309.577f, 2042.668f, 707.7781f, 4.694936f}, + {5295.885f, 2040.342f, 707.7781f, 5.078908f}, + {5340.836f, 1992.458f, 707.7781f, 2.757620f}, + {5325.072f, 1977.597f, 707.7781f, 2.076942f}, + {5277.365f, 1993.229f, 707.7781f, 0.401426f}, + {5275.479f, 2001.135f, 707.7781f, 0.174533f}, + {5302.448f, 2042.222f, 707.7781f, 4.904375f}, + {5343.293f, 1999.384f, 707.7781f, 2.914700f}, + {5295.635f, 1973.757f, 707.7781f, 1.186824f}, + {5311.031f, 1972.229f, 707.7781f, 1.640610f}, + {5275.076f, 2008.724f, 707.7781f, 6.213372f}, + {5316.701f, 2041.550f, 707.7781f, 4.502949f}, + {5344.150f, 2007.168f, 707.7781f, 3.159046f}, + {5319.158f, 1973.998f, 707.7781f, 1.919862f}, + {5302.247f, 1972.415f, 707.7781f, 1.378810f}, + {5277.739f, 2016.882f, 707.7781f, 5.969026f}, + {5322.964f, 2040.288f, 707.7781f, 4.345870f}, + {5343.467f, 2015.951f, 707.7781f, 3.490659f}, + {5313.820f, 1978.146f, 707.7781f, 1.745329f}, + {5279.649f, 2004.656f, 707.7781f, 0.069814f}, + {5306.057f, 2037.002f, 707.7781f, 4.817109f}, + {5337.865f, 2003.403f, 707.7781f, 2.984513f}, + {5299.434f, 1979.009f, 707.7781f, 1.239184f}, + {5312.752f, 2037.122f, 707.7781f, 4.590216f}, + {5335.724f, 1996.859f, 707.7781f, 2.740167f}, + {5280.632f, 2012.156f, 707.7781f, 6.056293f}, + {5320.369f, 1980.125f, 707.7781f, 2.007129f}, + {5306.572f, 1977.474f, 707.7781f, 1.500983f}, + {5336.599f, 2017.278f, 707.7781f, 3.473205f}, + {5282.897f, 2019.597f, 707.7781f, 5.881760f}, + {5318.704f, 2036.108f, 707.7781f, 4.223697f}, + {5280.513f, 1997.842f, 707.7781f, 0.296706f}, + {5337.833f, 2010.057f, 707.7781f, 3.228859f}, + {5299.250f, 2035.998f, 707.7781f, 5.026548f}, }; class instance_halls_of_reflection : public InstanceMapScript @@ -104,107 +69,107 @@ class instance_halls_of_reflection : public InstanceMapScript public: instance_halls_of_reflection() : InstanceMapScript("instance_halls_of_reflection", 668) { } - InstanceScript* GetInstanceScript(InstanceMap* map) const - { - return new instance_halls_of_reflection_InstanceMapScript(map); - } - struct instance_halls_of_reflection_InstanceMapScript : public InstanceScript { - instance_halls_of_reflection_InstanceMapScript(Map* map) : InstanceScript(map) {}; - - uint64 uiFalric; - uint64 uiMarwyn; - uint64 uiLichKingEvent; - uint64 uiJainaPart1; - uint64 uiSylvanasPart1; - - uint64 uiFrostmourne; - uint64 uiFrostmourneAltar; - uint64 uiArthasDoor; - uint64 uiFrontDoor; - - uint32 uiEncounter[MAX_ENCOUNTER]; - uint32 uiTeamInInstance; - uint32 uiWaveCount; - bool bIntroDone; - - EventMap events; + instance_halls_of_reflection_InstanceMapScript(Map* map) : InstanceScript(map) {} void Initialize() { + SetBossNumber(MAX_ENCOUNTER); events.Reset(); + _falricGUID = 0; + _marwynGUID = 0; + _jainaOrSylvanasPart1GUID = 0; + _frostwornGeneralGUID = 0; + _frostmourneGUID = 0; + _entranceDoorGUID = 0; + _frostwornDoorGUID = 0; + _arthasDoorGUID = 0; + _teamInInstance = 0; + _waveCount = 0; + _introEvent = NOT_STARTED; + _frostwornGeneral = NOT_STARTED; + } - uiFalric = 0; - uiMarwyn = 0; - uiLichKingEvent = 0; - uiJainaPart1 = 0; - uiSylvanasPart1 = 0; - - uiFrostmourne = 0; - uiFrostmourneAltar = 0; - uiArthasDoor = 0; - uiFrontDoor = 0; - uiTeamInInstance = 0; - uiWaveCount = 0; - bIntroDone = false; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - uiEncounter[i] = NOT_STARTED; + void OnPlayerEnter(Player* player) + { + if (!_teamInInstance) + _teamInInstance = player->GetTeam(); } void OnCreatureCreate(Creature* creature) { - Map::PlayerList const &players = instance->GetPlayers(); + Map::PlayerList const& players = instance->GetPlayers(); if (!players.isEmpty()) if (Player* player = players.begin()->getSource()) - uiTeamInInstance = player->GetTeam(); + _teamInInstance = player->GetTeam(); switch (creature->GetEntry()) { + case NPC_JAINA_PART1: + case NPC_SYLVANAS_PART1: + _jainaOrSylvanasPart1GUID = creature->GetGUID(); + break; case NPC_FALRIC: - uiFalric = creature->GetGUID(); + _falricGUID = creature->GetGUID(); break; case NPC_MARWYN: - uiMarwyn = creature->GetGUID(); - break; - case NPC_LICH_KING_EVENT: - uiLichKingEvent = creature->GetGUID(); + _marwynGUID = creature->GetGUID(); break; - case NPC_JAINA_PART1: - uiJainaPart1 = creature->GetGUID(); + case NPC_FROSTWORN_GENERAL: + _frostwornGeneralGUID = creature->GetGUID(); + if (GetBossState(DATA_MARWYN_EVENT) == DONE) + if (Creature* general = instance->GetCreature(_frostwornGeneralGUID)) + general->SetPhaseMask(1, true); break; - case NPC_SYLVANAS_PART1: - uiSylvanasPart1 = creature->GetGUID(); + } + } + + void OnCreatureRemove(Creature* creature) + { + switch (creature->GetEntry()) + { + case NPC_WAVE_MERCENARY: + case NPC_WAVE_FOOTMAN: + case NPC_WAVE_RIFLEMAN: + case NPC_WAVE_PRIEST: + case NPC_WAVE_MAGE: + { + uint32 internalWaveId = creature->AI()->GetData(0); + waveGuidList[internalWaveId].erase(creature->GetGUID()); break; + } } } void OnGameObjectCreate(GameObject* go) { - /// @todo init state depending on encounters switch (go->GetEntry()) { case GO_FROSTMOURNE: - uiFrostmourne = go->GetGUID(); + _frostmourneGUID = go->GetGUID(); go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_INTERACT_COND); HandleGameObject(0, false, go); + if (GetData(DATA_INTRO_EVENT) == DONE) + go->SetPhaseMask(2, true); break; - case GO_FROSTMOURNE_ALTAR: - uiFrostmourneAltar = go->GetGUID(); + case GO_ENTRANCE_DOOR: + _entranceDoorGUID = go->GetGUID(); go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_INTERACT_COND); HandleGameObject(0, true, go); break; - case GO_FRONT_DOOR: - uiFrontDoor = go->GetGUID(); + case GO_FROSTWORN_DOOR: + _frostwornDoorGUID = go->GetGUID(); go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_INTERACT_COND); - HandleGameObject(0, true, go); + if (GetBossState(DATA_MARWYN_EVENT) == DONE) + HandleGameObject(0, true, go); + else + HandleGameObject(0, false, go); break; case GO_ARTHAS_DOOR: - uiArthasDoor = go->GetGUID(); + _arthasDoorGUID = go->GetGUID(); go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_INTERACT_COND); - - if (uiEncounter[1] == DONE) + if (GetBossState(DATA_FROSWORN_EVENT) == DONE) HandleGameObject(0, true, go); else HandleGameObject(0, false, go); @@ -212,61 +177,273 @@ public: } } - void SetData(uint32 type, uint32 data) + void FillInitialWorldStates(WorldPacket& data) { - if (type == DATA_WAVE_COUNT && data == SPECIAL) - { - bIntroDone = true; - events.ScheduleEvent(EVENT_NEXT_WAVE, 10000); - return; - } + data << uint32(WORLD_STATE_HOR_WAVES_ENABLED) << uint32(0); + data << uint32(WORLD_STATE_HOR_WAVE_COUNT) << uint32(0); + } - if (uiWaveCount && data == NOT_STARTED) - DoWipe(); + bool SetBossState(uint32 type, EncounterState state) + { + if (!InstanceScript::SetBossState(type, state)) + return false; switch (type) { case DATA_FALRIC_EVENT: - uiEncounter[0] = data; - if (data == DONE) + if (state == DONE) + { + ++_waveCount; events.ScheduleEvent(EVENT_NEXT_WAVE, 60000); + } break; case DATA_MARWYN_EVENT: - uiEncounter[1] = data; - if (data == DONE) - HandleGameObject(uiArthasDoor, true); + if (state == DONE) + { + HandleGameObject(_entranceDoorGUID, true); + HandleGameObject(_frostwornDoorGUID, true); + if (Creature* general = instance->GetCreature(_frostwornGeneralGUID)) + general->SetPhaseMask(1, true); + } break; case DATA_LICHKING_EVENT: - uiEncounter[2] = data; break; + default: + break; + } + + return true; + } + + void SetData(uint32 type, uint32 data) + { + switch (type) + { + case DATA_INTRO_EVENT: + if (data == IN_PROGRESS) + { + if (!_introEvent) + { + if (_teamInInstance == ALLIANCE) + instance->SummonCreature(NPC_JAINA_PART1, JainaSpawnPos); + else + instance->SummonCreature(NPC_SYLVANAS_PART1, SylvanasSpawnPos); + } + } + _introEvent = data; + break; + case DATA_WAVE_COUNT: + if (_waveCount && data == NOT_STARTED) + ProcessEvent(NULL, EVENT_DO_WIPE); + break; + case DATA_FROSWORN_EVENT: + if (data == DONE) + { + HandleGameObject(_arthasDoorGUID, true); + // spawn Jaina part 2 + // spawn LK part 2 + } + _frostwornGeneral = data; + break; + } + + SaveToDB(); + } + + + // wave scheduling,checked when wave npcs die + void OnUnitDeath(Unit* unit) + { + Creature* creature = unit->ToCreature(); + if (!creature) + return; + + switch (creature->GetEntry()) + { + case NPC_WAVE_MERCENARY: + case NPC_WAVE_FOOTMAN: + case NPC_WAVE_RIFLEMAN: + case NPC_WAVE_PRIEST: + case NPC_WAVE_MAGE: + { + uint32 deadNpcs = 0; + uint32 waveId = creature->AI()->GetData(0); + for (std::set<uint64>::const_iterator itr = waveGuidList[waveId].begin(); itr != waveGuidList[waveId].end(); ++itr) + { + Creature* npc = instance->GetCreature(*itr); + if (!npc || !npc->isAlive()) + ++deadNpcs; + } + + // because the current npc returns isAlive when OnUnitDeath happens + // we check if the number of dead npcs is equal to the list-1 + if (deadNpcs == waveGuidList[waveId].size() - 1) + { + ++_waveCount; + events.ScheduleEvent(EVENT_NEXT_WAVE, 10000); + } + break; + } } + } + + void Update(uint32 diff) + { + if (!instance->HavePlayers()) + return; - if (data == DONE) - SaveToDB(); + events.Update(diff); + + switch (events.ExecuteEvent()) + { + case EVENT_NEXT_WAVE: + ProcessEvent(NULL, EVENT_ADD_WAVE); + break; + } + } + + void ProcessEvent(WorldObject* /*go*/, uint32 eventId) + { + switch (eventId) + { + // spawning all wave npcs at once + case EVENT_SPAWN_WAVES: + _waveCount = 1; + DoUpdateWorldState(WORLD_STATE_HOR_WAVES_ENABLED, 1); + DoUpdateWorldState(WORLD_STATE_HOR_WAVE_COUNT, _waveCount); + { + std::list<uint32> possibilityList, tempList; + uint32 posIndex = 0; + + possibilityList.push_back(NPC_WAVE_MERCENARY); + possibilityList.push_back(NPC_WAVE_FOOTMAN); + possibilityList.push_back(NPC_WAVE_RIFLEMAN); + possibilityList.push_back(NPC_WAVE_PRIEST); + possibilityList.push_back(NPC_WAVE_MAGE); + + // iterate each wave + for (uint8 i = 0; i < 8; ++i) + { + tempList = possibilityList; + + uint64 bossGuid = i <= 3 ? _falricGUID : _marwynGUID; + + if (!i) + Trinity::Containers::RandomResizeList(tempList, 3); + else if (i < 6 && i != 3) + Trinity::Containers::RandomResizeList(tempList, 4); + + for (std::list<uint32>::const_iterator itr = tempList.begin(); itr != tempList.end(); ++itr) + { + if (Creature* boss = instance->GetCreature(bossGuid)) + { + if (Creature* temp = boss->SummonCreature(*itr, SpawnPos[posIndex], TEMPSUMMON_DEAD_DESPAWN)) + { + temp->AI()->SetData(0, i); + waveGuidList[i].insert(temp->GetGUID()); + } + } + + ++posIndex; + } + } + } + events.ScheduleEvent(EVENT_NEXT_WAVE, 10000); + break; + case EVENT_ADD_WAVE: + DoUpdateWorldState(WORLD_STATE_HOR_WAVES_ENABLED, 1); + DoUpdateWorldState(WORLD_STATE_HOR_WAVE_COUNT, _waveCount); + HandleGameObject(_entranceDoorGUID, false); + + if (_waveCount % 5) + { + uint32 internalWaveId = _waveCount - ((_waveCount < 5) ? 1 : 2); + for (std::set<uint64>::const_iterator itr = waveGuidList[internalWaveId].begin(); itr != waveGuidList[internalWaveId].end(); ++itr) + { + if (Creature* temp = instance->GetCreature(*itr)) + { + temp->CastSpell(temp, SPELL_SPIRIT_ACTIVATE, true); + temp->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC|UNIT_FLAG_IMMUNE_TO_NPC|UNIT_FLAG_NOT_SELECTABLE); + temp->AI()->DoZoneInCombat(); + } + } + } + else + { + uint32 bossIndex = (_waveCount / 5) - 1; + if (GetBossState(DATA_FALRIC_EVENT + bossIndex) != DONE) + { + if (Creature* boss = instance->GetCreature(bossIndex ? _marwynGUID : _falricGUID)) + if (boss->AI()) + boss->AI()->DoAction(ACTION_ENTER_COMBAT); + } + else if (_waveCount != 10) + { + ++_waveCount; + events.ScheduleEvent(EVENT_NEXT_WAVE, 10000); + } + } + break; + case EVENT_DO_WIPE: + _waveCount = 0; + events.Reset(); + DoUpdateWorldState(WORLD_STATE_HOR_WAVES_ENABLED, 1); + DoUpdateWorldState(WORLD_STATE_HOR_WAVE_COUNT, _waveCount); + HandleGameObject(_entranceDoorGUID, true); + + if (Creature* falric = instance->GetCreature(_falricGUID)) + falric->SetVisible(false); + if (Creature* marwyn = instance->GetCreature(_marwynGUID)) + marwyn->SetVisible(false); + + //despawn wave npcs + for (uint8 i = 0; i < 8; ++i) + { + for (std::set<uint64>::const_iterator itr = waveGuidList[i].begin(); itr != waveGuidList[i].end(); ++itr) + if (Creature* creature = instance->GetCreature(*itr)) + creature->DespawnOrUnsummon(1); + + waveGuidList[i].clear(); + } + break; + } } uint32 GetData(uint32 type) const { switch (type) { - case DATA_FALRIC_EVENT: return uiEncounter[0]; - case DATA_MARWYN_EVENT: return uiEncounter[1]; - case DATA_LICHKING_EVENT: return uiEncounter[2]; - case DATA_WAVE_COUNT: return uiWaveCount; - case DATA_TEAM_IN_INSTANCE: return uiTeamInInstance; + case DATA_WAVE_COUNT: + return _waveCount; + case DATA_TEAM_IN_INSTANCE: + return _teamInInstance; + case DATA_INTRO_EVENT: + return _introEvent; + case DATA_FROSWORN_EVENT: + return _frostwornGeneral; + default: + break; } return 0; } - uint64 GetData64(uint32 identifier) const + uint64 GetData64(uint32 type) const { - switch (identifier) + switch (type) { - case DATA_FALRIC: return uiFalric; - case DATA_MARWYN: return uiMarwyn; - case DATA_LICHKING: return uiLichKingEvent; - case DATA_FROSTMOURNE: return uiFrostmourne; + case DATA_FALRIC_EVENT: + return _falricGUID; + case DATA_MARWYN_EVENT: + return _marwynGUID; + case DATA_FROSWORN_EVENT: + return _frostwornGeneralGUID; + case DATA_FROSTWORN_DOOR: + return _frostwornDoorGUID; + case DATA_FROSTMOURNE: + return _frostmourneGUID; + default: + break; } return 0; @@ -277,13 +454,13 @@ public: OUT_SAVE_INST_DATA; std::ostringstream saveStream; - saveStream << "H R 1 " << uiEncounter[0] << ' ' << uiEncounter[1] << ' ' << uiEncounter[2]; + saveStream << "H R " << GetBossSaveData() << _introEvent << ' ' << _frostwornGeneral; OUT_SAVE_INST_DATA_COMPLETE; return saveStream.str(); } - void Load(const char* in) + void Load(char const* in) { if (!in) { @@ -294,135 +471,67 @@ public: OUT_LOAD_INST_DATA(in); char dataHead1, dataHead2; - uint16 version; - uint16 data0, data1, data2; std::istringstream loadStream(in); - loadStream >> dataHead1 >> dataHead2 >> version >> data0 >> data1 >> data2; + loadStream >> dataHead1 >> dataHead2; if (dataHead1 == 'H' && dataHead2 == 'R') { - uiEncounter[0] = data0; - uiEncounter[1] = data1; - uiEncounter[2] = data2; - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (uiEncounter[i] == IN_PROGRESS) - uiEncounter[i] = NOT_STARTED; - - } else OUT_LOAD_INST_DATA_FAIL; - - if (uiEncounter[0] == DONE || uiEncounter[1] == DONE) - bIntroDone = true; - - OUT_LOAD_INST_DATA_COMPLETE; - } - - void AddWave() - { - DoUpdateWorldState(WORLD_STATE_HOR, 1); - DoUpdateWorldState(WORLD_STATE_HOR_WAVE_COUNT, uiWaveCount); - - switch (uiWaveCount) - { - case 1: - case 2: - case 3: - case 4: - if (Creature* pFalric = instance->GetCreature(uiFalric)) - SpawnWave(pFalric); - break; - case 5: - if (GetData(DATA_FALRIC_EVENT) == DONE) - events.ScheduleEvent(EVENT_NEXT_WAVE, 10000); - else if (Creature* pFalric = instance->GetCreature(uiFalric)) - if (pFalric->AI()) - pFalric->AI()->DoAction(ACTION_ENTER_COMBAT); - break; - case 6: - case 7: - case 8: - case 9: - if (Creature* pMarwyn = instance->GetCreature(uiMarwyn)) - SpawnWave(pMarwyn); - break; - case 10: - if (GetData(DATA_MARWYN_EVENT) != DONE) // wave should not have been started if DONE. Check anyway to avoid bug exploit! - if (Creature* pMarwyn = instance->GetCreature(uiMarwyn)) - if (pMarwyn->AI()) - pMarwyn->AI()->DoAction(ACTION_ENTER_COMBAT); - break; + { + uint32 tmpState; + loadStream >> tmpState; + if (tmpState == IN_PROGRESS || tmpState > SPECIAL) + tmpState = NOT_STARTED; + + SetBossState(i, EncounterState(tmpState)); + } + + uint32 temp = 0; + loadStream >> temp; + if (temp == DONE) + SetData(DATA_INTRO_EVENT, DONE); + else + SetData(DATA_INTRO_EVENT, NOT_STARTED); + + loadStream >> temp; + if (temp == DONE) + SetData(DATA_FROSWORN_EVENT, DONE); + else + SetData(DATA_FROSWORN_EVENT, NOT_STARTED); } - } + else + OUT_LOAD_INST_DATA_FAIL; - // Wipe has been detected. Perform cleanup and reset. - void DoWipe() - { - uiWaveCount = 0; - events.Reset(); - DoUpdateWorldState(WORLD_STATE_HOR, 1); - DoUpdateWorldState(WORLD_STATE_HOR_WAVE_COUNT, uiWaveCount); - HandleGameObject(uiFrontDoor, true); - - /// @todo - // in case of wipe, the event is normally restarted by jumping into the center of the room. - // As I can't find a trigger area there, just respawn Jaina/Sylvanas so the event may be restarted. - if (Creature* pJaina = instance->GetCreature(uiJainaPart1)) - pJaina->Respawn(); - if (Creature* pSylvanas = instance->GetCreature(uiSylvanasPart1)) - pSylvanas->Respawn(); - - if (Creature* pFalric = instance->GetCreature(uiFalric)) - pFalric->SetVisible(false); - if (Creature* pMarwyn = instance->GetCreature(uiMarwyn)) - pMarwyn->SetVisible(false); + OUT_LOAD_INST_DATA_COMPLETE; } - // spawn a wave on behalf of the summoner. - void SpawnWave(Creature* summoner) - { - uint32 index; - - summoner->SetVisible(true); - - /// @todo do composition at random. # of spawn also depends on uiWaveCount - // As of now, it is just one of each. - index = urand(0, ENCOUNTER_WAVE_MERCENARY-1); - summoner->SummonCreature(NPC_WAVE_MERCENARY, MercenarySpawnPos[index], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0); - - index = urand(0, ENCOUNTER_WAVE_FOOTMAN-1); - summoner->SummonCreature(NPC_WAVE_FOOTMAN, FootmenSpawnPos[index], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0); - - index = urand(0, ENCOUNTER_WAVE_RIFLEMAN-1); - summoner->SummonCreature(NPC_WAVE_RIFLEMAN, RiflemanSpawnPos[index], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0); + private: + uint64 _falricGUID; + uint64 _marwynGUID; + uint64 _jainaOrSylvanasPart1GUID; + uint64 _frostwornGeneralGUID; - index = urand(0, ENCOUNTER_WAVE_PRIEST-1); - summoner->SummonCreature(NPC_WAVE_PRIEST, PriestSpawnPos[index], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0); + uint64 _frostmourneGUID; + uint64 _entranceDoorGUID; + uint64 _frostwornDoorGUID; + uint64 _arthasDoorGUID; + uint64 _escapeDoorGUID; - index = urand(0, ENCOUNTER_WAVE_MAGE-1); - summoner->SummonCreature(NPC_WAVE_MAGE, MageSpawnPos[index], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0); - } - - void Update(uint32 diff) - { - if (!instance->HavePlayers()) - return; + uint32 _teamInInstance; + uint32 _waveCount; + uint32 _introEvent; + uint32 _frostwornGeneral; - events.Update(diff); + EventMap events; - switch (events.ExecuteEvent()) - { - case EVENT_NEXT_WAVE: - uiWaveCount++; - AddWave(); - break; - case EVENT_START_LICH_KING: - /// @todo - break; - } - } + std::set<uint64> waveGuidList[8]; }; + InstanceScript* GetInstanceScript(InstanceMap* map) const + { + return new instance_halls_of_reflection_InstanceMapScript(map); + } }; void AddSC_instance_halls_of_reflection() diff --git a/src/server/scripts/Northrend/Gundrak/gundrak.h b/src/server/scripts/Northrend/Gundrak/gundrak.h index 0c65b4d16de..a43edb4fcd7 100644 --- a/src/server/scripts/Northrend/Gundrak/gundrak.h +++ b/src/server/scripts/Northrend/Gundrak/gundrak.h @@ -43,12 +43,31 @@ enum Data64 enum mainCreatures { - CREATURE_RUIN_DWELLER = 29920, - CREATURE_SLAD_RAN = 29304, - CREATURE_MOORABI = 29305, - CREATURE_GALDARAH = 29306, - CREATURE_DRAKKARICOLOSSUS = 29307, - CREATURE_ECK = 29932 + CREATURE_RUIN_DWELLER = 29920, + CREATURE_SLAD_RAN = 29304, + CREATURE_MOORABI = 29305, + CREATURE_GALDARAH = 29306, + CREATURE_DRAKKARICOLOSSUS = 29307, + CREATURE_ECK = 29932 +}; + +enum Gameobjects { + + GO_SLADRAN_ALTAR = 192518, + GO_MOORABI_ALTAR = 192519, + GO_DRAKKARI_COLOSSUS_ALTAR = 192520, + GO_SLADRAN_STATUE = 192564, + GO_MOORABI_STATUE = 192565, + GO_GALDARAH_STATUE = 192566, + GO_DRAKKARI_COLOSSUS_STATUE = 192567, + GO_ECK_THE_FEROCIOUS_DOOR = 192632, + GO_ECK_THE_FEROCIOUS_DOOR_BEHIND = 192569, + GO_GALDARAH_DOOR1 = 193208, + GO_GALDARAH_DOOR2 = 193209, + GO_GALDARAH_DOOR3 = 192568, + GO_BRIDGE = 193188, + GO_COLLISION = 192633 + }; #endif diff --git a/src/server/scripts/Northrend/Gundrak/instance_gundrak.cpp b/src/server/scripts/Northrend/Gundrak/instance_gundrak.cpp index a9bbffa5fb0..d17198b0c92 100644 --- a/src/server/scripts/Northrend/Gundrak/instance_gundrak.cpp +++ b/src/server/scripts/Northrend/Gundrak/instance_gundrak.cpp @@ -45,44 +45,45 @@ public: { instance_gundrak_InstanceMapScript(Map* map) : InstanceScript(map) { - bHeroicMode = map->IsHeroic(); + isHeroic = map->IsHeroic(); } - bool bHeroicMode; + bool isHeroic; bool spawnSupport; uint32 timer; uint32 phase; uint64 toActivate; - uint64 uiSladRan; - uint64 uiMoorabi; - uint64 uiDrakkariColossus; - uint64 uiGalDarah; - uint64 uiEckTheFerocious; - - uint64 uiSladRanAltar; - uint64 uiMoorabiAltar; - uint64 uiDrakkariColossusAltar; - uint64 uiSladRanStatue; - uint64 uiMoorabiStatue; - uint64 uiDrakkariColossusStatue; - uint64 uiGalDarahStatue; - uint64 uiEckTheFerociousDoor; - uint64 uiEckTheFerociousDoorBehind; - uint64 uiGalDarahDoor1; - uint64 uiGalDarahDoor2; - uint64 uiBridge; - uint64 uiCollision; + uint64 sladRanGUID; + uint64 moorabiGUID; + uint64 drakkariColossusGUID; + uint64 galDarahGUID; + uint64 eckTheFerociousGUID; + + uint64 sladRanAltarGUID; + uint64 moorabiAltarGUID; + uint64 drakkariColossusAltarGUID; + uint64 sladRanStatueGUID; + uint64 moorabiStatueGUID; + uint64 drakkariColossusStatueGUID; + uint64 galDarahStatueGUID; + uint64 eckTheFerociousDoorGUID; + uint64 eckTheFerociousDoorBehindGUID; + uint64 galDarahDoor1GUID; + uint64 galDarahDoor2GUID; + uint64 galDarahDoor3GUID; + uint64 bridgeGUID; + uint64 collisionGUID; uint32 m_auiEncounter[MAX_ENCOUNTER]; - GOState uiSladRanStatueState; - GOState uiMoorabiStatueState; - GOState uiDrakkariColossusStatueState; - GOState uiGalDarahStatueState; - GOState uiBridgeState; - GOState uiCollisionState; + GOState sladRanStatueState; + GOState moorabiStatueState; + GOState drakkariColossusStatueState; + GOState galDarahStatueState; + GOState bridgeState; + GOState collisionState; std::set<uint64> DwellerGUIDs; @@ -96,35 +97,36 @@ public: phase = 0; toActivate = 0; - uiSladRan = 0; - uiMoorabi = 0; - uiDrakkariColossus = 0; - uiGalDarah = 0; - uiEckTheFerocious = 0; - - uiSladRanAltar = 0; - uiMoorabiAltar = 0; - uiDrakkariColossusAltar = 0; - - uiSladRanStatue = 0; - uiMoorabiStatue = 0; - uiDrakkariColossusStatue = 0; - uiGalDarahStatue = 0; - - uiEckTheFerociousDoor = 0; - uiEckTheFerociousDoorBehind = 0; - uiGalDarahDoor1 = 0; - uiGalDarahDoor2 = 0; - - uiBridge = 0; - uiCollision = 0; - - uiSladRanStatueState = GO_STATE_ACTIVE; - uiMoorabiStatueState = GO_STATE_ACTIVE; - uiDrakkariColossusStatueState = GO_STATE_ACTIVE; - uiGalDarahStatueState = GO_STATE_READY; - uiBridgeState = GO_STATE_ACTIVE; - uiCollisionState = GO_STATE_READY; + sladRanGUID = 0; + moorabiGUID = 0; + drakkariColossusGUID = 0; + galDarahGUID = 0; + eckTheFerociousGUID = 0; + + sladRanAltarGUID = 0; + moorabiAltarGUID = 0; + drakkariColossusAltarGUID = 0; + + sladRanStatueGUID = 0; + moorabiStatueGUID = 0; + drakkariColossusStatueGUID = 0; + galDarahStatueGUID = 0; + + eckTheFerociousDoorGUID = 0; + eckTheFerociousDoorBehindGUID = 0; + galDarahDoor1GUID = 0; + galDarahDoor2GUID = 0; + galDarahDoor3GUID = 0; + + bridgeGUID = 0; + collisionGUID = 0; + + sladRanStatueState = GO_STATE_ACTIVE; + moorabiStatueState = GO_STATE_ACTIVE; + drakkariColossusStatueState = GO_STATE_ACTIVE; + galDarahStatueState = GO_STATE_READY; + bridgeState = GO_STATE_ACTIVE; + collisionState = GO_STATE_READY; DwellerGUIDs.clear(); @@ -144,11 +146,21 @@ public: { switch (creature->GetEntry()) { - case CREATURE_SLAD_RAN: uiSladRan = creature->GetGUID(); break; - case CREATURE_MOORABI: uiMoorabi = creature->GetGUID(); break; - case CREATURE_GALDARAH: uiGalDarah = creature->GetGUID(); break; - case CREATURE_DRAKKARICOLOSSUS: uiDrakkariColossus = creature->GetGUID(); break; - case CREATURE_ECK: uiEckTheFerocious = creature->GetGUID(); break; + case CREATURE_SLAD_RAN: + sladRanGUID = creature->GetGUID(); + break; + case CREATURE_MOORABI: + moorabiGUID = creature->GetGUID(); + break; + case CREATURE_GALDARAH: + galDarahGUID = creature->GetGUID(); + break; + case CREATURE_DRAKKARICOLOSSUS: + drakkariColossusGUID = creature->GetGUID(); + break; + case CREATURE_ECK: + eckTheFerociousGUID = creature->GetGUID(); + break; case CREATURE_RUIN_DWELLER: if (creature->isAlive()) DwellerGUIDs.insert(creature->GetGUID()); @@ -160,13 +172,13 @@ public: { switch (go->GetEntry()) { - case 192518: - uiSladRanAltar = go->GetGUID(); + case GO_SLADRAN_ALTAR: + sladRanAltarGUID = go->GetGUID(); // Make sure that they start out as unusuable go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); if (m_auiEncounter[0] == DONE) { - if (uiSladRanStatueState == GO_STATE_ACTIVE) + if (sladRanStatueState == GO_STATE_ACTIVE) go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); else { @@ -175,13 +187,13 @@ public: } } break; - case 192519: - uiMoorabiAltar = go->GetGUID(); + case GO_MOORABI_ALTAR: + moorabiAltarGUID = go->GetGUID(); // Make sure that they start out as unusuable go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); if (m_auiEncounter[0] == DONE) { - if (uiMoorabiStatueState == GO_STATE_ACTIVE) + if (moorabiStatueState == GO_STATE_ACTIVE) go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); else { @@ -190,13 +202,13 @@ public: } } break; - case 192520: - uiDrakkariColossusAltar = go->GetGUID(); + case GO_DRAKKARI_COLOSSUS_ALTAR: + drakkariColossusAltarGUID = go->GetGUID(); // Make sure that they start out as unusuable go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); if (m_auiEncounter[0] == DONE) { - if (uiDrakkariColossusStatueState == GO_STATE_ACTIVE) + if (drakkariColossusStatueState == GO_STATE_ACTIVE) go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); else { @@ -205,53 +217,58 @@ public: } } break; - case 192564: - uiSladRanStatue = go->GetGUID(); - go->SetGoState(uiSladRanStatueState); + case GO_SLADRAN_STATUE: + sladRanStatueGUID = go->GetGUID(); + go->SetGoState(sladRanStatueState); break; - case 192565: - uiMoorabiStatue = go->GetGUID(); - go->SetGoState(uiMoorabiStatueState); + case GO_MOORABI_STATUE: + moorabiStatueGUID = go->GetGUID(); + go->SetGoState(moorabiStatueState); break; - case 192566: - uiGalDarahStatue = go->GetGUID(); - go->SetGoState(uiGalDarahStatueState); + case GO_GALDARAH_STATUE: + galDarahStatueGUID = go->GetGUID(); + go->SetGoState(galDarahStatueState); break; - case 192567: - uiDrakkariColossusStatue = go->GetGUID(); - go->SetGoState(uiDrakkariColossusStatueState); + case GO_DRAKKARI_COLOSSUS_STATUE: + drakkariColossusStatueGUID = go->GetGUID(); + go->SetGoState(drakkariColossusStatueState); break; - case 192632: - uiEckTheFerociousDoor = go->GetGUID(); - if (bHeroicMode && m_auiEncounter[1] == DONE) + case GO_ECK_THE_FEROCIOUS_DOOR: + eckTheFerociousDoorGUID = go->GetGUID(); + if (isHeroic && m_auiEncounter[1] == DONE) HandleGameObject(0, true, go); break; - case 192569: - uiEckTheFerociousDoorBehind = go->GetGUID(); - if (bHeroicMode && m_auiEncounter[4] == DONE) + case GO_ECK_THE_FEROCIOUS_DOOR_BEHIND: + eckTheFerociousDoorBehindGUID = go->GetGUID(); + if (isHeroic && m_auiEncounter[4] == DONE) HandleGameObject(0, true, go); - case 193208: - uiGalDarahDoor1 = go->GetGUID(); + case GO_GALDARAH_DOOR1: + galDarahDoor1GUID = go->GetGUID(); if (m_auiEncounter[3] == DONE) HandleGameObject(0, true, go); break; - case 193209: - uiGalDarahDoor2 = go->GetGUID(); + case GO_GALDARAH_DOOR2: + galDarahDoor2GUID = go->GetGUID(); if (m_auiEncounter[3] == DONE) HandleGameObject(0, true, go); break; - case 193188: - uiBridge = go->GetGUID(); - go->SetGoState(uiBridgeState); + case GO_BRIDGE: + bridgeGUID = go->GetGUID(); + go->SetGoState(bridgeState); break; - case 192633: - uiCollision = go->GetGUID(); - go->SetGoState(uiCollisionState); + case GO_COLLISION: + collisionGUID = go->GetGUID(); + go->SetGoState(collisionState); // Can't spawn here with SpawnGameObject because go isn't added to world yet... - if (uiCollisionState == GO_STATE_ACTIVE_ALTERNATIVE) + if (collisionState == GO_STATE_ACTIVE_ALTERNATIVE) spawnSupport = true; break; + case GO_GALDARAH_DOOR3: + galDarahDoor3GUID = go->GetGUID(); + if (m_auiEncounter[3] != IN_PROGRESS) + HandleGameObject(galDarahDoor3GUID, true, go); + break; } } @@ -263,7 +280,7 @@ public: m_auiEncounter[0] = data; if (data == DONE) { - GameObject* go = instance->GetGameObject(uiSladRanAltar); + GameObject* go = instance->GetGameObject(sladRanAltarGUID); if (go) go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); } @@ -272,18 +289,18 @@ public: m_auiEncounter[1] = data; if (data == DONE) { - GameObject* go = instance->GetGameObject(uiMoorabiAltar); + GameObject* go = instance->GetGameObject(moorabiAltarGUID); if (go) go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); - if (bHeroicMode) - HandleGameObject(uiEckTheFerociousDoor, true); + if (isHeroic) + HandleGameObject(eckTheFerociousDoorGUID, true); } break; case DATA_DRAKKARI_COLOSSUS_EVENT: m_auiEncounter[2] = data; if (data == DONE) { - GameObject* go = instance->GetGameObject(uiDrakkariColossusAltar); + GameObject* go = instance->GetGameObject(drakkariColossusAltarGUID); if (go) go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); } @@ -292,14 +309,15 @@ public: m_auiEncounter[3] = data; if (data == DONE) { - HandleGameObject(uiGalDarahDoor1, true); - HandleGameObject(uiGalDarahDoor2, true); + HandleGameObject(galDarahDoor1GUID, true); + HandleGameObject(galDarahDoor2GUID, true); } + HandleGameObject(galDarahDoor3GUID, data == IN_PROGRESS ? false : true); break; case DATA_ECK_THE_FEROCIOUS_EVENT: m_auiEncounter[4] = data; - if (bHeroicMode && data == DONE) - HandleGameObject(uiEckTheFerociousDoorBehind, true); + if (isHeroic && data == DONE) + HandleGameObject(eckTheFerociousDoorBehindGUID, true); break; } @@ -345,19 +363,19 @@ public: switch (type) { case DATA_SLAD_RAN_ALTAR: - return uiSladRanAltar; + return sladRanAltarGUID; case DATA_MOORABI_ALTAR: - return uiMoorabiAltar; + return moorabiAltarGUID; case DATA_DRAKKARI_COLOSSUS_ALTAR: - return uiDrakkariColossusAltar; + return drakkariColossusAltarGUID; case DATA_SLAD_RAN_STATUE: - return uiSladRanStatue; + return sladRanStatueGUID; case DATA_MOORABI_STATUE: - return uiMoorabiStatue; + return moorabiStatueGUID; case DATA_DRAKKARI_COLOSSUS_STATUE: - return uiDrakkariColossusStatue; + return drakkariColossusStatueGUID; case DATA_DRAKKARI_COLOSSUS: - return uiDrakkariColossus; + return drakkariColossusGUID; case DATA_STATUE_ACTIVATE: return toActivate; } @@ -372,9 +390,9 @@ public: std::ostringstream saveStream; saveStream << "G D " << m_auiEncounter[0] << ' ' << m_auiEncounter[1] << ' ' << m_auiEncounter[2] << ' ' << m_auiEncounter[3] << ' ' << m_auiEncounter[4] << ' ' - << (uiSladRanStatue ? GetObjState(uiSladRanStatue) : GO_STATE_ACTIVE) << ' ' << (uiMoorabiStatue ? GetObjState(uiMoorabiStatue) : GO_STATE_ACTIVE) << ' ' - << (uiDrakkariColossusStatue ? GetObjState(uiDrakkariColossusStatue) : GO_STATE_ACTIVE) << ' ' << (uiGalDarahStatue ? GetObjState(uiGalDarahStatue) : GO_STATE_READY) << ' ' - << (uiBridge ? GetObjState(uiBridge) : GO_STATE_ACTIVE) << ' ' << (uiCollision ? GetObjState(uiCollision) : GO_STATE_READY); + << (sladRanStatueGUID ? GetObjState(sladRanStatueGUID) : GO_STATE_ACTIVE) << ' ' << (moorabiStatueGUID ? GetObjState(moorabiStatueGUID) : GO_STATE_ACTIVE) << ' ' + << (drakkariColossusStatueGUID ? GetObjState(drakkariColossusStatueGUID) : GO_STATE_ACTIVE) << ' ' << (galDarahStatueGUID ? GetObjState(galDarahStatueGUID) : GO_STATE_READY) << ' ' + << (bridgeGUID ? GetObjState(bridgeGUID) : GO_STATE_ACTIVE) << ' ' << (collisionGUID ? GetObjState(collisionGUID) : GO_STATE_READY); str_data = saveStream.str(); @@ -406,12 +424,12 @@ public: m_auiEncounter[2] = data2; m_auiEncounter[3] = data3; m_auiEncounter[4] = data4; - uiSladRanStatueState = GOState(data5); - uiMoorabiStatueState = GOState(data6); - uiDrakkariColossusStatueState = GOState(data7); - uiGalDarahStatueState = GOState(data8); - uiBridgeState = GOState(data9); - uiCollisionState = GOState(data10); + sladRanStatueState = GOState(data5); + moorabiStatueState = GOState(data6); + drakkariColossusStatueState = GOState(data7); + galDarahStatueState = GOState(data8); + bridgeState = GOState(data9); + collisionState = GOState(data10); for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) if (m_auiEncounter[i] == IN_PROGRESS) @@ -426,8 +444,8 @@ public: // Spawn the support for the bridge if necessary if (spawnSupport) { - if (GameObject* pCollision = instance->GetGameObject(uiCollision)) - pCollision->SummonGameObject(192743, pCollision->GetPositionX(), pCollision->GetPositionY(), pCollision->GetPositionZ(), pCollision->GetOrientation(), 0, 0, 0, 0, 0); + if (GameObject* collision = instance->GetGameObject(collisionGUID)) + collision->SummonGameObject(192743, collision->GetPositionX(), collision->GetPositionY(), collision->GetPositionZ(), collision->GetOrientation(), 0, 0, 0, 0, 0); spawnSupport = false; } @@ -438,25 +456,25 @@ public: if (timer < diff) { timer = 0; - if (toActivate == uiBridge) + if (toActivate == bridgeGUID) { - GameObject* pBridge = instance->GetGameObject(uiBridge); - GameObject* pCollision = instance->GetGameObject(uiCollision); - GameObject* pSladRanStatue = instance->GetGameObject(uiSladRanStatue); - GameObject* pMoorabiStatue = instance->GetGameObject(uiMoorabiStatue); - GameObject* pDrakkariColossusStatue = instance->GetGameObject(uiDrakkariColossusStatue); - GameObject* pGalDarahStatue = instance->GetGameObject(uiGalDarahStatue); + GameObject* bridge = instance->GetGameObject(bridgeGUID); + GameObject* collision = instance->GetGameObject(collisionGUID); + GameObject* sladRanStatue = instance->GetGameObject(sladRanStatueGUID); + GameObject* moorabiStatue = instance->GetGameObject(moorabiStatueGUID); + GameObject* drakkariColossusStatue = instance->GetGameObject(drakkariColossusStatueGUID); + GameObject* galDarahStatue = instance->GetGameObject(galDarahStatueGUID); toActivate = 0; - if (pBridge && pCollision && pSladRanStatue && pMoorabiStatue && pDrakkariColossusStatue && pGalDarahStatue) + if (bridge && collision && sladRanStatue && moorabiStatue && drakkariColossusStatue && galDarahStatue) { - pBridge->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE); - pCollision->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE); - pSladRanStatue->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE); - pMoorabiStatue->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE); - pDrakkariColossusStatue->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE); - pGalDarahStatue->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE); + bridge->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE); + collision->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE); + sladRanStatue->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE); + moorabiStatue->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE); + drakkariColossusStatue->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE); + galDarahStatue->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE); // Add the GO that solidifies the bridge so you can walk on it spawnSupport = true; @@ -466,27 +484,27 @@ public: else { uint32 spell = 0; - GameObject* pAltar = NULL; - if (toActivate == uiSladRanStatue) + GameObject* altar = NULL; + if (toActivate == sladRanStatueGUID) { spell = 57071; - pAltar = instance->GetGameObject(uiSladRanAltar); + altar = instance->GetGameObject(sladRanAltarGUID); } - else if (toActivate == uiMoorabiStatue) + else if (toActivate == moorabiStatueGUID) { spell = 57068; - pAltar = instance->GetGameObject(uiMoorabiAltar); + altar = instance->GetGameObject(moorabiAltarGUID); } - else if (toActivate == uiDrakkariColossusStatue) + else if (toActivate == drakkariColossusStatueGUID) { spell = 57072; - pAltar = instance->GetGameObject(uiDrakkariColossusAltar); + altar = instance->GetGameObject(drakkariColossusAltarGUID); } // This is a workaround to make the beam cast properly. The caster should be ID 30298 but since the spells // all are with scripted target for that same ID, it will hit itself. - if (pAltar) - if (Creature* trigger = pAltar->SummonCreature(18721, pAltar->GetPositionX(), pAltar->GetPositionY(), pAltar->GetPositionZ() + 3, pAltar->GetOrientation(), TEMPSUMMON_CORPSE_DESPAWN, 5000)) + if (altar) + if (Creature* trigger = altar->SummonCreature(18721, altar->GetPositionX(), altar->GetPositionY(), altar->GetPositionZ() + 3, altar->GetOrientation(), TEMPSUMMON_CORPSE_DESPAWN, 5000)) { // Set the trigger model to invisible trigger->SetDisplayId(11686); @@ -499,7 +517,7 @@ public: toActivate = 0; if (phase == 3) - SetData64(DATA_STATUE_ACTIVATE, uiBridge); + SetData64(DATA_STATUE_ACTIVATE, bridgeGUID); else SaveToDB(); // Don't save in between last statue and bridge turning in case of crash leading to stuck instance } @@ -526,7 +544,7 @@ public: bool OnGossipHello(Player* /*player*/, GameObject* go) { InstanceScript* instance = go->GetInstanceScript(); - uint64 uiStatue = 0; + uint64 statueGUID = 0; go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); go->SetGoState(GO_STATE_ACTIVE); @@ -535,20 +553,20 @@ public: { switch (go->GetEntry()) { - case 192518: - uiStatue = instance->GetData64(DATA_SLAD_RAN_STATUE); + case GO_SLADRAN_ALTAR: + statueGUID = instance->GetData64(DATA_SLAD_RAN_STATUE); break; - case 192519: - uiStatue = instance->GetData64(DATA_MOORABI_STATUE); + case GO_MOORABI_ALTAR: + statueGUID = instance->GetData64(DATA_MOORABI_STATUE); break; - case 192520: - uiStatue = instance->GetData64(DATA_DRAKKARI_COLOSSUS_STATUE); + case GO_DRAKKARI_COLOSSUS_ALTAR: + statueGUID = instance->GetData64(DATA_DRAKKARI_COLOSSUS_STATUE); break; } if (!instance->GetData64(DATA_STATUE_ACTIVATE)) { - instance->SetData64(DATA_STATUE_ACTIVATE, uiStatue); + instance->SetData64(DATA_STATUE_ACTIVATE, statueGUID); go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); go->SetGoState(GO_STATE_ACTIVE); } diff --git a/src/server/scripts/Spells/spell_quest.cpp b/src/server/scripts/Spells/spell_quest.cpp index 3036c52876d..4cc464af9ab 100644 --- a/src/server/scripts/Spells/spell_quest.cpp +++ b/src/server/scripts/Spells/spell_quest.cpp @@ -1640,6 +1640,37 @@ class spell_q13291_q13292_q13239_q13261_armored_decoy_summon_skytalon : public S } }; +class spell_q12847_summon_soul_moveto_bunny : public SpellScriptLoader +{ + public: + spell_q12847_summon_soul_moveto_bunny() : SpellScriptLoader("spell_q12847_summon_soul_moveto_bunny") { } + + class spell_q12847_summon_soul_moveto_bunny_SpellScript : public SpellScript + { + PrepareSpellScript(spell_q12847_summon_soul_moveto_bunny_SpellScript); + + void ChangeSummonPos(SpellEffIndex /*effIndex*/) + { + // Adjust effect summon position + WorldLocation summonPos = *GetExplTargetDest(); + Position offset = { 0.0f, 0.0f, 2.5f, 0.0f }; + summonPos.RelocateOffset(offset); + SetExplTargetDest(summonPos); + GetHitDest()->RelocateOffset(offset); + } + + void Register() + { + OnEffectHit += SpellEffectFn(spell_q12847_summon_soul_moveto_bunny_SpellScript::ChangeSummonPos, EFFECT_0, SPELL_EFFECT_SUMMON); + } + }; + + SpellScript *GetSpellScript() const + { + return new spell_q12847_summon_soul_moveto_bunny_SpellScript(); + } +}; + void AddSC_quest_spell_scripts() { new spell_q55_sacred_cleansing(); @@ -1680,4 +1711,5 @@ void AddSC_quest_spell_scripts() new spell_q12527_zuldrak_rat(); new spell_q13291_q13292_q13239_q13261_frostbrood_skytalon_grab_decoy(); new spell_q13291_q13292_q13239_q13261_armored_decoy_summon_skytalon(); + new spell_q12847_summon_soul_moveto_bunny(); } diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.cpp b/src/server/shared/Database/Implementation/CharacterDatabase.cpp index 9704b709959..4fb9c763f16 100644 --- a/src/server/shared/Database/Implementation/CharacterDatabase.cpp +++ b/src/server/shared/Database/Implementation/CharacterDatabase.cpp @@ -319,6 +319,7 @@ void CharacterDatabaseConnection::DoPrepareStatements() PrepareStatement(CHAR_UPD_ARENA_TEAM_MEMBER, "UPDATE arena_team_member SET personalRating = ?, weekGames = ?, weekWins = ?, seasonGames = ?, seasonWins = ? WHERE arenaTeamId = ? AND guid = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_REP_CHARACTER_ARENA_STATS, "REPLACE INTO character_arena_stats (guid, slot, matchMakerRating) VALUES (?, ?, ?)", CONNECTION_ASYNC); PrepareStatement(CHAR_SEL_PLAYER_ARENA_TEAMS, "SELECT arena_team_member.arenaTeamId FROM arena_team_member JOIN arena_team ON arena_team_member.arenaTeamId = arena_team.arenaTeamId WHERE guid = ?", CONNECTION_SYNCH); + PrepareStatement(CHAR_UPD_ARENA_TEAM_NAME, "UPDATE arena_team SET name = ? WHERE arenaTeamId = ?", CONNECTION_ASYNC); // Character battleground data PrepareStatement(CHAR_INS_PLAYER_BGDATA, "INSERT INTO character_battleground_data (guid, instanceId, team, joinX, joinY, joinZ, joinO, joinMapId, taxiStart, taxiEnd, mountSpell) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC); @@ -439,8 +440,12 @@ void CharacterDatabaseConnection::DoPrepareStatements() PrepareStatement(CHAR_SEL_CHAR_DEL_INFO_BY_NAME, "SELECT guid, deleteInfos_Name, deleteInfos_Account, deleteDate FROM characters WHERE deleteDate IS NOT NULL AND deleteInfos_Name LIKE CONCAT('%%', ?, '%%')", CONNECTION_SYNCH); PrepareStatement(CHAR_SEL_CHAR_DEL_INFO, "SELECT guid, deleteInfos_Name, deleteInfos_Account, deleteDate FROM characters WHERE deleteDate IS NOT NULL", CONNECTION_SYNCH); PrepareStatement(CHAR_SEL_CHARS_BY_ACCOUNT_ID, "SELECT guid FROM characters WHERE account = ?", CONNECTION_SYNCH); - PrepareStatement(CHAR_SEL_CHAR_PINFO, "SELECT totaltime, level, money, account, race, class, map, zone FROM characters WHERE guid = ?", CONNECTION_SYNCH); + PrepareStatement(CHAR_SEL_CHAR_PINFO, "SELECT totaltime, level, money, account, race, class, map, zone, gender, health, playerFlags FROM characters WHERE guid = ?", CONNECTION_SYNCH); PrepareStatement(CHAR_SEL_PINFO_BANS, "SELECT unbandate, bandate = unbandate, bannedby, banreason FROM character_banned WHERE guid = ? AND active ORDER BY bandate ASC LIMIT 1", CONNECTION_SYNCH); + //0: lowGUID + PrepareStatement(CHAR_SEL_PINFO_MAILS, "SELECT SUM(CASE WHEN (checked & 1) THEN 1 ELSE 0 END) AS 'readmail', COUNT(*) AS 'totalmail' FROM mail WHERE `receiver` = ?", CONNECTION_SYNCH); + //0: lowGUID + PrepareStatement(CHAR_SEL_PINFO_XP, "SELECT xp FROM characters WHERE guid = ?", CONNECTION_SYNCH); PrepareStatement(CHAR_SEL_CHAR_HOMEBIND, "SELECT mapId, zoneId, posX, posY, posZ FROM character_homebind WHERE guid = ?", CONNECTION_SYNCH); PrepareStatement(CHAR_SEL_CHAR_GUID_NAME_BY_ACC, "SELECT guid, name FROM characters WHERE account = ?", CONNECTION_SYNCH); PrepareStatement(CHAR_SEL_POOL_QUEST_SAVE, "SELECT quest_id FROM pool_quest_save WHERE pool_id = ?", CONNECTION_SYNCH); diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.h b/src/server/shared/Database/Implementation/CharacterDatabase.h index d9900d53f46..53c309f9ba0 100755 --- a/src/server/shared/Database/Implementation/CharacterDatabase.h +++ b/src/server/shared/Database/Implementation/CharacterDatabase.h @@ -268,6 +268,7 @@ enum CharacterDatabaseStatements CHAR_UPD_ARENA_TEAM_MEMBER, CHAR_REP_CHARACTER_ARENA_STATS, CHAR_SEL_PLAYER_ARENA_TEAMS, + CHAR_UPD_ARENA_TEAM_NAME, CHAR_SEL_PETITION, CHAR_SEL_PETITION_SIGNATURE, @@ -381,6 +382,8 @@ enum CharacterDatabaseStatements CHAR_SEL_CHARS_BY_ACCOUNT_ID, CHAR_SEL_CHAR_PINFO, + CHAR_SEL_PINFO_XP, + CHAR_SEL_PINFO_MAILS, CHAR_SEL_PINFO_BANS, CHAR_SEL_CHAR_HOMEBIND, CHAR_SEL_CHAR_GUID_NAME_BY_ACC, diff --git a/src/server/shared/Database/Implementation/LoginDatabase.cpp b/src/server/shared/Database/Implementation/LoginDatabase.cpp index 0118f637205..6113dd61d70 100644 --- a/src/server/shared/Database/Implementation/LoginDatabase.cpp +++ b/src/server/shared/Database/Implementation/LoginDatabase.cpp @@ -79,7 +79,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 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.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); diff --git a/src/server/shared/Database/Implementation/WorldDatabase.cpp b/src/server/shared/Database/Implementation/WorldDatabase.cpp index c6e520cfdde..75bafb571e9 100644 --- a/src/server/shared/Database/Implementation/WorldDatabase.cpp +++ b/src/server/shared/Database/Implementation/WorldDatabase.cpp @@ -91,4 +91,6 @@ void WorldDatabaseConnection::DoPrepareStatements() PrepareStatement(WORLD_INS_DISABLES, "INSERT INTO disables (entry, sourceType, flags, comment) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC); PrepareStatement(WORLD_SEL_DISABLES, "SELECT entry FROM disables WHERE entry = ? AND sourceType = ?", CONNECTION_SYNCH); PrepareStatement(WORLD_DEL_DISABLES, "DELETE FROM disables WHERE entry = ? AND sourceType = ?", CONNECTION_ASYNC); + // 0: uint8 + PrepareStatement(WORLD_SEL_REQ_XP, "SELECT xp_for_next_level FROM player_xp_for_level WHERE lvl = ?", CONNECTION_SYNCH); } diff --git a/src/server/shared/Database/Implementation/WorldDatabase.h b/src/server/shared/Database/Implementation/WorldDatabase.h index d8c3c69dbba..171627bb83a 100644 --- a/src/server/shared/Database/Implementation/WorldDatabase.h +++ b/src/server/shared/Database/Implementation/WorldDatabase.h @@ -112,6 +112,7 @@ enum WorldDatabaseStatements WORLD_SEL_DISABLES, WORLD_INS_DISABLES, WORLD_DEL_DISABLES, + WORLD_SEL_REQ_XP, MAX_WORLDDATABASE_STATEMENTS }; |