diff options
Diffstat (limited to 'src')
29 files changed, 437 insertions, 994 deletions
diff --git a/src/server/game/Chat/Chat.cpp b/src/server/game/Chat/Chat.cpp index 6f614994489..f05ce5bded9 100644 --- a/src/server/game/Chat/Chat.cpp +++ b/src/server/game/Chat/Chat.cpp @@ -982,7 +982,7 @@ uint32 ChatHandler::extractSpellIdFromLink(char* text) if (!idS) return 0; - uint32 id = (uint32)atol(idS); + uint32 id = atoul(idS); switch (type) { @@ -995,13 +995,10 @@ uint32 ChatHandler::extractSpellIdFromLink(char* text) if (!talentEntry) return 0; - int32 rank = param1_str ? (uint32)atol(param1_str) : 0; + uint32 rank = param1_str ? atol(param1_str) : 0u; if (rank >= MAX_TALENT_RANK) return 0; - if (rank < 0) - rank = 0; - return talentEntry->RankID[rank]; } case SPELL_LINK_ENCHANT: @@ -1009,7 +1006,7 @@ uint32 ChatHandler::extractSpellIdFromLink(char* text) return id; case SPELL_LINK_GLYPH: { - uint32 glyph_prop_id = param1_str ? (uint32)atol(param1_str) : 0; + uint32 glyph_prop_id = param1_str ? atoul(param1_str) : 0; GlyphPropertiesEntry const* glyphPropEntry = sGlyphPropertiesStore.LookupEntry(glyph_prop_id); if (!glyphPropEntry) @@ -1082,7 +1079,7 @@ ObjectGuid ChatHandler::extractGuidFromLink(char* text) } case SPELL_LINK_CREATURE: { - uint32 lowguid = (uint32)atol(idS); + uint32 lowguid = atoul(idS); if (CreatureData const* data = sObjectMgr->GetCreatureData(lowguid)) return ObjectGuid(HIGHGUID_UNIT, data->id, lowguid); @@ -1091,7 +1088,7 @@ ObjectGuid ChatHandler::extractGuidFromLink(char* text) } case SPELL_LINK_GAMEOBJECT: { - uint32 lowguid = (uint32)atol(idS); + uint32 lowguid = atoul(idS); if (GameObjectData const* data = sObjectMgr->GetGOData(lowguid)) return ObjectGuid(HIGHGUID_GAMEOBJECT, data->id, lowguid); diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index 4ffddde021c..6702815870f 100644 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -607,7 +607,7 @@ void Object::_LoadIntoDataField(std::string const& data, uint32 startOffset, uin for (uint32 index = 0; index < count; ++index) { - m_uint32Values[startOffset + index] = atol(tokens[index]); + m_uint32Values[startOffset + index] = atoul(tokens[index]); _changesMask.SetBit(startOffset + index); } } diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 048b2f8e9bb..04e6cb000f8 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -203,7 +203,7 @@ void PlayerTaxi::LoadTaxiMask(std::string const &data) for (Tokenizer::const_iterator iter = tokens.begin(); index < TaxiMaskSize && iter != tokens.end(); ++iter, ++index) { // load and set bits only for existing taxi nodes - m_taximask[index] = sTaxiNodesMask[index] & uint32(atol(*iter)); + m_taximask[index] = sTaxiNodesMask[index] & atoul(*iter); } } @@ -229,7 +229,7 @@ bool PlayerTaxi::LoadTaxiDestinationsFromString(const std::string& values, uint3 for (Tokenizer::const_iterator iter = Tokenizer.begin(); iter != Tokenizer.end(); ++iter) { - uint32 node = uint32(atol(*iter)); + uint32 node = atoul(*iter); AddTaxiDestination(node); } diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 9a4b7a347c8..beac32b0145 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -13852,7 +13852,7 @@ void CharmInfo::LoadPetActionBar(const std::string& data) // use unsigned cast to avoid sign negative format use at long-> ActiveStates (int) conversion ActiveStates type = ActiveStates(atol(*iter)); ++iter; - uint32 action = uint32(atol(*iter)); + uint32 action = atoul(*iter); PetActionBar[index].SetActionAndType(action, type); diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 9e31e901189..8dc117b3362 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -556,17 +556,17 @@ void ObjectMgr::LoadCreatureTemplateAddons() creatureAddon.auras.resize(tokens.size()); for (Tokenizer::const_iterator itr = tokens.begin(); itr != tokens.end(); ++itr) { - SpellInfo const* AdditionalSpellInfo = sSpellMgr->GetSpellInfo(uint32(atol(*itr))); + SpellInfo const* AdditionalSpellInfo = sSpellMgr->GetSpellInfo(atoul(*itr)); if (!AdditionalSpellInfo) { - TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) has wrong spell %u defined in `auras` field in `creature_template_addon`.", entry, uint32(atol(*itr))); + TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) has wrong spell %lu defined in `auras` field in `creature_template_addon`.", entry, atoul(*itr)); continue; } if (AdditionalSpellInfo->HasAura(SPELL_AURA_CONTROL_VEHICLE)) - TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) has SPELL_AURA_CONTROL_VEHICLE aura %u defined in `auras` field in `creature_template_addon`.", entry, uint32(atol(*itr))); + TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) has SPELL_AURA_CONTROL_VEHICLE aura %lu defined in `auras` field in `creature_template_addon`.", entry, atoul(*itr)); - creatureAddon.auras[i++] = uint32(atol(*itr)); + creatureAddon.auras[i++] = atoul(*itr); } if (creatureAddon.mount) @@ -1004,17 +1004,17 @@ void ObjectMgr::LoadCreatureAddons() creatureAddon.auras.resize(tokens.size()); for (Tokenizer::const_iterator itr = tokens.begin(); itr != tokens.end(); ++itr) { - SpellInfo const* AdditionalSpellInfo = sSpellMgr->GetSpellInfo(uint32(atol(*itr))); + SpellInfo const* AdditionalSpellInfo = sSpellMgr->GetSpellInfo(atoul(*itr)); if (!AdditionalSpellInfo) { - TC_LOG_ERROR("sql.sql", "Creature (GUID: %u) has wrong spell %u defined in `auras` field in `creature_addon`.", guid, uint32(atol(*itr))); + TC_LOG_ERROR("sql.sql", "Creature (GUID: %u) has wrong spell %lu defined in `auras` field in `creature_addon`.", guid, atoul(*itr)); continue; } if (AdditionalSpellInfo->HasAura(SPELL_AURA_CONTROL_VEHICLE)) - TC_LOG_ERROR("sql.sql", "Creature (GUID: %u) has SPELL_AURA_CONTROL_VEHICLE aura %u defined in `auras` field in `creature_addon`.", guid, uint32(atol(*itr))); + TC_LOG_ERROR("sql.sql", "Creature (GUID: %u) has SPELL_AURA_CONTROL_VEHICLE aura %lu defined in `auras` field in `creature_addon`.", guid, atoul(*itr)); - creatureAddon.auras[i++] = uint32(atol(*itr)); + creatureAddon.auras[i++] = atoul(*itr); } if (creatureAddon.mount) @@ -5673,35 +5673,32 @@ void ObjectMgr::LoadAreaTriggerScripts() uint32 oldMSTime = getMSTime(); _areaTriggerScriptStore.clear(); // need for reload case - QueryResult result = WorldDatabase.Query("SELECT entry, ScriptName FROM areatrigger_scripts"); + QueryResult result = WorldDatabase.Query("SELECT entry, ScriptName FROM areatrigger_scripts"); if (!result) { TC_LOG_INFO("server.loading", ">> Loaded 0 areatrigger scripts. DB table `areatrigger_scripts` is empty."); return; } - uint32 count = 0; - do { - ++count; - Field* fields = result->Fetch(); - uint32 Trigger_ID = fields[0].GetUInt32(); - const char *scriptName = fields[1].GetCString(); + uint32 triggerId = fields[0].GetUInt32(); + char const* scriptName = fields[1].GetCString(); - AreaTriggerEntry const* atEntry = sAreaTriggerStore.LookupEntry(Trigger_ID); + AreaTriggerEntry const* atEntry = sAreaTriggerStore.LookupEntry(triggerId); if (!atEntry) { - TC_LOG_ERROR("sql.sql", "Area trigger (ID:%u) does not exist in `AreaTrigger.dbc`.", Trigger_ID); + TC_LOG_ERROR("sql.sql", "AreaTrigger (ID: %u) does not exist in `AreaTrigger.dbc`.", triggerId); continue; } - _areaTriggerScriptStore[Trigger_ID] = GetScriptId(scriptName); - } while (result->NextRow()); + _areaTriggerScriptStore[triggerId] = GetScriptId(scriptName); + } + while (result->NextRow()); - TC_LOG_INFO("server.loading", ">> Loaded %u areatrigger scripts in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); + TC_LOG_INFO("server.loading", ">> Loaded " SZFMTD " areatrigger scripts in %u ms", _areaTriggerScriptStore.size(), GetMSTimeDiffToNow(oldMSTime)); } uint32 ObjectMgr::GetNearestTaxiNode(float x, float y, float z, uint32 mapid, uint32 team) @@ -8544,31 +8541,32 @@ void ObjectMgr::LoadScriptNames() { uint32 oldMSTime = getMSTime(); - _scriptNamesStore.push_back(""); + _scriptNamesStore.emplace_back(""); + QueryResult result = WorldDatabase.Query( - "SELECT DISTINCT(ScriptName) FROM achievement_criteria_data WHERE ScriptName <> '' AND type = 11 " - "UNION " - "SELECT DISTINCT(ScriptName) FROM battleground_template WHERE ScriptName <> '' " - "UNION " - "SELECT DISTINCT(ScriptName) FROM creature_template WHERE ScriptName <> '' " - "UNION " - "SELECT DISTINCT(ScriptName) FROM gameobject_template WHERE ScriptName <> '' " - "UNION " - "SELECT DISTINCT(ScriptName) FROM item_template WHERE ScriptName <> '' " - "UNION " - "SELECT DISTINCT(ScriptName) FROM areatrigger_scripts WHERE ScriptName <> '' " - "UNION " - "SELECT DISTINCT(ScriptName) FROM spell_script_names WHERE ScriptName <> '' " - "UNION " - "SELECT DISTINCT(ScriptName) FROM transports WHERE ScriptName <> '' " - "UNION " - "SELECT DISTINCT(ScriptName) FROM game_weather WHERE ScriptName <> '' " - "UNION " - "SELECT DISTINCT(ScriptName) FROM conditions WHERE ScriptName <> '' " - "UNION " - "SELECT DISTINCT(ScriptName) FROM outdoorpvp_template WHERE ScriptName <> '' " - "UNION " - "SELECT DISTINCT(script) FROM instance_template WHERE script <> ''"); + "SELECT DISTINCT(ScriptName) FROM achievement_criteria_data WHERE ScriptName <> '' AND type = 11 " + "UNION " + "SELECT DISTINCT(ScriptName) FROM battleground_template WHERE ScriptName <> '' " + "UNION " + "SELECT DISTINCT(ScriptName) FROM creature_template WHERE ScriptName <> '' " + "UNION " + "SELECT DISTINCT(ScriptName) FROM gameobject_template WHERE ScriptName <> '' " + "UNION " + "SELECT DISTINCT(ScriptName) FROM item_template WHERE ScriptName <> '' " + "UNION " + "SELECT DISTINCT(ScriptName) FROM areatrigger_scripts WHERE ScriptName <> '' " + "UNION " + "SELECT DISTINCT(ScriptName) FROM spell_script_names WHERE ScriptName <> '' " + "UNION " + "SELECT DISTINCT(ScriptName) FROM transports WHERE ScriptName <> '' " + "UNION " + "SELECT DISTINCT(ScriptName) FROM game_weather WHERE ScriptName <> '' " + "UNION " + "SELECT DISTINCT(ScriptName) FROM conditions WHERE ScriptName <> '' " + "UNION " + "SELECT DISTINCT(ScriptName) FROM outdoorpvp_template WHERE ScriptName <> '' " + "UNION " + "SELECT DISTINCT(script) FROM instance_template WHERE script <> ''"); if (!result) { @@ -8576,20 +8574,23 @@ void ObjectMgr::LoadScriptNames() return; } - uint32 count = 1; - do { - _scriptNamesStore.push_back((*result)[0].GetString()); - ++count; + _scriptNamesStore.emplace_back((*result)[0].GetCString()); } while (result->NextRow()); std::sort(_scriptNamesStore.begin(), _scriptNamesStore.end()); - TC_LOG_INFO("server.loading", ">> Loaded %d Script Names in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); + +#ifdef SCRIPTS + for (size_t i = 1; i < _scriptNamesStore.size(); ++i) + UnusedScriptNames.push_back(_scriptNamesStore[i]); +#endif + + TC_LOG_INFO("server.loading", ">> Loaded " SZFMTD " ScriptNames in %u ms", _scriptNamesStore.size(), GetMSTimeDiffToNow(oldMSTime)); } -uint32 ObjectMgr::GetScriptId(const char *name) +uint32 ObjectMgr::GetScriptId(char const* name) { // use binary search to find the script name in the sorted vector // assume "" is the first element diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h index 62303143202..7504f03868e 100644 --- a/src/server/game/Globals/ObjectMgr.h +++ b/src/server/game/Globals/ObjectMgr.h @@ -1253,9 +1253,8 @@ class ObjectMgr bool IsVendorItemValid(uint32 vendor_entry, uint32 item, int32 maxcount, uint32 ptime, uint32 ExtendedCost, Player* player = NULL, std::set<uint32>* skip_vendors = NULL, uint32 ORnpcflag = 0) const; void LoadScriptNames(); - ScriptNameContainer &GetScriptNames() { return _scriptNamesStore; } - const char * GetScriptName(uint32 id) const { return id < _scriptNamesStore.size() ? _scriptNamesStore[id].c_str() : ""; } - uint32 GetScriptId(const char *name); + char const* GetScriptName(uint32 id) const { return id < _scriptNamesStore.size() ? _scriptNamesStore[id].c_str() : ""; } + uint32 GetScriptId(char const* name); SpellClickInfoMapBounds GetSpellClickInfoMapBounds(uint32 creature_id) const { diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index 18cd5d5bd06..7e218b601e0 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -2004,7 +2004,7 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recvData) } for (uint32 index = 0; index < ktcount; ++index) - knownTitles[index] = atol(tokens[index]); + knownTitles[index] = atoul(tokens[index]); for (std::map<uint32, uint32>::const_iterator it = sObjectMgr->FactionChangeTitles.begin(); it != sObjectMgr->FactionChangeTitles.end(); ++it) { diff --git a/src/server/game/Scripting/ScriptMgr.cpp b/src/server/game/Scripting/ScriptMgr.cpp index be0bf1aa067..d1ebcba118d 100644 --- a/src/server/game/Scripting/ScriptMgr.cpp +++ b/src/server/game/Scripting/ScriptMgr.cpp @@ -34,6 +34,12 @@ #include "WorldPacket.h" #include "WorldSession.h" +// namespace +// { + UnusedScriptContainer UnusedScripts; + UnusedScriptNamesContainer UnusedScriptNames; +// } + // This is the global static registry of scripts. template<class TScript> class ScriptRegistry @@ -89,6 +95,12 @@ class ScriptRegistry { ScriptPointerList[id] = script; sScriptMgr->IncrementScriptCount(); + + #ifdef SCRIPTS + UnusedScriptNamesContainer::iterator itr = std::lower_bound(UnusedScriptNames.begin(), UnusedScriptNames.end(), script->GetName()); + if (itr != UnusedScriptNames.end() && *itr == script->GetName()) + UnusedScriptNames.erase(itr); + #endif } else { @@ -106,8 +118,7 @@ class ScriptRegistry // Avoid calling "delete script;" because we are currently in the script constructor // In a valid scenario this will not happen because every script has a name assigned in the database - // If that happens, it's acceptable to just leak a few bytes - + UnusedScripts.push_back(script); return; } } @@ -189,6 +200,15 @@ void ScriptMgr::Initialize() FillSpellSummary(); AddScripts(); +#ifdef SCRIPTS + for (std::string const& scriptName : UnusedScriptNames) + { + TC_LOG_ERROR("sql.sql", "ScriptName '%s' exists in database, but no core script found!", scriptName.c_str()); + } +#endif + + UnloadUnusedScripts(); + TC_LOG_INFO("server.loading", ">> Loaded %u C++ scripts in %u ms", GetScriptCount(), GetMSTimeDiffToNow(oldMSTime)); } @@ -229,10 +249,19 @@ void ScriptMgr::Unload() #undef SCR_CLEAR + UnloadUnusedScripts(); + delete[] SpellSummary; delete[] UnitAI::AISpellInfo; } +void ScriptMgr::UnloadUnusedScripts() +{ + for (size_t i = 0; i < UnusedScripts.size(); ++i) + delete UnusedScripts[i]; + UnusedScripts.clear(); +} + void ScriptMgr::LoadDatabase() { sScriptSystemMgr->LoadScriptWaypoints(); diff --git a/src/server/game/Scripting/ScriptMgr.h b/src/server/game/Scripting/ScriptMgr.h index f6e76763f95..6a4e2f9910a 100644 --- a/src/server/game/Scripting/ScriptMgr.h +++ b/src/server/game/Scripting/ScriptMgr.h @@ -873,6 +873,15 @@ class GroupScript : public ScriptObject // Placed here due to ScriptRegistry::AddScript dependency. #define sScriptMgr ScriptMgr::instance() +// namespace +// { + typedef std::vector<ScriptObject*> UnusedScriptContainer; + typedef std::list<std::string> UnusedScriptNamesContainer; + + extern UnusedScriptContainer UnusedScripts; + extern UnusedScriptNamesContainer UnusedScriptNames; +// } + // Manages registration, loading, and execution of scripts. class ScriptMgr { @@ -901,6 +910,7 @@ class ScriptMgr public: /* Unloading */ void Unload(); + void UnloadUnusedScripts(); public: /* SpellScriptLoader */ diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp index 69297d32105..609617f0478 100644 --- a/src/server/game/Server/WorldSession.cpp +++ b/src/server/game/Server/WorldSession.cpp @@ -284,11 +284,7 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater) while (m_Socket && !_recvQueue.empty() && _recvQueue.peek(true) != firstDelayedPacket && _recvQueue.next(packet, updater)) { - if (!AntiDOS.EvaluateOpcode(*packet, currentTime)) - { - KickPlayer(); - } - else if (packet->GetOpcode() >= NUM_MSG_TYPES) + if (packet->GetOpcode() >= NUM_MSG_TYPES) { TC_LOG_ERROR("network.opcode", "Received non-existed opcode %s from %s", GetOpcodeNameForLogging(packet->GetOpcode()).c_str() , GetPlayerInfo().c_str()); @@ -320,7 +316,7 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater) "Player is currently not in world yet.", GetOpcodeNameForLogging(packet->GetOpcode()).c_str()); } } - else if (_player->IsInWorld()) + else if (_player->IsInWorld() && AntiDOS.EvaluateOpcode(*packet, currentTime)) { sScriptMgr->OnPacketReceive(this, *packet); (this->*opHandle.handler)(*packet); @@ -332,7 +328,7 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater) if (!_player && !m_playerRecentlyLogout && !m_playerLogout) // There's a short delay between _player = null and m_playerRecentlyLogout = true during logout LogUnexpectedOpcode(packet, "STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT", "the player has not logged in yet and not recently logout"); - else + else if (AntiDOS.EvaluateOpcode(*packet, currentTime)) { // not expected _player or must checked in packet handler sScriptMgr->OnPacketReceive(this, *packet); @@ -345,7 +341,7 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater) LogUnexpectedOpcode(packet, "STATUS_TRANSFER", "the player has not logged in yet"); else if (_player->IsInWorld()) LogUnexpectedOpcode(packet, "STATUS_TRANSFER", "the player is still in world"); - else + else if(AntiDOS.EvaluateOpcode(*packet, currentTime)) { sScriptMgr->OnPacketReceive(this, *packet); (this->*opHandle.handler)(*packet); @@ -365,9 +361,12 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater) if (packet->GetOpcode() == CMSG_CHAR_ENUM) m_playerRecentlyLogout = false; - sScriptMgr->OnPacketReceive(this, *packet); - (this->*opHandle.handler)(*packet); - LogUnprocessedTail(packet); + if (AntiDOS.EvaluateOpcode(*packet, currentTime)) + { + sScriptMgr->OnPacketReceive(this, *packet); + (this->*opHandle.handler)(*packet); + LogUnprocessedTail(packet); + } break; case STATUS_NEVER: TC_LOG_ERROR("network.opcode", "Received not allowed opcode %s from %s", GetOpcodeNameForLogging(packet->GetOpcode()).c_str() @@ -1262,8 +1261,11 @@ bool WorldSession::DosProtection::EvaluateOpcode(WorldPacket& p, time_t time) co case POLICY_LOG: return true; case POLICY_KICK: + { TC_LOG_INFO("network", "AntiDOS: Player kicked!"); + Session->KickPlayer(); return false; + } case POLICY_BAN: { BanMode bm = (BanMode)sWorld->getIntConfig(CONFIG_PACKET_SPOOF_BANMODE); @@ -1277,7 +1279,7 @@ bool WorldSession::DosProtection::EvaluateOpcode(WorldPacket& p, time_t time) co } sWorld->BanAccount(bm, nameOrIp, duration, "DOS (Packet Flooding/Spoofing", "Server: AutoDOS"); TC_LOG_INFO("network", "AntiDOS: Player automatically banned for %u seconds.", duration); - + Session->KickPlayer(); return false; } default: // invalid policy diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 311182291c5..e85fbba104b 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -3438,7 +3438,7 @@ void Spell::SendSpellCooldown() { // Handle pet cooldowns here if needed instead of in PetAI to avoid hidden cooldown restarts Creature* _creature = m_caster->ToCreature(); - if (_creature && _creature->IsPet()) + if (_creature && (_creature->IsPet() || _creature->IsGuardian())) _creature->AddCreatureSpellCooldown(m_spellInfo->Id); return; diff --git a/src/server/game/Tools/PlayerDump.cpp b/src/server/game/Tools/PlayerDump.cpp index 584331ad393..136f8aab22c 100644 --- a/src/server/game/Tools/PlayerDump.cpp +++ b/src/server/game/Tools/PlayerDump.cpp @@ -527,10 +527,10 @@ DumpReturn PlayerDumpReader::LoadDump(std::string const& file, uint32 account, s if (!changenth(line, 2, chraccount)) // characters.account update ROLLBACK(DUMP_FILE_BROKEN); - race = uint8(atol(getnth(line, 4).c_str())); - playerClass = uint8(atol(getnth(line, 5).c_str())); - gender = uint8(atol(getnth(line, 6).c_str())); - level = uint8(atol(getnth(line, 7).c_str())); + race = uint8(atoul(getnth(line, 4).c_str())); + playerClass = uint8(atoul(getnth(line, 5).c_str())); + gender = uint8(atoul(getnth(line, 6).c_str())); + level = uint8(atoul(getnth(line, 7).c_str())); if (name.empty()) { // check if the original name already exists diff --git a/src/server/scripts/Commands/cs_debug.cpp b/src/server/scripts/Commands/cs_debug.cpp index d3d012e70d5..2eebc9cae10 100644 --- a/src/server/scripts/Commands/cs_debug.cpp +++ b/src/server/scripts/Commands/cs_debug.cpp @@ -488,7 +488,7 @@ public: static bool HandleDebugSendQuestPartyMsgCommand(ChatHandler* handler, char const* args) { - uint32 msg = atol((char*)args); + uint32 msg = atoul(args); handler->GetSession()->GetPlayer()->SendPushToPartyResponse(handler->GetSession()->GetPlayer(), msg); return true; } @@ -507,7 +507,7 @@ public: static bool HandleDebugSendQuestInvalidMsgCommand(ChatHandler* handler, char const* args) { - QuestFailedReason msg = static_cast<QuestFailedReason>(atol((char*)args)); + QuestFailedReason msg = static_cast<QuestFailedReason>(atoul(args)); handler->GetSession()->GetPlayer()->SendCanTakeQuestResponse(msg); return true; } diff --git a/src/server/scripts/Commands/cs_gobject.cpp b/src/server/scripts/Commands/cs_gobject.cpp index f3ddc6f0137..c0bf2a6bb84 100644 --- a/src/server/scripts/Commands/cs_gobject.cpp +++ b/src/server/scripts/Commands/cs_gobject.cpp @@ -118,7 +118,7 @@ public: if (!id) return false; - uint32 objectId = atol(id); + uint32 objectId = atoul(id); if (!objectId) return false; @@ -238,7 +238,7 @@ public: if (!id) return false; - uint32 objectId = atol(id); + uint32 objectId = atoul(id); if (objectId) result = WorldDatabase.PQuery("SELECT guid, id, position_x, position_y, position_z, orientation, map, phaseMask, (POW(position_x - '%f', 2) + POW(position_y - '%f', 2) + POW(position_z - '%f', 2)) AS order_ FROM gameobject WHERE map = '%i' AND id = '%u' ORDER BY order_ ASC LIMIT 1", diff --git a/src/server/scripts/Commands/cs_group.cpp b/src/server/scripts/Commands/cs_group.cpp index a558d977b85..06967c69888 100644 --- a/src/server/scripts/Commands/cs_group.cpp +++ b/src/server/scripts/Commands/cs_group.cpp @@ -269,7 +269,7 @@ public: const char* onlineState = ""; // Parse the guid to uint32... - ObjectGuid parseGUID(HIGHGUID_PLAYER, uint32(atol((char*)args))); + ObjectGuid parseGUID(HIGHGUID_PLAYER, uint32(atoul(args))); // ... and try to extract a player out of it. if (sObjectMgr->GetPlayerNameByGUID(parseGUID, nameTarget)) diff --git a/src/server/scripts/Commands/cs_list.cpp b/src/server/scripts/Commands/cs_list.cpp index 0f21200c22d..b57629a577e 100644 --- a/src/server/scripts/Commands/cs_list.cpp +++ b/src/server/scripts/Commands/cs_list.cpp @@ -65,7 +65,7 @@ public: if (!id) return false; - uint32 creatureId = atol(id); + uint32 creatureId = atoul(id); if (!creatureId) { handler->PSendSysMessage(LANG_COMMAND_INVALIDCREATUREID, creatureId); @@ -82,7 +82,7 @@ public: } char* countStr = strtok(NULL, " "); - uint32 count = countStr ? atol(countStr) : 10; + uint32 count = countStr ? atoul(countStr) : 10; if (count == 0) return false; @@ -133,11 +133,11 @@ public: if (!*args) return false; - char* id = handler->extractKeyFromLink((char*)args, "Hitem"); + char const* id = handler->extractKeyFromLink((char*)args, "Hitem"); if (!id) return false; - uint32 itemId = atol(id); + uint32 itemId = atoul(id); if (!itemId) { handler->PSendSysMessage(LANG_COMMAND_ITEMIDINVALID, itemId); @@ -154,7 +154,7 @@ public: } char* countStr = strtok(NULL, " "); - uint32 count = countStr ? atol(countStr) : 10; + uint32 count = countStr ? atoul(countStr) : 10; if (count == 0) return false; @@ -354,7 +354,7 @@ public: if (!id) return false; - uint32 gameObjectId = atol(id); + uint32 gameObjectId = atoul(id); if (!gameObjectId) { handler->PSendSysMessage(LANG_COMMAND_LISTOBJINVALIDID, gameObjectId); @@ -371,7 +371,7 @@ public: } char* countStr = strtok(NULL, " "); - uint32 count = countStr ? atol(countStr) : 10; + uint32 count = countStr ? atoul(countStr) : 10; if (count == 0) return false; @@ -476,7 +476,7 @@ public: if (!*args) return false; - ObjectGuid parseGUID(HIGHGUID_PLAYER, uint32(atol((char*)args))); + ObjectGuid parseGUID(HIGHGUID_PLAYER, uint32(atoul(args))); if (sObjectMgr->GetPlayerNameByGUID(parseGUID, targetName)) { diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp index a853a02bb11..2f2891b42ab 100644 --- a/src/server/scripts/Commands/cs_misc.cpp +++ b/src/server/scripts/Commands/cs_misc.cpp @@ -1134,7 +1134,7 @@ public: char const* id = handler->extractKeyFromLink((char*)args, "Hitem"); if (!id) return false; - itemId = uint32(atol(id)); + itemId = atoul(id); } char const* ccount = strtok(NULL, " "); @@ -1216,7 +1216,7 @@ public: if (!id) return false; - uint32 itemSetId = atol(id); + uint32 itemSetId = atoul(id); // prevent generation all items with itemset field value '0' if (itemSetId == 0) @@ -1357,7 +1357,7 @@ public: return false; } - int32 level = uint32(atol(levelStr)); + int32 level = atol(levelStr); Player* target = handler->getSelectedPlayer(); if (!target) @@ -1379,7 +1379,7 @@ public: // If our target does not yet have the skill they are trying to add to them, the chosen level also becomes // the max level of the new profession. - uint16 max = maxPureSkill ? atol (maxPureSkill) : targetHasSkill ? target->GetPureMaxSkillValue(skill) : uint16(level); + uint16 max = maxPureSkill ? atoul(maxPureSkill) : targetHasSkill ? target->GetPureMaxSkillValue(skill) : uint16(level); if (level <= 0 || level > max || max <= 0) return false; @@ -1419,7 +1419,7 @@ public: PreparedStatement* stmt = NULL; // To make sure we get a target, we convert our guid to an omniversal... - ObjectGuid parseGUID(HIGHGUID_PLAYER, uint32(atol((char*)args))); + ObjectGuid parseGUID(HIGHGUID_PLAYER, uint32(atoul(args))); // ... and make sure we get a target, somehow. if (sObjectMgr->GetPlayerNameByGUID(parseGUID, targetName)) @@ -1780,7 +1780,7 @@ public: uint32 totalmail = uint32(fields[1].GetUInt64()); // ... we have to convert it from Char to int. We can use totalmail as it is - rmailint = atol(readmail.c_str()); + rmailint = atoul(readmail.c_str()); // Output XXI. LANG_INFO_CHR_MAILS if at least one mail is given if (totalmail >= 1) diff --git a/src/server/scripts/Commands/cs_npc.cpp b/src/server/scripts/Commands/cs_npc.cpp index 987c12debb7..1434493e948 100644 --- a/src/server/scripts/Commands/cs_npc.cpp +++ b/src/server/scripts/Commands/cs_npc.cpp @@ -326,15 +326,15 @@ public: char* fmaxcount = strtok(NULL, " "); //add maxcount, default: 0 uint32 maxcount = 0; if (fmaxcount) - maxcount = atol(fmaxcount); + maxcount = atoul(fmaxcount); char* fincrtime = strtok(NULL, " "); //add incrtime, default: 0 uint32 incrtime = 0; if (fincrtime) - incrtime = atol(fincrtime); + incrtime = atoul(fincrtime); char* fextendedcost = strtok(NULL, " "); //add ExtendedCost, default: 0 - uint32 extendedcost = fextendedcost ? atol(fextendedcost) : 0; + uint32 extendedcost = fextendedcost ? atoul(fextendedcost) : 0; Creature* vendor = handler->getSelectedCreature(); if (!vendor) { @@ -564,7 +564,7 @@ public: handler->SetSentErrorMessage(true); return false; } - uint32 itemId = atol(pitem); + uint32 itemId = atoul(pitem); if (!sObjectMgr->RemoveVendorItem(vendor->GetEntry(), itemId)) { @@ -1321,7 +1321,7 @@ public: return false; } - ObjectGuid receiver_guid(HIGHGUID_PLAYER, uint32(atol(receiver_str))); + ObjectGuid receiver_guid(HIGHGUID_PLAYER, uint32(atoul(receiver_str))); // check online security Player* receiver = ObjectAccessor::FindPlayer(receiver_guid); diff --git a/src/server/scripts/Commands/cs_quest.cpp b/src/server/scripts/Commands/cs_quest.cpp index fb486128049..9f7098b9134 100644 --- a/src/server/scripts/Commands/cs_quest.cpp +++ b/src/server/scripts/Commands/cs_quest.cpp @@ -67,7 +67,7 @@ public: if (!cId) return false; - uint32 entry = atol(cId); + uint32 entry = atoul(cId); Quest const* quest = sObjectMgr->GetQuestTemplate(entry); @@ -112,7 +112,7 @@ public: if (!cId) return false; - uint32 entry = atol(cId); + uint32 entry = atoul(cId); Quest const* quest = sObjectMgr->GetQuestTemplate(entry); @@ -165,7 +165,7 @@ public: if (!cId) return false; - uint32 entry = atol(cId); + uint32 entry = atoul(cId); Quest const* quest = sObjectMgr->GetQuestTemplate(entry); @@ -269,7 +269,7 @@ public: if (!cId) return false; - uint32 entry = atol(cId); + uint32 entry = atoul(cId); Quest const* quest = sObjectMgr->GetQuestTemplate(entry); diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_ragnaros.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_ragnaros.cpp index 58f38ec4267..860cc609c7b 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_ragnaros.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_ragnaros.cpp @@ -225,7 +225,7 @@ class boss_ragnaros : public CreatureScript events.ScheduleEvent(EVENT_ELEMENTAL_FIRE, urand(10000, 14000)); break; case EVENT_MAGMA_BLAST: - if (me->IsWithinMeleeRange(me->GetVictim())) + if (!me->IsWithinMeleeRange(me->GetVictim())) { DoCastVictim(SPELL_MAGMA_BLAST); if (!_hasYelledMagmaBurst) diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_archimonde.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_archimonde.cpp index 992b20d2580..a0ff40c8a3c 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_archimonde.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_archimonde.cpp @@ -66,12 +66,32 @@ enum Spells SPELL_FEAR = 31970, }; +enum Events +{ + EVENT_DRAIN_NORDRASSIL = 1, + EVENT_HAND_OF_DEATH, // Raid wiper + EVENT_UNLEASH_SOUL_CHARGE, + EVENT_FINGER_OF_DEATH, + EVENT_GRIP_OF_THE_LEGION, + EVENT_FEAR, + EVENT_AIR_BURST, + EVENT_DOOMFIRE, + EVENT_DISTANCE_CHECK, // This checks if he's too close to the World Tree (75 yards from a point on the tree), if true then he will enrage + EVENT_SUMMON_WHISP +}; + enum Summons { - CREATURE_DOOMFIRE = 18095, - CREATURE_DOOMFIRE_SPIRIT = 18104, - CREATURE_ANCIENT_WISP = 17946, - CREATURE_CHANNEL_TARGET = 22418, + NPC_DOOMFIRE = 18095, + NPC_DOOMFIRE_SPIRIT = 18104, + NPC_ANCIENT_WISP = 17946, + NPC_CHANNEL_TARGET = 22418 +}; + +enum Actions +{ + ACTION_ENRAGE, + ACTION_CHANNEL_WORLD_TREE }; Position const NordrassilLoc = {5503.713f, -3523.436f, 1608.781f, 0.0f}; @@ -249,409 +269,288 @@ class boss_archimonde : public CreatureScript public: boss_archimonde() : CreatureScript("boss_archimonde") { } - CreatureAI* GetAI(Creature* creature) const override - { - return GetInstanceAI<boss_archimondeAI>(creature); - } - - struct boss_archimondeAI : public hyjal_trashAI + struct boss_archimondeAI : public BossAI { - boss_archimondeAI(Creature* creature) : hyjal_trashAI(creature) + boss_archimondeAI(Creature* creature) : BossAI(creature, DATA_ARCHIMONDE) { Initialize(); - instance = creature->GetInstanceScript(); } void Initialize() { DoomfireSpiritGUID.Clear(); - damageTaken = 0; WorldTreeGUID.Clear(); - DrainNordrassilTimer = 0; - FearTimer = 42000; - AirBurstTimer = 30000; - GripOfTheLegionTimer = urand(5000, 25000); - DoomfireTimer = 20000; - SoulChargeTimer = urand(2000, 30000); SoulChargeCount = 0; - MeleeRangeCheckTimer = 15000; - HandOfDeathTimer = 2000; - WispCount = 0; // When ~30 wisps are summoned, Archimonde dies - EnrageTimer = 600000; // 10 minutes - CheckDistanceTimer = 30000; // This checks if he's too close to the World Tree (75 yards from a point on the tree), if true then he will enrage - SummonWispTimer = 0; + WispCount = 0; // When ~30 wisps are summoned, Archimonde dies + _unleashSpell = 0; + _chargeSpell = 0; Enraged = false; - BelowTenPercent = false; HasProtected = false; - IsChanneling = false; } - InstanceScript* instance; - - ObjectGuid DoomfireSpiritGUID; - ObjectGuid WorldTreeGUID; - - uint32 DrainNordrassilTimer; - uint32 FearTimer; - uint32 AirBurstTimer; - uint32 GripOfTheLegionTimer; - uint32 DoomfireTimer; - uint32 SoulChargeTimer; - uint8 SoulChargeCount; - uint32 MeleeRangeCheckTimer; - uint32 HandOfDeathTimer; - uint32 SummonWispTimer; - uint8 WispCount; - uint32 EnrageTimer; - uint32 CheckDistanceTimer; - - bool Enraged; - bool BelowTenPercent; - bool HasProtected; - bool IsChanneling; - void Reset() override { - instance->SetData(DATA_ARCHIMONDEEVENT, NOT_STARTED); - Initialize(); + _Reset(); + me->RemoveAllAuras(); // Reset Soul Charge auras. + if (!me->isMoving()) + DoAction(ACTION_CHANNEL_WORLD_TREE); } void EnterCombat(Unit* /*who*/) override { - me->InterruptSpell(CURRENT_CHANNELED_SPELL); Talk(SAY_AGGRO); - DoZoneInCombat(); - - instance->SetData(DATA_ARCHIMONDEEVENT, IN_PROGRESS); - } - - void KilledUnit(Unit* victim) override - { - Talk(SAY_SLAY); - - if (victim && victim->GetTypeId() == TYPEID_PLAYER) - GainSoulCharge(victim->ToPlayer()); + _EnterCombat(); + events.ScheduleEvent(EVENT_FEAR, 42000); + events.ScheduleEvent(EVENT_AIR_BURST, 30000); + events.ScheduleEvent(EVENT_GRIP_OF_THE_LEGION, urand(5000, 25000)); + events.ScheduleEvent(EVENT_DOOMFIRE, 20000); + events.ScheduleEvent(EVENT_UNLEASH_SOUL_CHARGE, urand(2000, 30000)); + events.ScheduleEvent(EVENT_FINGER_OF_DEATH, 15000); + events.ScheduleEvent(EVENT_HAND_OF_DEATH, 600000); + events.ScheduleEvent(EVENT_DISTANCE_CHECK, 30000); } - void GainSoulCharge(Player* victim) + void ExecuteEvent(uint32 eventId) override { - switch (victim->getClass()) + switch (eventId) { - case CLASS_PRIEST: - case CLASS_PALADIN: - case CLASS_WARLOCK: - victim->CastSpell(me, SPELL_SOUL_CHARGE_RED, true); + case EVENT_DRAIN_NORDRASSIL: + if (Unit* Nordrassil = ObjectAccessor::GetUnit(*me, WorldTreeGUID)) + Nordrassil->CastSpell(me, SPELL_DRAIN_WORLD_TREE_2, true); + events.ScheduleEvent(EVENT_DRAIN_NORDRASSIL, 1000); break; - case CLASS_MAGE: - case CLASS_ROGUE: - case CLASS_WARRIOR: - victim->CastSpell(me, SPELL_SOUL_CHARGE_YELLOW, true); + case EVENT_HAND_OF_DEATH: + DoCastAOE(SPELL_HAND_OF_DEATH); + events.ScheduleEvent(EVENT_HAND_OF_DEATH, 2000); break; - case CLASS_DRUID: - case CLASS_SHAMAN: - case CLASS_HUNTER: - victim->CastSpell(me, SPELL_SOUL_CHARGE_GREEN, true); + case EVENT_UNLEASH_SOUL_CHARGE: + _chargeSpell = 0; + _unleashSpell = 0; + me->InterruptNonMeleeSpells(false); + switch (urand(0, 2)) + { + case 0: + _chargeSpell = SPELL_SOUL_CHARGE_RED; + _unleashSpell = SPELL_UNLEASH_SOUL_RED; + break; + case 1: + _chargeSpell = SPELL_SOUL_CHARGE_YELLOW; + _unleashSpell = SPELL_UNLEASH_SOUL_YELLOW; + break; + case 2: + _chargeSpell = SPELL_SOUL_CHARGE_GREEN; + _unleashSpell = SPELL_UNLEASH_SOUL_GREEN; + break; + } + + if (me->HasAura(_chargeSpell)) + { + me->RemoveAuraFromStack(_chargeSpell); + DoCastVictim(_unleashSpell); + SoulChargeCount--; + events.ScheduleEvent(EVENT_UNLEASH_SOUL_CHARGE, urand(2000, 30000)); + } + break; + case EVENT_FINGER_OF_DEATH: + if (!SelectTarget(SELECT_TARGET_RANDOM, 0, 5.0f)) // Checks if there are no targets in melee range + { + DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0), SPELL_FINGER_OF_DEATH); + events.ScheduleEvent(EVENT_FINGER_OF_DEATH, 1000); + } + else + events.ScheduleEvent(EVENT_FINGER_OF_DEATH, 5000); + break; + case EVENT_GRIP_OF_THE_LEGION: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) + DoCast(target, SPELL_GRIP_OF_THE_LEGION); + events.ScheduleEvent(EVENT_GRIP_OF_THE_LEGION, urand(5000, 25000)); + break; + case EVENT_AIR_BURST: + Talk(SAY_AIR_BURST); + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1)) + DoCast(target, SPELL_AIR_BURST); //not on tank + events.ScheduleEvent(EVENT_AIR_BURST, urand(25000, 40000)); + break; + case EVENT_FEAR: + DoCastAOE(SPELL_FEAR); + events.ScheduleEvent(EVENT_FEAR, 42000); + break; + case EVENT_DOOMFIRE: + Talk(SAY_DOOMFIRE); + if (Unit* temp = SelectTarget(SELECT_TARGET_RANDOM, 1)) + SummonDoomfire(temp); + else + SummonDoomfire(me->GetVictim()); + events.ScheduleEvent(EVENT_DOOMFIRE, 20000); + break; + case EVENT_DISTANCE_CHECK: + if (Creature* channelTrigger = ObjectAccessor::GetCreature(*me, WorldTreeGUID)) + if (me->IsWithinDistInMap(channelTrigger, 75.0f)) + DoAction(ACTION_ENRAGE); + events.ScheduleEvent(EVENT_DISTANCE_CHECK, 5000); + break; + case EVENT_SUMMON_WHISP: + DoSpawnCreature(NPC_ANCIENT_WISP, float(rand32() % 40), float(rand32() % 40), 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + ++WispCount; + if (WispCount >= 30) + me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + events.ScheduleEvent(EVENT_SUMMON_WHISP, 1500); + break; + default: break; } - - SoulChargeTimer = urand(2000, 30000); - ++SoulChargeCount; - } - - void JustDied(Unit* killer) override - { - hyjal_trashAI::JustDied(killer); - Talk(SAY_DEATH); - - instance->SetData(DATA_ARCHIMONDEEVENT, DONE); } - bool CanUseFingerOfDeath() + void DamageTaken(Unit* /*attacker*/, uint32 &damage) override { - // First we check if our current victim is in melee range or not. - Unit* victim = me->GetVictim(); - if (victim && me->IsWithinDistInMap(victim, me->GetAttackDistance(victim))) - return false; - - ThreatContainer::StorageType const &threatlist = me->getThreatManager().getThreatList(); - if (threatlist.empty()) - return false; - - std::list<Unit*> targets; - ThreatContainer::StorageType::const_iterator itr = threatlist.begin(); - for (; itr != threatlist.end(); ++itr) + if (me->HealthBelowPctDamaged(10, damage)) { - Unit* unit = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid()); - if (unit && unit->IsAlive()) - targets.push_back(unit); - } + if (!Enraged) + DoAction(ACTION_ENRAGE); - if (targets.empty()) - return false; + if (!HasProtected) + { + me->GetMotionMaster()->Clear(false); + me->GetMotionMaster()->MoveIdle(); - targets.sort(Trinity::ObjectDistanceOrderPred(me)); - Unit* target = targets.front(); - if (target) - { - if (!me->IsWithinDistInMap(target, me->GetAttackDistance(target))) - return true; // Cast Finger of Death - else // This target is closest, he is our new tank - me->AddThreat(target, me->getThreatManager().getThreat(me->GetVictim())); + // All members of raid must get this buff + DoCastAOE(SPELL_PROTECTION_OF_ELUNE, true); + HasProtected = true; + events.ScheduleEvent(EVENT_SUMMON_WHISP, 1500); + } } - - return false; } - void JustSummoned(Creature* summoned) override + void KilledUnit(Unit* victim) override { - if (summoned->GetEntry() == CREATURE_ANCIENT_WISP) - summoned->AI()->AttackStart(me); - else - { - summoned->setFaction(me->getFaction()); - summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - } - - if (summoned->GetEntry() == CREATURE_DOOMFIRE_SPIRIT) - { - DoomfireSpiritGUID = summoned->GetGUID(); - } + Talk(SAY_SLAY); - if (summoned->GetEntry() == CREATURE_DOOMFIRE) + if (victim->GetTypeId() == TYPEID_PLAYER) { - summoned->CastSpell(summoned, SPELL_DOOMFIRE_SPAWN, false); - summoned->CastSpell(summoned, SPELL_DOOMFIRE, true, 0, 0, me->GetGUID()); - - if (Unit* DoomfireSpirit = ObjectAccessor::GetUnit(*me, DoomfireSpiritGUID)) + switch (victim->getClass()) { - summoned->GetMotionMaster()->MoveFollow(DoomfireSpirit, 0.0f, 0.0f); - DoomfireSpiritGUID.Clear(); + case CLASS_PRIEST: + case CLASS_PALADIN: + case CLASS_WARLOCK: + victim->CastSpell(me, SPELL_SOUL_CHARGE_RED, true); + break; + case CLASS_MAGE: + case CLASS_ROGUE: + case CLASS_WARRIOR: + victim->CastSpell(me, SPELL_SOUL_CHARGE_YELLOW, true); + break; + case CLASS_DRUID: + case CLASS_SHAMAN: + case CLASS_HUNTER: + victim->CastSpell(me, SPELL_SOUL_CHARGE_GREEN, true); + break; } + + events.ScheduleEvent(EVENT_UNLEASH_SOUL_CHARGE, urand(2000, 30000)); + ++SoulChargeCount; } } - //this is code doing close to what the summoning spell would do (spell 31903) - void SummonDoomfire(Unit* target) + void JustReachedHome() override { - me->SummonCreature(CREATURE_DOOMFIRE_SPIRIT, - target->GetPositionX()+15.0f, target->GetPositionY()+15.0f, target->GetPositionZ(), 0, - TEMPSUMMON_TIMED_DESPAWN, 27000); - - me->SummonCreature(CREATURE_DOOMFIRE, - target->GetPositionX()-15.0f, target->GetPositionY()-15.0f, target->GetPositionZ(), 0, - TEMPSUMMON_TIMED_DESPAWN, 27000); + DoAction(ACTION_CHANNEL_WORLD_TREE); } - void UnleashSoulCharge() + void JustDied(Unit* /*killer*/) override { - me->InterruptNonMeleeSpells(false); - - bool HasCast = false; - uint32 chargeSpell = 0; - uint32 unleashSpell = 0; + Talk(SAY_DEATH); + _JustDied(); + // @todo: remove this when instance script gets updated, kept for compatibility only + instance->SetData(DATA_ARCHIMONDE, DONE); + } - switch (urand(0, 2)) + void JustSummoned(Creature* summoned) override + { + switch (summoned->GetEntry()) { - case 0: - chargeSpell = SPELL_SOUL_CHARGE_RED; - unleashSpell = SPELL_UNLEASH_SOUL_RED; + case NPC_ANCIENT_WISP: + summoned->AI()->AttackStart(me); break; - case 1: - chargeSpell = SPELL_SOUL_CHARGE_YELLOW; - unleashSpell = SPELL_UNLEASH_SOUL_YELLOW; + case NPC_DOOMFIRE_SPIRIT: + DoomfireSpiritGUID = summoned->GetGUID(); break; - case 2: - chargeSpell = SPELL_SOUL_CHARGE_GREEN; - unleashSpell = SPELL_UNLEASH_SOUL_GREEN; - break; - } + case NPC_DOOMFIRE: + summoned->CastSpell(summoned, SPELL_DOOMFIRE_SPAWN, false); + summoned->CastSpell(summoned, SPELL_DOOMFIRE, true, 0, 0, me->GetGUID()); - if (me->HasAura(chargeSpell)) - { - me->RemoveAuraFromStack(chargeSpell); - DoCastVictim(unleashSpell); - HasCast = true; - SoulChargeCount--; + if (Unit* DoomfireSpirit = ObjectAccessor::GetUnit(*me, DoomfireSpiritGUID)) + { + summoned->GetMotionMaster()->MoveFollow(DoomfireSpirit, 0.0f, 0.0f); + DoomfireSpiritGUID.Clear(); + } + break; + default: + break; } - - if (HasCast) - SoulChargeTimer = urand(2000, 30000); } - void UpdateAI(uint32 diff) override + void DoAction(int32 actionId) override { - if (!me->IsInCombat()) + switch (actionId) { - // Do not let the raid skip straight to Archimonde. Visible and hostile ONLY if Azagalor is finished. - if ((instance->GetData(DATA_AZGALOREVENT) < DONE) && (me->IsVisible() || (me->getFaction() != 35))) - { - me->SetVisible(false); - me->setFaction(35); - } - else if ((instance->GetData(DATA_AZGALOREVENT) >= DONE) && (!me->IsVisible() || (me->getFaction() == 35))) - { - me->setFaction(1720); - me->SetVisible(true); - } - - if (DrainNordrassilTimer <= diff) - { - if (!IsChanneling) + case ACTION_ENRAGE: + me->GetMotionMaster()->Clear(false); + me->GetMotionMaster()->MoveIdle(); + Enraged = true; + Talk(SAY_ENRAGE); + break; + case ACTION_CHANNEL_WORLD_TREE: + if (Creature* temp = me->SummonCreature(NPC_CHANNEL_TARGET, NordrassilLoc, TEMPSUMMON_TIMED_DESPAWN, 1200000)) { - Creature* temp = me->SummonCreature(CREATURE_CHANNEL_TARGET, NordrassilLoc, TEMPSUMMON_TIMED_DESPAWN, 1200000); - - if (temp) - WorldTreeGUID = temp->GetGUID(); + WorldTreeGUID = temp->GetGUID(); if (Unit* Nordrassil = ObjectAccessor::GetUnit(*me, WorldTreeGUID)) { Nordrassil->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); Nordrassil->SetDisplayId(11686); DoCast(Nordrassil, SPELL_DRAIN_WORLD_TREE); - IsChanneling = true; } + events.ScheduleEvent(EVENT_DRAIN_NORDRASSIL, 1000); } - - if (Unit* Nordrassil = ObjectAccessor::GetUnit(*me, WorldTreeGUID)) - { - Nordrassil->CastSpell(me, SPELL_DRAIN_WORLD_TREE_2, true); - DrainNordrassilTimer = 1000; - } - } else DrainNordrassilTimer -= diff; + break; + default: + break; } + } - if (!UpdateVictim()) + //this is code doing close to what the summoning spell would do (spell 31903) + void SummonDoomfire(Unit* target) + { + if (!target) return; - if (me->HealthBelowPct(10) && !BelowTenPercent && !Enraged) - BelowTenPercent = true; - - if (!Enraged) - { - if (EnrageTimer <= diff) - { - if (HealthAbovePct(10)) - { - me->GetMotionMaster()->Clear(false); - me->GetMotionMaster()->MoveIdle(); - Enraged = true; - Talk(SAY_ENRAGE); - } - } else EnrageTimer -= diff; - - if (CheckDistanceTimer <= diff) - { - // To simplify the check, we simply summon a Creature in the location and then check how far we are from the creature - Creature* Check = me->SummonCreature(CREATURE_CHANNEL_TARGET, NordrassilLoc, TEMPSUMMON_TIMED_DESPAWN, 2000); - if (Check) - { - Check->SetVisible(false); - - if (me->IsWithinDistInMap(Check, 75)) - { - me->GetMotionMaster()->Clear(false); - me->GetMotionMaster()->MoveIdle(); - Enraged = true; - Talk(SAY_ENRAGE); - } - } - CheckDistanceTimer = 5000; - } else CheckDistanceTimer -= diff; - } - - if (BelowTenPercent) - { - if (!HasProtected) - { - me->GetMotionMaster()->Clear(false); - me->GetMotionMaster()->MoveIdle(); - - //all members of raid must get this buff - DoCastVictim(SPELL_PROTECTION_OF_ELUNE, true); - HasProtected = true; - Enraged = true; - } - - if (SummonWispTimer <= diff) - { - DoSpawnCreature(CREATURE_ANCIENT_WISP, float(rand32() % 40), float(rand32() % 40), 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - SummonWispTimer = 1500; - ++WispCount; - } else SummonWispTimer -= diff; - - if (WispCount >= 30) - me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - } - - if (Enraged) - { - if (HandOfDeathTimer <= diff) - { - DoCastVictim(SPELL_HAND_OF_DEATH); - HandOfDeathTimer = 2000; - } else HandOfDeathTimer -= diff; - return; // Don't do anything after this point. - } - - if (SoulChargeCount) - { - if (SoulChargeTimer <= diff) - UnleashSoulCharge(); - else SoulChargeTimer -= diff; - } - - if (GripOfTheLegionTimer <= diff) - { - DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0), SPELL_GRIP_OF_THE_LEGION); - GripOfTheLegionTimer = urand(5000, 25000); - } else GripOfTheLegionTimer -= diff; - - if (AirBurstTimer <= diff) - { - Talk(SAY_AIR_BURST); - DoCast(SelectTarget(SELECT_TARGET_RANDOM, 1), SPELL_AIR_BURST);//not on tank - AirBurstTimer = urand(25000, 40000); - } else AirBurstTimer -= diff; - - if (FearTimer <= diff) - { - DoCastVictim(SPELL_FEAR); - FearTimer = 42000; - } else FearTimer -= diff; - - if (DoomfireTimer <= diff) - { - Talk(SAY_DOOMFIRE); - Unit* temp = SelectTarget(SELECT_TARGET_RANDOM, 1); - if (!temp) - temp = me->GetVictim(); - - //replace with spell cast 31903 once implicitTarget 73 implemented - SummonDoomfire(temp); - - //supposedly three doomfire can be up at the same time - DoomfireTimer = 20000; - } else DoomfireTimer -= diff; - - if (MeleeRangeCheckTimer <= diff) - { - if (CanUseFingerOfDeath()) - { - DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0), SPELL_FINGER_OF_DEATH); - MeleeRangeCheckTimer = 1000; - } - - MeleeRangeCheckTimer = 5000; - } else MeleeRangeCheckTimer -= diff; + me->SummonCreature(NPC_DOOMFIRE_SPIRIT, + target->GetPositionX()+15.0f, target->GetPositionY()+15.0f, target->GetPositionZ(), 0, + TEMPSUMMON_TIMED_DESPAWN, 27000); - DoMeleeAttackIfReady(); + me->SummonCreature(NPC_DOOMFIRE, + target->GetPositionX()-15.0f, target->GetPositionY()-15.0f, target->GetPositionZ(), 0, + TEMPSUMMON_TIMED_DESPAWN, 27000); } - void WaypointReached(uint32 /*waypointId*/) override { } + + private: + ObjectGuid DoomfireSpiritGUID; + ObjectGuid WorldTreeGUID; + uint8 SoulChargeCount; + uint8 WispCount; + uint32 _chargeSpell; + uint32 _unleashSpell; + bool Enraged; + bool HasProtected; }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetInstanceAI<boss_archimondeAI>(creature); + } }; void AddSC_boss_archimonde() diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/instance_hyjal.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/instance_hyjal.cpp index 1d4a728b08b..fa8edf2c498 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/instance_hyjal.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/instance_hyjal.cpp @@ -104,14 +104,32 @@ public: { switch (creature->GetEntry()) { - case RAGE_WINTERCHILL: RageWinterchill = creature->GetGUID(); break; - case ANETHERON: Anetheron = creature->GetGUID(); break; - case KAZROGAL: Kazrogal = creature->GetGUID(); break; - case AZGALOR: Azgalor = creature->GetGUID(); break; - case ARCHIMONDE: Archimonde = creature->GetGUID(); break; - case JAINA: JainaProudmoore = creature->GetGUID(); break; - case THRALL: Thrall = creature->GetGUID(); break; - case TYRANDE: TyrandeWhisperwind = creature->GetGUID(); break; + case RAGE_WINTERCHILL: + RageWinterchill = creature->GetGUID(); + break; + case ANETHERON: + Anetheron = creature->GetGUID(); + break; + case KAZROGAL: + Kazrogal = creature->GetGUID(); + break; + case AZGALOR: + Azgalor = creature->GetGUID(); + break; + case ARCHIMONDE: + Archimonde = creature->GetGUID(); + if (GetData(DATA_AZGALOREVENT) != DONE) + creature->SetVisible(false); + break; + case JAINA: + JainaProudmoore = creature->GetGUID(); + break; + case THRALL: + Thrall = creature->GetGUID(); + break; + case TYRANDE: + TyrandeWhisperwind = creature->GetGUID(); + break; } } @@ -150,6 +168,9 @@ public: m_auiEncounter[3] = data; if (data == DONE) { + if (Creature* archimonde = instance->GetCreature(Archimonde)) + archimonde->SetVisible(true); + if (ArchiYell) break; diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/culling_of_stratholme.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/culling_of_stratholme.cpp index b84d24d66d3..794496382c2 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/culling_of_stratholme.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/culling_of_stratholme.cpp @@ -292,6 +292,7 @@ public: break; } player->CLOSE_GOSSIP_MENU(); + ai->SetDespawnAtFar(false); creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); return true; } diff --git a/src/server/scripts/Kalimdor/zone_dustwallow_marsh.cpp b/src/server/scripts/Kalimdor/zone_dustwallow_marsh.cpp index 9f5e7bdf29d..d254cbe08fb 100644 --- a/src/server/scripts/Kalimdor/zone_dustwallow_marsh.cpp +++ b/src/server/scripts/Kalimdor/zone_dustwallow_marsh.cpp @@ -19,12 +19,11 @@ /* ScriptData SDName: Dustwallow_Marsh SD%Complete: 95 -SDComment: Quest support: 11180, 558, 11126, 11142, 11174, Vendor Nat Pagle +SDComment: Quest support: 558, 11126, 11142, 11174, Vendor Nat Pagle SDCategory: Dustwallow Marsh EndScriptData */ /* ContentData -npc_risen_husk_spirit npc_lady_jaina_proudmoore npc_nat_pagle npc_private_hendel @@ -40,99 +39,6 @@ EndContentData */ #include "WorldSession.h" /*###### -## npc_risen_husk_spirit -######*/ - -enum HauntingWitchHill -{ - // Quest - QUEST_WHATS_HAUNTING_WITCH_HILL = 11180, - - // General spells - SPELL_SUMMON_RESTLESS_APPARITION = 42511, - SPELL_WITCH_HILL_INFORMATION_CREDIT = 42512, - - // Risen Husk specific - SPELL_CONSUME_FLESH = 37933, - NPC_RISEN_HUSK = 23555, - - // Risen Spirit specific - SPELL_INTANGIBLE_PRESENCE = 43127, - NPC_RISEN_SPIRIT = 23554, - - // Events - EVENT_CONSUME_FLESH = 1, - EVENT_INTANGIBLE_PRESENCE = 2, -}; - -class npc_risen_husk_spirit : public CreatureScript -{ - public: - npc_risen_husk_spirit() : CreatureScript("npc_risen_husk_spirit") { } - - struct npc_risen_husk_spiritAI : public ScriptedAI - { - npc_risen_husk_spiritAI(Creature* creature) : ScriptedAI(creature) { } - - void Reset() override - { - events.Reset(); - if (me->GetEntry() == NPC_RISEN_HUSK) - events.ScheduleEvent(EVENT_CONSUME_FLESH, 5000); - else if (me->GetEntry() == NPC_RISEN_SPIRIT) - events.ScheduleEvent(EVENT_INTANGIBLE_PRESENCE, 5000); - } - - void JustDied(Unit* killer) override - { - if (killer->GetTypeId() == TYPEID_PLAYER) - { - if (killer->ToPlayer()->GetQuestStatus(QUEST_WHATS_HAUNTING_WITCH_HILL) == QUEST_STATUS_INCOMPLETE) - { - DoCast(me, SPELL_SUMMON_RESTLESS_APPARITION, true); - DoCast(killer, SPELL_WITCH_HILL_INFORMATION_CREDIT, true); - } - } - } - - void UpdateAI(uint32 diff) override - { - if (!UpdateVictim()) - return; - - events.Update(diff); - - while (uint32 eventId = events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_CONSUME_FLESH: - DoCastVictim(SPELL_CONSUME_FLESH); - events.ScheduleEvent(EVENT_CONSUME_FLESH, 15000); - break; - case EVENT_INTANGIBLE_PRESENCE: - DoCastVictim(SPELL_INTANGIBLE_PRESENCE); - events.ScheduleEvent(EVENT_INTANGIBLE_PRESENCE, 15000); - break; - default: - break; - } - } - - DoMeleeAttackIfReady(); - } - - private: - EventMap events; - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return new npc_risen_husk_spiritAI(creature); - } -}; - -/*###### ## npc_lady_jaina_proudmoore ######*/ @@ -369,131 +275,6 @@ public: }; -/*###### -## npc_stinky -######*/ - -enum Stinky -{ - QUEST_STINKYS_ESCAPE_H = 1270, - QUEST_STINKYS_ESCAPE_A = 1222, - SAY_QUEST_ACCEPTED = 0, - SAY_STAY_1 = 1, - SAY_STAY_2 = 2, - SAY_STAY_3 = 3, - SAY_STAY_4 = 4, - SAY_STAY_5 = 5, - SAY_STAY_6 = 6, - SAY_QUEST_COMPLETE = 7, - SAY_ATTACKED_1 = 8, - EMOTE_DISAPPEAR = 9 -}; - -class npc_stinky : public CreatureScript -{ -public: - npc_stinky() : CreatureScript("npc_stinky") { } - - CreatureAI* GetAI(Creature* creature) const override - { - return new npc_stinkyAI(creature); - } - - bool OnQuestAccept(Player* player, Creature* creature, Quest const* quest) override - { - if (quest->GetQuestId() == QUEST_STINKYS_ESCAPE_H || quest->GetQuestId() == QUEST_STINKYS_ESCAPE_A) - { - if (npc_stinkyAI* pEscortAI = CAST_AI(npc_stinky::npc_stinkyAI, creature->AI())) - { - creature->setFaction(FACTION_ESCORT_N_NEUTRAL_ACTIVE); - creature->SetStandState(UNIT_STAND_STATE_STAND); - creature->AI()->Talk(SAY_QUEST_ACCEPTED); - pEscortAI->Start(false, false, player->GetGUID()); - } - } - return true; - } - - struct npc_stinkyAI : public npc_escortAI - { - npc_stinkyAI(Creature* creature) : npc_escortAI(creature) { } - - void WaypointReached(uint32 waypointId) override - { - Player* player = GetPlayerForEscort(); - if (!player) - return; - - switch (waypointId) - { - case 7: - Talk(SAY_STAY_1, player); - break; - case 11: - Talk(SAY_STAY_2, player); - break; - case 25: - Talk(SAY_STAY_3, player); - break; - case 26: - Talk(SAY_STAY_4, player); - break; - case 27: - Talk(SAY_STAY_5, player); - break; - case 28: - Talk(SAY_STAY_6, player); - me->SetStandState(UNIT_STAND_STATE_KNEEL); - break; - case 29: - me->SetStandState(UNIT_STAND_STATE_STAND); - break; - case 37: - Talk(SAY_QUEST_COMPLETE, player); - me->SetSpeed(MOVE_RUN, 1.2f, true); - me->SetWalk(false); - if (player->GetQuestStatus(QUEST_STINKYS_ESCAPE_H)) - player->GroupEventHappens(QUEST_STINKYS_ESCAPE_H, me); - if (player->GetQuestStatus(QUEST_STINKYS_ESCAPE_A)) - player->GroupEventHappens(QUEST_STINKYS_ESCAPE_A, me); - break; - case 39: - Talk(EMOTE_DISAPPEAR); - break; - } - } - - void EnterCombat(Unit* who) override - { - Talk(SAY_ATTACKED_1, who); - } - - void Reset() override { } - - void JustDied(Unit* /*killer*/) override - { - Player* player = GetPlayerForEscort(); - if (player && HasEscortState(STATE_ESCORT_ESCORTING)) - { - if (player->GetQuestStatus(QUEST_STINKYS_ESCAPE_H)) - player->FailQuest(QUEST_STINKYS_ESCAPE_H); - - if (player->GetQuestStatus(QUEST_STINKYS_ESCAPE_A)) - player->FailQuest(QUEST_STINKYS_ESCAPE_A); - } - } - - void UpdateAI(uint32 uiDiff) override - { - npc_escortAI::UpdateAI(uiDiff); - - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } - }; -}; enum SpellScripts { @@ -634,46 +415,13 @@ class spell_energize_aoe : public SpellScriptLoader } }; -/*###### -## go_blackhoof_cage -######*/ - -enum PrisonersOfTheGrimTotems -{ - NPC_THERAMORE_PRISONER = 23720, - SAY_FREE = 0, -}; - -class go_blackhoof_cage : public GameObjectScript -{ -public: - go_blackhoof_cage() : GameObjectScript("go_blackhoof_cage") { } - - bool OnGossipHello(Player* player, GameObject* go) override - { - go->UseDoorOrButton(); - if (Creature* prisoner = go->FindNearestCreature(NPC_THERAMORE_PRISONER, 1.0f)) - { - if (player) - player->KilledMonsterCredit(NPC_THERAMORE_PRISONER); - - prisoner->AI()->Talk(SAY_FREE); // We also emote cry here (handled in creature_text.emote) - prisoner->DespawnOrUnsummon(6000); - } - return true; - } -}; - void AddSC_dustwallow_marsh() { - new npc_risen_husk_spirit(); new npc_lady_jaina_proudmoore(); new npc_nat_pagle(); new npc_private_hendel(); new npc_zelfrax(); - new npc_stinky(); new spell_ooze_zap(); new spell_ooze_zap_channel_end(); new spell_energize_aoe(); - new go_blackhoof_cage(); } diff --git a/src/server/scripts/Northrend/zone_dragonblight.cpp b/src/server/scripts/Northrend/zone_dragonblight.cpp index eff84365f63..b949c43b64d 100644 --- a/src/server/scripts/Northrend/zone_dragonblight.cpp +++ b/src/server/scripts/Northrend/zone_dragonblight.cpp @@ -366,48 +366,6 @@ class npc_commander_eligor_dawnbringer : public CreatureScript } }; -enum AlexstraszaWrGate -{ - // Quest - QUEST_RETURN_TO_AG_A = 12499, - QUEST_RETURN_TO_AG_H = 12500, - - // Movie - MOVIE_ID_GATES = 14 -}; - -#define GOSSIP_ITEM_WHAT_HAPPENED "Alexstrasza, can you show me what happened here?" - -class npc_alexstrasza_wr_gate : public CreatureScript -{ -public: - npc_alexstrasza_wr_gate() : CreatureScript("npc_alexstrasza_wr_gate") { } - - bool OnGossipHello(Player* player, Creature* creature) override - { - if (creature->IsQuestGiver()) - player->PrepareQuestMenu(creature->GetGUID()); - - if (player->GetQuestRewardStatus(QUEST_RETURN_TO_AG_A) || player->GetQuestRewardStatus(QUEST_RETURN_TO_AG_H)) - player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_WHAT_HAPPENED, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID()); - return true; - } - - bool OnGossipSelect(Player* player, Creature* /*creature*/, uint32 /*sender*/, uint32 action) override - { - player->PlayerTalkClass->ClearMenus(); - if (action == GOSSIP_ACTION_INFO_DEF+1) - { - player->CLOSE_GOSSIP_MENU(); - player->SendMovieStart(MOVIE_ID_GATES); - } - - return true; - } -}; - /*###### ## Quest Strengthen the Ancients (12096|12092) ######*/ @@ -746,7 +704,6 @@ class npc_torturer_lecraft : public CreatureScript void AddSC_dragonblight() { new npc_commander_eligor_dawnbringer(); - new npc_alexstrasza_wr_gate(); new spell_q12096_q12092_dummy(); new spell_q12096_q12092_bark(); new npc_wyrmrest_defender(); diff --git a/src/server/scripts/Northrend/zone_icecrown.cpp b/src/server/scripts/Northrend/zone_icecrown.cpp index 7436ac8400f..2b317453992 100644 --- a/src/server/scripts/Northrend/zone_icecrown.cpp +++ b/src/server/scripts/Northrend/zone_icecrown.cpp @@ -210,52 +210,6 @@ public: }; /*###### -## npc_vereth_the_cunning -######*/ - -enum VerethTheCunning -{ - NPC_GEIST_RETURN_BUNNY_KC = 31049, - NPC_LITHE_STALKER = 30894, - SPELL_SUBDUED_LITHE_STALKER = 58151, -}; - -class npc_vereth_the_cunning : public CreatureScript -{ -public: - npc_vereth_the_cunning() : CreatureScript("npc_vereth_the_cunning") { } - - struct npc_vereth_the_cunningAI : public ScriptedAI - { - npc_vereth_the_cunningAI(Creature* creature) : ScriptedAI(creature) { } - - void MoveInLineOfSight(Unit* who) override - - { - ScriptedAI::MoveInLineOfSight(who); - - if (who->GetEntry() == NPC_LITHE_STALKER && me->IsWithinDistInMap(who, 10.0f)) - { - if (Unit* owner = who->GetCharmer()) - { - if (who->HasAura(SPELL_SUBDUED_LITHE_STALKER)) - { - owner->ToPlayer()->KilledMonsterCredit(NPC_GEIST_RETURN_BUNNY_KC); - who->ToCreature()->DisappearAndDie(); - - } - } - } - } - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return new npc_vereth_the_cunningAI(creature); - } -}; - -/*###### * npc_tournament_training_dummy ######*/ enum TournamentDummy @@ -881,207 +835,12 @@ class npc_frostbrood_skytalon : public CreatureScript } }; -/*###### -## The Flesh Giant Champion - Id: 13235 -######*/ -enum FleshGiant -{ - QUEST_FLESH_GIANT_CHAMPION = 13235, - - NPC_MORBIDUS = 30698, - NPC_LICH_KING = 31301, - NPC_OLAKIN = 31428, - NPC_DHAKAR = 31306, - - FACTION_HOSTILE = 14, - FACTION_BASIC = 2102, - - EVENT_INTRO = 1, - EVENT_LK_SAY_1 = 2, - EVENT_LK_SAY_2 = 3, - EVENT_LK_SAY_3 = 4, - EVENT_LK_SAY_4 = 5, - EVENT_LK_SAY_5 = 6, - EVENT_OUTRO = 7, - EVENT_START = 8, - - SPELL_SIMPLE_TELEPORT = 64195, - - SAY_DHAKAR_START = 0, - SAY_LK_1 = 0, - SAY_LK_2 = 1, - SAY_LK_3 = 2, - SAY_LK_4 = 3, - SAY_LK_5 = 4, - SAY_OLAKIN_PAY = 0 -}; - -class npc_margrave_dhakar : public CreatureScript -{ - public: - npc_margrave_dhakar() : CreatureScript("npc_margrave_dhakar") { } - - struct npc_margrave_dhakarAI : public ScriptedAI - { - npc_margrave_dhakarAI(Creature* creature) : ScriptedAI(creature) , _summons(me) { } - - void Reset() override - { - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_NONE); - - _events.Reset(); - _summons.DespawnAll(); - } - - void sGossipSelect(Player* player, uint32 sender, uint32 action) override - { - if (player->GetQuestStatus(QUEST_FLESH_GIANT_CHAMPION) == QUEST_STATUS_INCOMPLETE && !player->IsInCombat()) - { - if (me->GetCreatureTemplate()->GossipMenuId == sender && !action) - { - _events.ScheduleEvent(EVENT_INTRO, 1000); - me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - } - } - } - - void UpdateAI(uint32 diff) override - { - _events.Update(diff); - - while (uint32 eventId = _events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_INTRO: - { - Talk(SAY_DHAKAR_START); - me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_READY2H); - - if (Creature* morbidus = me->FindNearestCreature(NPC_MORBIDUS, 50.0f, true)) - { - if (Creature* lichKing = me->SummonCreature(NPC_LICH_KING, morbidus->GetPositionX() + 10.0f, morbidus->GetPositionY(), morbidus->GetPositionZ())) - { - _lichKingGuid = lichKing->GetGUID(); - lichKing->SetFacingTo(morbidus->GetOrientation()); - lichKing->CastSpell(lichKing, SPELL_SIMPLE_TELEPORT, true); - } - } - - _events.ScheduleEvent(EVENT_LK_SAY_1, 5000); - break; - } - case EVENT_LK_SAY_1: - { - if (Creature* lichKing = ObjectAccessor::GetCreature(*me, _lichKingGuid)) - lichKing->AI()->Talk(SAY_LK_1); - _events.ScheduleEvent(EVENT_LK_SAY_2, 5000); - break; - } - case EVENT_LK_SAY_2: - { - if (Creature* lichKing = ObjectAccessor::GetCreature(*me, _lichKingGuid)) - lichKing->AI()->Talk(SAY_LK_2); - _events.ScheduleEvent(EVENT_LK_SAY_3, 5000); - break; - } - case EVENT_LK_SAY_3: - { - if (Creature* lichKing = ObjectAccessor::GetCreature(*me, _lichKingGuid)) - lichKing->AI()->Talk(SAY_LK_3); - _events.ScheduleEvent(EVENT_LK_SAY_4, 5000); - break; - } - case EVENT_LK_SAY_4: - { - if (Creature* lichKing = ObjectAccessor::GetCreature(*me, _lichKingGuid)) - lichKing->AI()->Talk(SAY_LK_4); - _events.ScheduleEvent(EVENT_OUTRO, 12000); - break; - } - case EVENT_LK_SAY_5: - { - if (Creature* lichKing = ObjectAccessor::GetCreature(*me, _lichKingGuid)) - lichKing->AI()->Talk(SAY_LK_5); - _events.ScheduleEvent(EVENT_OUTRO, 8000); - break; - } - case EVENT_OUTRO: - { - if (Creature* olakin = me->FindNearestCreature(NPC_OLAKIN, 50.0f, true)) - olakin->AI()->Talk(SAY_OLAKIN_PAY); - - if (Creature* lichKing = ObjectAccessor::GetCreature(*me, _lichKingGuid)) - lichKing->DespawnOrUnsummon(0); - - _events.ScheduleEvent(EVENT_START, 5000); - break; - } - case EVENT_START: - { - if (Creature* morbidus = me->FindNearestCreature(NPC_MORBIDUS, 50.0f, true)) - { - morbidus->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_ATTACKABLE_1 | UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC | UNIT_FLAG_DISABLE_MOVE); - morbidus->setFaction(FACTION_HOSTILE); - } - - break; - } - } - } - - DoMeleeAttackIfReady(); - } - - private: - EventMap _events; - SummonList _summons; - ObjectGuid _lichKingGuid; - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return new npc_margrave_dhakarAI(creature); - } -}; - -class npc_morbidus : public CreatureScript -{ - public: - npc_morbidus() : CreatureScript("npc_morbidus") { } - - struct npc_morbidusAI : public ScriptedAI - { - npc_morbidusAI(Creature* creature) : ScriptedAI(creature) { } - - void Reset() override - { - if (Creature* dhakar = me->FindNearestCreature(NPC_DHAKAR, 50.0f, true)) - dhakar->AI()->Reset(); - - // this will prevent the event to start without morbidus being alive - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->SetReactState(REACT_PASSIVE); - me->setFaction(FACTION_BASIC); - } - }; - - CreatureAI* GetAI(Creature* creature) const override - { - return new npc_morbidusAI(creature); - } -}; - void AddSC_icecrown() { new npc_squire_david; new npc_argent_valiant; new npc_guardian_pavilion; - new npc_vereth_the_cunning; new npc_tournament_training_dummy; new npc_blessed_banner(); new npc_frostbrood_skytalon(); - new npc_margrave_dhakar(); - new npc_morbidus(); } diff --git a/src/server/scripts/Outland/CoilfangReservoir/SteamVault/instance_steam_vault.cpp b/src/server/scripts/Outland/CoilfangReservoir/SteamVault/instance_steam_vault.cpp index f0884e83baa..794d3a490f6 100644 --- a/src/server/scripts/Outland/CoilfangReservoir/SteamVault/instance_steam_vault.cpp +++ b/src/server/scripts/Outland/CoilfangReservoir/SteamVault/instance_steam_vault.cpp @@ -31,21 +31,25 @@ class go_main_chambers_access_panel : public GameObjectScript return false; if (go->GetEntry() == GO_ACCESS_PANEL_HYDRO && (instance->GetBossState(DATA_HYDROMANCER_THESPIA) == DONE || instance->GetBossState(DATA_HYDROMANCER_THESPIA) == SPECIAL)) - { instance->SetBossState(DATA_HYDROMANCER_THESPIA, SPECIAL); - go->SetGoState(GO_STATE_ACTIVE); - } if (go->GetEntry() == GO_ACCESS_PANEL_MEK && (instance->GetBossState(DATA_MEKGINEER_STEAMRIGGER) == DONE || instance->GetBossState(DATA_MEKGINEER_STEAMRIGGER) == SPECIAL)) - { instance->SetBossState(DATA_MEKGINEER_STEAMRIGGER, SPECIAL); - go->SetGoState(GO_STATE_ACTIVE); - } + + go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); + go->SetGoState(GO_STATE_ACTIVE); return true; } }; +ObjectData const gameObjectData[] = +{ + { GO_ACCESS_PANEL_HYDRO, DATA_ACCESS_PANEL_HYDRO }, + { GO_ACCESS_PANEL_MEK, DATA_ACCESS_PANEL_MEK }, + { 0, 0 } // END +}; + class instance_steam_vault : public InstanceMapScript { public: @@ -57,6 +61,7 @@ class instance_steam_vault : public InstanceMapScript { SetHeaders(DataHeader); SetBossNumber(EncounterCount); + LoadObjectData(nullptr, gameObjectData); DistillerState = 0; } @@ -89,6 +94,8 @@ class instance_steam_vault : public InstanceMapScript default: break; } + + InstanceScript::OnGameObjectCreate(go); } ObjectGuid GetGuidData(uint32 type) const override @@ -128,6 +135,9 @@ class instance_steam_vault : public InstanceMapScript switch (type) { case DATA_HYDROMANCER_THESPIA: + if (state == DONE) + if (GameObject* panel = GetGameObject(DATA_ACCESS_PANEL_HYDRO)) + panel->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); if (state == SPECIAL) { if (GetBossState(DATA_MEKGINEER_STEAMRIGGER) == SPECIAL) @@ -137,6 +147,9 @@ class instance_steam_vault : public InstanceMapScript } break; case DATA_MEKGINEER_STEAMRIGGER: + if (state == DONE) + if (GameObject* panel = GetGameObject(DATA_ACCESS_PANEL_MEK)) + panel->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); if (state == SPECIAL) { if (GetBossState(DATA_HYDROMANCER_THESPIA) == SPECIAL) diff --git a/src/server/scripts/Outland/CoilfangReservoir/SteamVault/steam_vault.h b/src/server/scripts/Outland/CoilfangReservoir/SteamVault/steam_vault.h index 58f71b047ef..d18d0406dea 100644 --- a/src/server/scripts/Outland/CoilfangReservoir/SteamVault/steam_vault.h +++ b/src/server/scripts/Outland/CoilfangReservoir/SteamVault/steam_vault.h @@ -28,7 +28,11 @@ enum DataTypes DATA_HYDROMANCER_THESPIA = 0, DATA_MEKGINEER_STEAMRIGGER = 1, DATA_WARLORD_KALITHRESH = 2, - DATA_DISTILLER = 3 + DATA_DISTILLER = 3, + + // Additional Data + DATA_ACCESS_PANEL_HYDRO = 4, + DATA_ACCESS_PANEL_MEK = 5 }; enum CreatureIds diff --git a/src/server/shared/Common.h b/src/server/shared/Common.h index 27e6cb63514..8ffb138379a 100644 --- a/src/server/shared/Common.h +++ b/src/server/shared/Common.h @@ -79,6 +79,9 @@ inline float finiteAlways(float f) { return std::isfinite(f) ? f : 0.0f; } +inline unsigned long atoul(char const* str) { return strtoul(str, nullptr, 10); } +inline unsigned long long atoull(char const* str) { return strtoull(str, nullptr, 10); } + #define STRINGIZE(a) #a enum TimeConstants |