Merge commit '32d9a71a4219ea353950979a2491e7879b7fa79a' into 4.3.4

Conflicts:
	README.md
	sql/base/auth_database.sql
	sql/updates/world/2014_12_27_01_world_335.sql
	src/server/game/Conditions/ConditionMgr.cpp
	src/server/game/Globals/ObjectMgr.cpp
	src/server/game/Server/WorldSession.cpp
	src/server/scripts/Commands/cs_misc.cpp
	src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/instance_hyjal.cpp
	src/server/scripts/Kalimdor/zone_dustwallow_marsh.cpp
	src/server/scripts/Spells/spell_hunter.cpp
This commit is contained in:
Carbenium committed 2015-07-21 20:05:44 +02:00
commit 79eb80dcba
71 files changed
+1652 -1862

No files matched your search

+7 -8
View File
@@ -2,12 +2,9 @@
[![Issue Stats](http://www.issuestats.com/github/TrinityCore/TrinityCore/badge/issue)](http://www.issuestats.com/github/TrinityCore/TrinityCore) [![Issue Stats](http://www.issuestats.com/github/TrinityCore/TrinityCore/badge/pr)](http://www.issuestats.com/github/TrinityCore/TrinityCore) [![Bountysource](https://www.bountysource.com/badge/tracker?tracker_id=1310)](https://www.bountysource.com/trackers/1310-trinity-core?utm_source=1310&utm_medium=shield&utm_campaign=TRACKER_BADGE)
## Build Status
6.x | 4.3.4 | 3.3.5
:------------: | :------------: | :------------:
[![6.x Build Status](https://travis-ci.org/TrinityCore/TrinityCore.svg?branch=6.x)](https://travis-ci.org/TrinityCore/TrinityCore) | [![4.3.4 Build Status](https://travis-ci.org/TrinityCore/TrinityCore.svg?branch=4.3.4)](https://travis-ci.org/TrinityCore/TrinityCore) | [![3.3.5 Build Status](https://travis-ci.org/TrinityCore/TrinityCore.svg?branch=3.3.5)](https://travis-ci.org/TrinityCore/TrinityCore)
[![Coverity Scan Build Status](https://scan.coverity.com/projects/435/badge.svg)](https://scan.coverity.com/projects/435) | | [![Coverity Scan Build Status](https://scan.coverity.com/projects/4656/badge.svg)](https://scan.coverity.com/projects/4656)
`6.x`: [![6.x Build Status](https://travis-ci.org/TrinityCore/TrinityCore.svg?branch=6.x)](https://travis-ci.org/TrinityCore/TrinityCore)
`4.3.4`: [![4.3.4 Build Status](https://travis-ci.org/TrinityCore/TrinityCore.svg?branch=4.3.4)](https://travis-ci.org/TrinityCore/TrinityCore)
`3.3.5`: [![3.3.5 Build Status](https://travis-ci.org/TrinityCore/TrinityCore.svg?branch=3.3.5)](https://travis-ci.org/TrinityCore/TrinityCore)
## Introduction
@@ -40,8 +37,10 @@ website at [TrinityCore.org](http://www.trinitycore.org).
## Install
Detailed installation guides are available in the [wiki](http://collab.kpsn.org/display/tc/Installation+Guide) for
Windows, Linux and Mac OSX.
Detailed installation guides are available in the wiki for
[Windows](http://collab.kpsn.org/display/tc/Win),
[Linux](http://collab.kpsn.org/display/tc/Linux) and
[Mac OSX](http://collab.kpsn.org/display/tc/Mac).
## Reporting issues
+3 -3
View File
@@ -341,9 +341,9 @@ endfunction()
# Guesses Boost's compiler prefix used in built library names
# Returns the guess by setting the variable pointed to by _ret
function(_Boost_GUESS_COMPILER_PREFIX _ret)
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel"
OR "${CMAKE_CXX_COMPILER}" MATCHES "icl"
OR "${CMAKE_CXX_COMPILER}" MATCHES "icpc")
if(${CMAKE_CXX_COMPILER_ID} STREQUAL "Intel"
OR ${CMAKE_CXX_COMPILER} MATCHES "icl"
OR ${CMAKE_CXX_COMPILER} MATCHES "icpc")
if(WIN32)
set (_boost_COMPILER "-iw")
else()
+1 -1
View File
@@ -26,7 +26,7 @@ utf8-cpp (UTF-8 with C++ in a Portable Way)
zlib (A Massively Spiffy Yet Delicately Unobtrusive Compression Library)
http://www.zlib.net/
Version: 1.2.7
Version: 1.2.8
gSOAP (a portable development toolkit for C and C++ XML Web services and XML data bindings)
http://gsoap2.sourceforge.net/
+6 -5
View File
@@ -1,8 +1,8 @@
-- MySQL dump 10.15 Distrib 10.0.13-MariaDB, for Win64 (x86)
-- MySQL dump 10.15 Distrib 10.0.15-MariaDB, for Win64 (x86)
--
-- Host: localhost Database: auth_4x
-- ------------------------------------------------------
-- Server version 10.0.13-MariaDB
-- Server version 10.0.15-MariaDB
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
@@ -496,7 +496,8 @@ DROP TABLE IF EXISTS `rbac_default_permissions`;
CREATE TABLE `rbac_default_permissions` (
`secId` int(10) unsigned NOT NULL COMMENT 'Security Level id',
`permissionId` int(10) unsigned NOT NULL COMMENT 'permission id',
PRIMARY KEY (`secId`,`permissionId`),
`realmId` int(11) NOT NULL DEFAULT '-1' COMMENT 'Realm Id, -1 means all',
PRIMARY KEY (`secId`,`permissionId`,`realmId`),
KEY `fk__rbac_default_permissions__rbac_permissions` (`permissionId`),
CONSTRAINT `fk__rbac_default_permissions__rbac_permissions` FOREIGN KEY (`permissionId`) REFERENCES `rbac_permissions` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Default permission to assign to different account security levels';
@@ -508,7 +509,7 @@ CREATE TABLE `rbac_default_permissions` (
LOCK TABLES `rbac_default_permissions` WRITE;
/*!40000 ALTER TABLE `rbac_default_permissions` DISABLE KEYS */;
INSERT INTO `rbac_default_permissions` VALUES (3,192),(2,193),(1,194),(0,195);
INSERT INTO `rbac_default_permissions` VALUES (0,195,-1),(1,194,-1),(2,193,-1),(3,192,-1);
/*!40000 ALTER TABLE `rbac_default_permissions` ENABLE KEYS */;
UNLOCK TABLES;
@@ -661,4 +662,4 @@ UNLOCK TABLES;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
-- Dump completed on 2014-11-11 0:38:41
-- Dump completed on 2014-12-21 20:42:33
+3
View File
@@ -0,0 +1,3 @@
ALTER TABLE `rbac_default_permissions`
ADD COLUMN `realmId` INT(11) NOT NULL DEFAULT '-1' COMMENT 'Realm Id, -1 means all',
DROP PRIMARY KEY, ADD PRIMARY KEY (`secId`, `permissionId`, `realmId`);
+9
View File
@@ -0,0 +1,9 @@
-- Add rbac_permissions
DELETE FROM `rbac_permissions` WHERE `id` = 51;
INSERT INTO `rbac_permissions` (`id`,`name`) VALUES
(51, 'Allow trading between factions');
-- Add rbac_linked_permissions
DELETE FROM `rbac_linked_permissions` WHERE `linkedId` = 51;
INSERT INTO `rbac_linked_permissions` (`id`,`linkedId`) VALUES
(194, 51);
+1 -1
View File
@@ -446,7 +446,7 @@ void AccountMgr::LoadRBAC()
while (result->NextRow());
TC_LOG_DEBUG("rbac", "AccountMgr::LoadRBAC: Loading default permissions");
result = LoginDatabase.Query("SELECT secId, permissionId FROM rbac_default_permissions ORDER BY secId ASC");
result = LoginDatabase.PQuery("SELECT secId, permissionId FROM rbac_default_permissions WHERE (realmId = %u OR realmId = -1) ORDER BY secId ASC", realmID);
if (!result)
{
TC_LOG_INFO("server.loading", ">> Loaded 0 default permission definitions. DB table `rbac_default_permissions` is empty.");
+1
View File
@@ -100,6 +100,7 @@ enum RBACPermissions
RBAC_PERM_COMMANDS_PINFO_CHECK_PERSONAL_DATA = 48,
RBAC_PERM_EMAIL_CONFIRM_FOR_PASS_CHANGE = 49,
RBAC_PERM_MAY_CHECK_OWN_EMAIL = 50,
RBAC_PERM_ALLOW_TWO_SIDE_TRADE = 51,
// Free space for core permissions (till 149)
// Roles (Permissions with delegated permissions) use 199 and descending
+5 -8
View File
@@ -1000,7 +1000,7 @@ uint32 ChatHandler::extractSpellIdFromLink(char* text)
if (!idS)
return 0;
uint32 id = (uint32)atol(idS);
uint32 id = atoul(idS);
switch (type)
{
@@ -1013,13 +1013,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:
@@ -1027,7 +1024,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)
@@ -1100,7 +1097,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);
@@ -1109,7 +1106,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);
File diff suppressed because it is too large. Load diff
+16 -3
View File
@@ -212,6 +212,8 @@ struct Condition
uint32 GetSearcherTypeMaskForCondition();
bool isLoaded() const { return ConditionType > CONDITION_NONE || ReferenceId; }
uint32 GetMaxAvailableConditionTargets();
std::string ToString(bool ext = false) const; /// For logging purpose
};
typedef std::list<Condition*> ConditionList;
@@ -230,7 +232,6 @@ class ConditionMgr
~ConditionMgr();
public:
static ConditionMgr* instance()
{
static ConditionMgr instance;
@@ -245,14 +246,24 @@ class ConditionMgr
bool IsObjectMeetToConditions(WorldObject* object, ConditionList const& conditions);
bool IsObjectMeetToConditions(WorldObject* object1, WorldObject* object2, ConditionList const& conditions);
bool IsObjectMeetToConditions(ConditionSourceInfo& sourceInfo, ConditionList const& conditions);
bool CanHaveSourceGroupSet(ConditionSourceType sourceType) const;
bool CanHaveSourceIdSet(ConditionSourceType sourceType) const;
static bool CanHaveSourceGroupSet(ConditionSourceType sourceType);
static bool CanHaveSourceIdSet(ConditionSourceType sourceType);
ConditionList GetConditionsForNotGroupedEntry(ConditionSourceType sourceType, uint32 entry);
ConditionList GetConditionsForSpellClickEvent(uint32 creatureId, uint32 spellId);
ConditionList GetConditionsForSmartEvent(int32 entryOrGuid, uint32 eventId, uint32 sourceType);
ConditionList GetConditionsForVehicleSpell(uint32 creatureId, uint32 spellId);
ConditionList GetConditionsForNpcVendorEvent(uint32 creatureId, uint32 itemId);
struct ConditionTypeInfo
{
char const* Name;
bool HasConditionValue1;
bool HasConditionValue2;
bool HasConditionValue3;
};
static char const* StaticSourceTypeData[CONDITION_SOURCE_TYPE_MAX];
static ConditionTypeInfo const StaticConditionTypeData[CONDITION_MAX];
private:
bool isSourceTypeValid(Condition* cond);
bool addToLootTemplate(Condition* cond, LootTemplate* loot);
@@ -261,6 +272,8 @@ class ConditionMgr
bool addToSpellImplicitTargetConditions(Condition* cond);
bool IsObjectMeetToConditionList(ConditionSourceInfo& sourceInfo, ConditionList const& conditions);
static void LogUselessConditionValue(Condition* cond, uint8 index, uint32 value);
void Clean(); // free up resources
std::list<Condition*> AllocatedMemoryStore; // some garbage collection :)
+1 -1
View File
@@ -785,7 +785,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);
}
}
+14 -10
View File
@@ -209,7 +209,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);
}
}
@@ -236,7 +236,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);
}
@@ -15555,12 +15555,13 @@ void Player::RewardQuest(Quest const* quest, uint32 reward, Object* questGiver,
void Player::FailQuest(uint32 questId)
{
// Already complete quests shouldn't turn failed.
if (GetQuestStatus(questId) == QUEST_STATUS_COMPLETE)
return;
if (Quest const* quest = sObjectMgr->GetQuestTemplate(questId))
{
// Already complete quests shouldn't turn failed.
if (GetQuestStatus(questId) == QUEST_STATUS_COMPLETE && !quest->HasSpecialFlag(QUEST_SPECIAL_FLAGS_TIMED))
return;
SetQuestStatus(questId, QUEST_STATUS_FAILED);
uint16 log_slot = FindQuestSlot(questId);
@@ -21550,12 +21551,15 @@ void Player::SetRestBonus(float rest_bonus_new)
m_rest_bonus = rest_bonus_new;
// update data for client
if (GetSession()->IsARecruiter() || (GetSession()->GetRecruiterId() != 0))
if ((GetsRecruitAFriendBonus(true) && (GetSession()->IsARecruiter() || GetSession()->GetRecruiterId() != 0)))
SetByteValue(PLAYER_BYTES_2, 3, REST_STATE_RAF_LINKED);
else if (m_rest_bonus > 10)
SetByteValue(PLAYER_BYTES_2, 3, REST_STATE_RESTED); // Set Reststate = Rested
else if (m_rest_bonus <= 1)
SetByteValue(PLAYER_BYTES_2, 3, REST_STATE_NOT_RAF_LINKED); // Set Reststate = Normal
else
{
if (m_rest_bonus > 10)
SetByteValue(PLAYER_BYTES_2, 3, REST_STATE_RESTED);
else if (m_rest_bonus <= 1)
SetByteValue(PLAYER_BYTES_2, 3, REST_STATE_NOT_RAF_LINKED);
}
//RestTickUpdate
SetUInt32Value(PLAYER_REST_STATE_EXPERIENCE, uint32(m_rest_bonus));
+1 -1
View File
@@ -12232,7 +12232,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);
+50 -49
View File
@@ -596,17 +596,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)
@@ -1044,17 +1044,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)
@@ -5757,35 +5757,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)
@@ -8690,31 +8687,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 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_script_names 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 <> ''");
"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)
{
@@ -8722,20 +8720,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
+2 -3
View File
@@ -1261,9 +1261,8 @@ class ObjectMgr
bool IsVendorItemValid(uint32 vendor_entry, uint32 id, int32 maxcount, uint32 ptime, uint32 ExtendedCost, uint8 type, 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
{
@@ -2110,7 +2110,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)
{
+8 -16
View File
@@ -42,14 +42,6 @@ enum CharterItemIDs
ARENA_TEAM_CHARTER_5v5 = 23562
};
enum CharterCosts
{
GUILD_CHARTER_COST = 1000,
ARENA_TEAM_CHARTER_2v2_COST = 800000,
ARENA_TEAM_CHARTER_3v3_COST = 1200000,
ARENA_TEAM_CHARTER_5v5_COST = 2000000
};
void WorldSession::HandlePetitionBuyOpcode(WorldPacket& recvData)
{
TC_LOG_DEBUG("network", "Received opcode CMSG_PETITION_BUY");
@@ -106,7 +98,7 @@ void WorldSession::HandlePetitionBuyOpcode(WorldPacket& recvData)
return;
charterid = GUILD_CHARTER;
cost = GUILD_CHARTER_COST;
cost = sWorld->getIntConfig(CONFIG_CHARTER_COST_GUILD);
type = GUILD_CHARTER_TYPE;
}
else
@@ -122,17 +114,17 @@ void WorldSession::HandlePetitionBuyOpcode(WorldPacket& recvData)
{
case 1:
charterid = ARENA_TEAM_CHARTER_2v2;
cost = ARENA_TEAM_CHARTER_2v2_COST;
cost = sWorld->getIntConfig(CONFIG_CHARTER_COST_ARENA_2v2);
type = ARENA_TEAM_CHARTER_2v2_TYPE;
break;
case 2:
charterid = ARENA_TEAM_CHARTER_3v3;
cost = ARENA_TEAM_CHARTER_3v3_COST;
cost = sWorld->getIntConfig(CONFIG_CHARTER_COST_ARENA_3v3);
type = ARENA_TEAM_CHARTER_3v3_TYPE;
break;
case 3:
charterid = ARENA_TEAM_CHARTER_5v5;
cost = ARENA_TEAM_CHARTER_5v5_COST;
cost = sWorld->getIntConfig(CONFIG_CHARTER_COST_ARENA_5v5);
type = ARENA_TEAM_CHARTER_5v5_TYPE;
break;
default:
@@ -941,7 +933,7 @@ void WorldSession::SendPetitionShowList(ObjectGuid guid)
data << uint32(1); // index
data << uint32(GUILD_CHARTER); // charter entry
data << uint32(CHARTER_DISPLAY_ID); // charter display id
data << uint32(GUILD_CHARTER_COST); // charter cost
data << uint32(sWorld->getIntConfig(CONFIG_CHARTER_COST_GUILD)); // charter cost
data << uint32(0); // unknown
data << uint32(sWorld->getIntConfig(CONFIG_MIN_PETITION_SIGNS)); // required signs
}
@@ -952,21 +944,21 @@ void WorldSession::SendPetitionShowList(ObjectGuid guid)
data << uint32(1); // index
data << uint32(ARENA_TEAM_CHARTER_2v2); // charter entry
data << uint32(CHARTER_DISPLAY_ID); // charter display id
data << uint32(ARENA_TEAM_CHARTER_2v2_COST); // charter cost
data << uint32(sWorld->getIntConfig(CONFIG_CHARTER_COST_ARENA_2v2)); // charter cost
data << uint32(2); // unknown
data << uint32(2); // required signs?
// 3v3
data << uint32(2); // index
data << uint32(ARENA_TEAM_CHARTER_3v3); // charter entry
data << uint32(CHARTER_DISPLAY_ID); // charter display id
data << uint32(ARENA_TEAM_CHARTER_3v3_COST); // charter cost
data << uint32(sWorld->getIntConfig(CONFIG_CHARTER_COST_ARENA_3v3)); // charter cost
data << uint32(3); // unknown
data << uint32(3); // required signs?
// 5v5
data << uint32(3); // index
data << uint32(ARENA_TEAM_CHARTER_5v5); // charter entry
data << uint32(CHARTER_DISPLAY_ID); // charter display id
data << uint32(ARENA_TEAM_CHARTER_5v5_COST); // charter cost
data << uint32(sWorld->getIntConfig(CONFIG_CHARTER_COST_ARENA_5v5)); // charter cost
data << uint32(5); // unknown
data << uint32(5); // required signs?
}
+3 -1
View File
@@ -775,7 +775,9 @@ void WorldSession::HandleInitiateTradeOpcode(WorldPacket& recvPacket)
return;
}
if (!sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_TRADE) && pOther->GetTeam() !=_player->GetTeam())
if (pOther->GetTeam() != _player->GetTeam() &&
(!sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_TRADE) &&
!GetPlayer()->GetSession()->HasPermission(rbac::RBAC_PERM_ALLOW_TWO_SIDE_TRADE)))
{
info.Status = TRADE_STATUS_WRONG_FACTION;
SendTradeStatus(info);
+1 -1
View File
@@ -128,7 +128,7 @@ void InstanceScript::LoadObjectData(ObjectData const* creatureData, ObjectData c
if (gameObjectData)
LoadObjectData(gameObjectData, _gameObjectInfo);
TC_LOG_ERROR("scripts", "InstanceScript::LoadObjectData: " SZFMTD " objects loaded.", _creatureInfo.size() + _gameObjectInfo.size());
TC_LOG_DEBUG("scripts", "InstanceScript::LoadObjectData: " SZFMTD " objects loaded.", _creatureInfo.size() + _gameObjectInfo.size());
}
void InstanceScript::LoadObjectData(ObjectData const* data, ObjectInfoMap& objectInfo)
@@ -56,12 +56,12 @@ void RandomMovementGenerator<Creature>::_setRandomLocation(Creature* creature)
Trinity::NormalizeMapCoord(destX);
Trinity::NormalizeMapCoord(destY);
travelDistZ = distanceX*distanceX + distanceY*distanceY;
travelDistZ = range; // sin^2+cos^2=1, so travelDistZ=range^2; no need for sqrt below
if (is_air_ok) // 3D system above ground and above water (flying mode)
{
// Limit height change
const float distanceZ = float(rand_norm()) * std::sqrt(travelDistZ)/2.0f;
const float distanceZ = float(rand_norm()) * travelDistZ/2.0f;
destZ = respZ + distanceZ;
float levelZ = map->GetWaterOrGroundLevel(destX, destY, destZ-2.0f);
@@ -73,7 +73,7 @@ void RandomMovementGenerator<Creature>::_setRandomLocation(Creature* creature)
else // 2D only
{
// 10.0 is the max that vmap high can check (MAX_CAN_FALL_DISTANCE)
travelDistZ = travelDistZ >= 100.0f ? 10.0f : std::sqrt(travelDistZ);
travelDistZ = travelDistZ >= 10.0f ? 10.0f : travelDistZ;
// The fastest way to get an accurate result 90% of the time.
// Better result can be obtained like 99% accuracy with a ray light, but the cost is too high and the code is too long.
+31 -2
View File
@@ -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();
+10
View File
@@ -872,6 +872,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
{
@@ -900,6 +909,7 @@ class ScriptMgr
public: /* Unloading */
void Unload();
void UnloadUnusedScripts();
public: /* SpellScriptLoader */
+59 -47
View File
@@ -324,46 +324,51 @@ 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();
OpcodeHandler const* opHandle = opcodeTable[packet->GetOpcode()];
try
if (packet->GetOpcode() >= NUM_MSG_TYPES)
{
switch (opHandle->Status)
TC_LOG_ERROR("network.opcode", "Received non-existed opcode %s from %s", GetOpcodeNameForLogging(packet->GetOpcode()).c_str()
, GetPlayerInfo().c_str());
sScriptMgr->OnUnknownPacketReceive(this, *packet);
}
else
{
OpcodeHandler& opHandle = opcodeTable[packet->GetOpcode()];
try
{
case STATUS_LOGGEDIN:
if (!_player)
{
// skip STATUS_LOGGEDIN opcode unexpected errors if player logout sometime ago - this can be network lag delayed packets
//! If player didn't log out a while ago, it means packets are being sent while the server does not recognize
//! the client to be in world yet. We will re-add the packets to the bottom of the queue and process them later.
if (!m_playerRecentlyLogout)
switch (opHandle->Status)
{
case STATUS_LOGGEDIN:
if (!_player)
{
//! Prevent infinite loop
if (!firstDelayedPacket)
firstDelayedPacket = packet;
//! Because checking a bool is faster than reallocating memory
deletePacket = false;
QueuePacket(packet);
//! Log
// skip STATUS_LOGGEDIN opcode unexpected errors if player logout sometime ago - this can be network lag delayed packets
//! If player didn't log out a while ago, it means packets are being sent while the server does not recognize
//! the client to be in world yet. We will re-add the packets to the bottom of the queue and process them later.
if (!m_playerRecentlyLogout)
{
//! Prevent infinite loop
if (!firstDelayedPacket)
firstDelayedPacket = packet;
//! Because checking a bool is faster than reallocating memory
deletePacket = false;
QueuePacket(packet);
//! Log
TC_LOG_DEBUG("network", "Re-enqueueing packet with opcode %s with with status STATUS_LOGGEDIN. "
"Player is currently not in world yet.", GetOpcodeNameForLogging(packet->GetOpcode()).c_str());
}
}
else if (_player->IsInWorld())
{
sScriptMgr->OnPacketReceive(this, *packet);
(this->*opHandle->Handler)(*packet);
LogUnprocessedTail(packet);
}
// lag can cause STATUS_LOGGEDIN opcodes to arrive after the player started a transfer
break;
case STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT:
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 (_player->IsInWorld() && AntiDOS.EvaluateOpcode(*packet, currentTime))
{
sScriptMgr->OnPacketReceive(this, *packet);
(this->*opHandle.handler)(*packet);
LogUnprocessedTail(packet);
}
// lag can cause STATUS_LOGGEDIN opcodes to arrive after the player started a transfer
break;
case STATUS_LOGGEDIN_OR_RECENTLY_LOGGOUT:
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 if (AntiDOS.EvaluateOpcode(*packet, currentTime))
{
// not expected _player or must checked in packet hanlder
sScriptMgr->OnPacketReceive(this, *packet);
@@ -376,7 +381,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);
@@ -396,25 +401,29 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater)
if (packet->GetOpcode() == CMSG_CHAR_ENUM)
m_playerRecentlyLogout = false;
sScriptMgr->OnPacketReceive(this, *packet);
if (AntiDOS.EvaluateOpcode(*packet, currentTime))
{
sScriptMgr->OnPacketReceive(this, *packet);
(this->*opHandle->Handler)(*packet);
LogUnprocessedTail(packet);
LogUnprocessedTail(packet);
}
break;
case STATUS_NEVER:
TC_LOG_ERROR("network.opcode", "Received not allowed opcode %s from %s", GetOpcodeNameForLogging(packet->GetOpcode()).c_str()
, GetPlayerInfo().c_str());
break;
case STATUS_UNHANDLED:
TC_LOG_ERROR("network.opcode", "Received not handled opcode %s from %s", GetOpcodeNameForLogging(packet->GetOpcode()).c_str()
break;
case STATUS_UNHANDLED:
TC_LOG_DEBUG("network.opcode", "Received not handled opcode %s from %s", GetOpcodeNameForLogging(packet->GetOpcode()).c_str()
, GetPlayerInfo().c_str());
break;
break;
}
}
catch (ByteBufferException const&)
{
TC_LOG_ERROR("misc", "WorldSession::Update ByteBufferException occured while parsing a packet (opcode: %u) from client %s, accountid=%i. Skipped packet.",
packet->GetOpcode(), GetRemoteAddress().c_str(), GetAccountId());
packet->hexlike();
}
}
catch (ByteBufferException const&)
{
TC_LOG_ERROR("network", "WorldSession::Update ByteBufferException occured while parsing a packet (opcode: %u) from client %s, accountid=%i. Skipped packet.",
packet->GetOpcode(), GetRemoteAddress().c_str(), GetAccountId());
packet->hexlike();
}
if (deletePacket)
@@ -1208,8 +1217,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);
@@ -1223,7 +1235,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
+14 -1
View File
@@ -3450,7 +3450,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;
@@ -7096,6 +7096,19 @@ bool Spell::CallScriptEffectHandlers(SpellEffIndex effIndex, SpellEffectHandleMo
return preventDefault;
}
void Spell::CallScriptSuccessfulDispel(SpellEffIndex effIndex)
{
for (std::list<SpellScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
{
(*scritr)->_PrepareScriptCall(SPELL_SCRIPT_HOOK_EFFECT_SUCCESSFUL_DISPEL);
std::list<SpellScript::EffectHandler>::iterator hookItrEnd = (*scritr)->OnEffectSuccessfulDispel.end(), hookItr = (*scritr)->OnEffectSuccessfulDispel.begin();
for (; hookItr != hookItrEnd; ++hookItr)
hookItr->Call(*scritr, effIndex);
(*scritr)->_FinishScriptCall();
}
}
void Spell::CallScriptBeforeHitHandlers()
{
for (std::list<SpellScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
+1
View File
@@ -649,6 +649,7 @@ class Spell
SpellCastResult CallScriptCheckCastHandlers();
void PrepareScriptHitHandlers();
bool CallScriptEffectHandlers(SpellEffIndex effIndex, SpellEffectHandleMode mode);
void CallScriptSuccessfulDispel(SpellEffIndex effIndex);
void CallScriptBeforeHitHandlers();
void CallScriptOnHitHandlers();
void CallScriptAfterHitHandlers();
+4
View File
@@ -310,6 +310,10 @@ bool SpellScript::_Validate(SpellInfo const* entry)
if (!(*itr).GetAffectedEffectsMask(entry))
TC_LOG_ERROR("scripts", "Spell `%u` Effect `%s` of script `%s` did not match dbc effect data - handler bound to hook `OnEffectHitTarget` of SpellScript won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str());
for (std::list<EffectHandler>::iterator itr = OnEffectSuccessfulDispel.begin(); itr != OnEffectSuccessfulDispel.end(); ++itr)
if (!(*itr).GetAffectedEffectsMask(entry))
TC_LOG_ERROR("scripts", "Spell `%u` Effect `%s` of script `%s` did not match dbc effect data - handler bound to hook `OnEffectSuccessfulDispel` of SpellScript won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str());
for (std::list<ObjectAreaTargetSelectHandler>::iterator itr = OnObjectAreaTargetSelect.begin(); itr != OnObjectAreaTargetSelect.end(); ++itr)
if (!(*itr).GetAffectedEffectsMask(entry))
TC_LOG_ERROR("scripts", "Spell `%u` Effect `%s` of script `%s` did not match dbc effect data - handler bound to hook `OnObjectAreaTargetSelect` of SpellScript won't be executed", entry->Id, (*itr).ToString().c_str(), m_scriptName->c_str());
+5
View File
@@ -130,6 +130,7 @@ enum SpellScriptHookType
SPELL_SCRIPT_HOOK_EFFECT_LAUNCH_TARGET,
SPELL_SCRIPT_HOOK_EFFECT_HIT,
SPELL_SCRIPT_HOOK_EFFECT_HIT_TARGET,
SPELL_SCRIPT_HOOK_EFFECT_SUCCESSFUL_DISPEL,
SPELL_SCRIPT_HOOK_BEFORE_HIT,
SPELL_SCRIPT_HOOK_HIT,
SPELL_SCRIPT_HOOK_AFTER_HIT,
@@ -292,6 +293,7 @@ class SpellScript : public _SpellScript
HookList<EffectHandler> OnEffectLaunchTarget;
HookList<EffectHandler> OnEffectHit;
HookList<EffectHandler> OnEffectHitTarget;
HookList<EffectHandler> OnEffectSuccessfulDispel;
#define SpellEffectFn(F, I, N) EffectHandlerFunction(&F, I, N)
// example: BeforeHit += SpellHitFn(class::function);
@@ -334,6 +336,9 @@ class SpellScript : public _SpellScript
// 11. OnHit - executed just before spell deals damage and procs auras - when spell hits target - called for each target from spell target map
// 12. AfterHit - executed just after spell finishes all it's jobs for target - called for each target from spell target map
// this hook is only executed after a successful dispel of any aura
// OnEffectSuccessfulDispel - executed just after effect successfully dispelled aura(s)
//
// methods allowing interaction with Spell object
//
+4 -4
View File
@@ -532,10 +532,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
+5
View File
@@ -703,6 +703,11 @@ void World::LoadConfigSettings(bool reload)
m_int_configs[CONFIG_MIN_PET_NAME] = 2;
}
m_int_configs[CONFIG_CHARTER_COST_GUILD] = sConfigMgr->GetIntDefault("Guild.CharterCost", 1000);
m_int_configs[CONFIG_CHARTER_COST_ARENA_2v2] = sConfigMgr->GetIntDefault("ArenaTeam.CharterCost.2v2", 800000);
m_int_configs[CONFIG_CHARTER_COST_ARENA_3v3] = sConfigMgr->GetIntDefault("ArenaTeam.CharterCost.3v3", 1200000);
m_int_configs[CONFIG_CHARTER_COST_ARENA_5v5] = sConfigMgr->GetIntDefault("ArenaTeam.CharterCost.5v5", 2000000);
m_int_configs[CONFIG_CHARACTER_CREATING_DISABLED] = sConfigMgr->GetIntDefault("CharacterCreating.Disabled", 0);
m_int_configs[CONFIG_CHARACTER_CREATING_DISABLED_RACEMASK] = sConfigMgr->GetIntDefault("CharacterCreating.Disabled.RaceMask", 0);
m_int_configs[CONFIG_CHARACTER_CREATING_DISABLED_CLASSMASK] = sConfigMgr->GetIntDefault("CharacterCreating.Disabled.ClassMask", 0);
+4
View File
@@ -358,6 +358,10 @@ enum WorldIntConfigs
CONFIG_BG_REWARD_WINNER_CONQUEST_LAST,
CONFIG_CREATURE_PICKPOCKET_REFILL,
CONFIG_AHBOT_UPDATE_INTERVAL,
CONFIG_CHARTER_COST_GUILD,
CONFIG_CHARTER_COST_ARENA_2v2,
CONFIG_CHARTER_COST_ARENA_3v3,
CONFIG_CHARTER_COST_ARENA_5v5,
INT_CONFIG_VALUE_COUNT
};
+2 -2
View File
@@ -489,7 +489,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;
}
@@ -508,7 +508,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;
}
+2 -2
View File
@@ -118,7 +118,7 @@ public:
if (!id)
return false;
uint32 objectId = atol(id);
uint32 objectId = atoul(id);
if (!objectId)
return false;
@@ -240,7 +240,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",
+1 -1
View File
@@ -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))
+8 -8
View File
@@ -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))
{
+7 -7
View File
@@ -1149,7 +1149,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, " ");
@@ -1231,7 +1231,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)
@@ -1372,7 +1372,7 @@ public:
return false;
}
int32 level = uint32(atol(levelStr));
int32 level = atol(levelStr);
Player* target = handler->getSelectedPlayer();
if (!target)
@@ -1394,7 +1394,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;
@@ -1434,7 +1434,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))
@@ -1795,7 +1795,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)
@@ -1993,7 +1993,7 @@ public:
static bool HandleMuteInfoHelper(uint32 accountId, char const* accountName, ChatHandler *handler)
{
PreparedStatement *stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_MUTE_INFO);
stmt->setUInt16(0, accountId);
stmt->setUInt32(0, accountId);
PreparedQueryResult result = LoginDatabase.Query(stmt);
if (!result)
+5 -5
View File
@@ -334,15 +334,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)
{
@@ -572,7 +572,7 @@ public:
handler->SetSentErrorMessage(true);
return false;
}
uint32 itemId = atol(pitem);
uint32 itemId = atoul(pitem);
const uint8 type = 1; // FIXME: make type (1 item, 2 currency) an argument
@@ -1356,7 +1356,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);
+4 -4
View File
@@ -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);
@@ -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)
@@ -25,10 +25,9 @@ EndScriptData */
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "hyjal.h"
#include "SpellAuras.h"
#include "hyjal_trash.h"
#include "SpellScript.h"
#include "Player.h"
#include "hyjal.h"
enum Texts
{
@@ -39,42 +38,59 @@ enum Texts
SAY_ENRAGE = 5,
SAY_DEATH = 6,
SAY_SOUL_CHARGE = 7,
// YELL_ARCHIMONDE_INTRO = 8
};
enum Spells
{
SPELL_DENOUEMENT_WISP = 32124,
SPELL_ANCIENT_SPARK = 39349,
SPELL_PROTECTION_OF_ELUNE = 38528,
SPELL_DENOUEMENT_WISP = 32124,
SPELL_ANCIENT_SPARK = 39349,
SPELL_PROTECTION_OF_ELUNE = 38528,
SPELL_DRAIN_WORLD_TREE = 39140,
SPELL_DRAIN_WORLD_TREE_2 = 39141,
SPELL_DRAIN_WORLD_TREE = 39140,
SPELL_DRAIN_WORLD_TREE_TRIGGERED = 39141,
SPELL_FINGER_OF_DEATH = 31984,
SPELL_HAND_OF_DEATH = 35354,
SPELL_AIR_BURST = 32014,
SPELL_GRIP_OF_THE_LEGION = 31972,
SPELL_DOOMFIRE_STRIKE = 31903, //summons two creatures
SPELL_DOOMFIRE_SPAWN = 32074,
SPELL_DOOMFIRE = 31945,
SPELL_SOUL_CHARGE_YELLOW = 32045,
SPELL_SOUL_CHARGE_GREEN = 32051,
SPELL_SOUL_CHARGE_RED = 32052,
SPELL_UNLEASH_SOUL_YELLOW = 32054,
SPELL_UNLEASH_SOUL_GREEN = 32057,
SPELL_UNLEASH_SOUL_RED = 32053,
SPELL_FEAR = 31970,
SPELL_FINGER_OF_DEATH = 31984,
SPELL_HAND_OF_DEATH = 35354,
SPELL_AIR_BURST = 32014,
SPELL_GRIP_OF_THE_LEGION = 31972,
SPELL_DOOMFIRE_STRIKE = 31903, // summons two creatures
SPELL_DOOMFIRE_SPAWN = 32074,
SPELL_DOOMFIRE = 31945,
SPELL_SOUL_CHARGE_YELLOW = 32045,
SPELL_SOUL_CHARGE_GREEN = 32051,
SPELL_SOUL_CHARGE_RED = 32052,
SPELL_UNLEASH_SOUL_YELLOW = 32054,
SPELL_UNLEASH_SOUL_GREEN = 32057,
SPELL_UNLEASH_SOUL_RED = 32053,
SPELL_FEAR = 31970
};
enum Events
{
EVENT_HAND_OF_DEATH = 1, // 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
};
Position const NordrassilLoc = {5503.713f, -3523.436f, 1608.781f, 0.0f};
enum Actions
{
ACTION_ENRAGE,
ACTION_CHANNEL_WORLD_TREE
};
class npc_ancient_wisp : public CreatureScript
{
@@ -200,7 +216,6 @@ public:
}
void MoveInLineOfSight(Unit* who) override
{
//will update once TargetGUID is 0. In case noone actually moves(not likely) and this is 0
//when UpdateAI needs it, it will be forced to select randomPoint
@@ -249,409 +264,309 @@ class boss_archimonde : public CreatureScript
public:
boss_archimonde() : CreatureScript("boss_archimonde") { }
CreatureAI* GetAI(Creature* creature) const override
struct boss_archimondeAI : public BossAI
{
return GetInstanceAI<boss_archimondeAI>(creature);
}
struct boss_archimondeAI : public hyjal_trashAI
{
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;
_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 InitializeAI() override
{
BossAI::InitializeAI();
DoAction(ACTION_CHANNEL_WORLD_TREE);
}
void Reset() override
{
instance->SetData(DATA_ARCHIMONDEEVENT, NOT_STARTED);
Initialize();
_Reset();
me->RemoveAllAuras(); // Reset Soul Charge auras.
}
void EnterCombat(Unit* /*who*/) override
{
me->InterruptSpell(CURRENT_CHANNELED_SPELL);
Talk(SAY_AGGRO);
DoZoneInCombat();
_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);
}
instance->SetData(DATA_ARCHIMONDEEVENT, IN_PROGRESS);
void ExecuteEvent(uint32 eventId) override
{
switch (eventId)
{
case EVENT_HAND_OF_DEATH:
DoCastAOE(SPELL_HAND_OF_DEATH);
events.ScheduleEvent(EVENT_HAND_OF_DEATH, 2000);
break;
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 = instance->GetCreature(DATA_CHANNEL_TARGET))
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;
}
}
void DamageTaken(Unit* /*attacker*/, uint32 &damage) override
{
if (me->HealthBelowPctDamaged(10, damage))
{
if (!Enraged)
DoAction(ACTION_ENRAGE);
if (!HasProtected)
{
me->GetMotionMaster()->Clear(false);
me->GetMotionMaster()->MoveIdle();
// All members of raid must get this buff
DoCastAOE(SPELL_PROTECTION_OF_ELUNE, true);
HasProtected = true;
events.ScheduleEvent(EVENT_SUMMON_WHISP, 1500);
}
}
}
void KilledUnit(Unit* victim) override
{
Talk(SAY_SLAY);
if (victim && victim->GetTypeId() == TYPEID_PLAYER)
GainSoulCharge(victim->ToPlayer());
}
void GainSoulCharge(Player* victim)
{
switch (victim->getClass())
if (victim->GetTypeId() == TYPEID_PLAYER)
{
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;
}
switch (victim->getClass())
{
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;
}
SoulChargeTimer = urand(2000, 30000);
++SoulChargeCount;
events.ScheduleEvent(EVENT_UNLEASH_SOUL_CHARGE, urand(2000, 30000));
++SoulChargeCount;
}
}
void JustDied(Unit* killer) override
void JustReachedHome() override
{
DoAction(ACTION_CHANNEL_WORLD_TREE);
}
void JustDied(Unit* /*killer*/) override
{
hyjal_trashAI::JustDied(killer);
Talk(SAY_DEATH);
instance->SetData(DATA_ARCHIMONDEEVENT, DONE);
}
bool CanUseFingerOfDeath()
{
// 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)
{
Unit* unit = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid());
if (unit && unit->IsAlive())
targets.push_back(unit);
}
if (targets.empty())
return false;
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()));
}
return false;
_JustDied();
// @todo: remove this when instance script gets updated, kept for compatibility only
instance->SetData(DATA_ARCHIMONDE, DONE);
}
void JustSummoned(Creature* summoned) override
{
if (summoned->GetEntry() == CREATURE_ANCIENT_WISP)
summoned->AI()->AttackStart(me);
else
switch (summoned->GetEntry())
{
summoned->setFaction(me->getFaction());
summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
case NPC_ANCIENT_WISP:
summoned->AI()->AttackStart(me);
break;
case NPC_DOOMFIRE_SPIRIT:
DoomfireSpiritGUID = summoned->GetGUID();
break;
case NPC_DOOMFIRE:
summoned->CastSpell(summoned, SPELL_DOOMFIRE_SPAWN, false);
summoned->CastSpell(summoned, SPELL_DOOMFIRE, true, 0, 0, me->GetGUID());
if (Unit* DoomfireSpirit = ObjectAccessor::GetUnit(*me, DoomfireSpiritGUID))
{
summoned->GetMotionMaster()->MoveFollow(DoomfireSpirit, 0.0f, 0.0f);
DoomfireSpiritGUID.Clear();
}
break;
default:
break;
}
}
if (summoned->GetEntry() == CREATURE_DOOMFIRE_SPIRIT)
void DoAction(int32 actionId) override
{
switch (actionId)
{
DoomfireSpiritGUID = summoned->GetGUID();
}
if (summoned->GetEntry() == CREATURE_DOOMFIRE)
{
summoned->CastSpell(summoned, SPELL_DOOMFIRE_SPAWN, false);
summoned->CastSpell(summoned, SPELL_DOOMFIRE, true, 0, 0, me->GetGUID());
if (Unit* DoomfireSpirit = ObjectAccessor::GetUnit(*me, DoomfireSpiritGUID))
{
summoned->GetMotionMaster()->MoveFollow(DoomfireSpirit, 0.0f, 0.0f);
DoomfireSpiritGUID.Clear();
}
case ACTION_ENRAGE:
me->GetMotionMaster()->Clear(false);
me->GetMotionMaster()->MoveIdle();
Enraged = true;
Talk(SAY_ENRAGE);
break;
case ACTION_CHANNEL_WORLD_TREE:
DoCastAOE(SPELL_DRAIN_WORLD_TREE, true);
break;
default:
break;
}
}
//this is code doing close to what the summoning spell would do (spell 31903)
void SummonDoomfire(Unit* target)
{
me->SummonCreature(CREATURE_DOOMFIRE_SPIRIT,
if (!target)
return;
me->SummonCreature(NPC_DOOMFIRE_SPIRIT,
target->GetPositionX()+15.0f, target->GetPositionY()+15.0f, target->GetPositionZ(), 0,
TEMPSUMMON_TIMED_DESPAWN, 27000);
me->SummonCreature(CREATURE_DOOMFIRE,
me->SummonCreature(NPC_DOOMFIRE,
target->GetPositionX()-15.0f, target->GetPositionY()-15.0f, target->GetPositionZ(), 0,
TEMPSUMMON_TIMED_DESPAWN, 27000);
}
void UnleashSoulCharge()
{
me->InterruptNonMeleeSpells(false);
bool HasCast = false;
uint32 chargeSpell = 0;
uint32 unleashSpell = 0;
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);
HasCast = true;
SoulChargeCount--;
}
if (HasCast)
SoulChargeTimer = urand(2000, 30000);
}
void UpdateAI(uint32 diff) override
{
if (!me->IsInCombat())
{
// 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)
{
Creature* temp = me->SummonCreature(CREATURE_CHANNEL_TARGET, NordrassilLoc, TEMPSUMMON_TIMED_DESPAWN, 1200000);
if (temp)
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;
}
}
if (Unit* Nordrassil = ObjectAccessor::GetUnit(*me, WorldTreeGUID))
{
Nordrassil->CastSpell(me, SPELL_DRAIN_WORLD_TREE_2, true);
DrainNordrassilTimer = 1000;
}
} else DrainNordrassilTimer -= diff;
}
if (!UpdateVictim())
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;
DoMeleeAttackIfReady();
}
void WaypointReached(uint32 /*waypointId*/) override { }
private:
ObjectGuid DoomfireSpiritGUID;
uint8 SoulChargeCount;
uint8 WispCount;
uint32 _chargeSpell;
uint32 _unleashSpell;
bool Enraged;
bool HasProtected;
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetInstanceAI<boss_archimondeAI>(creature);
}
};
// 39142 - Drain World Tree Dummy
class spell_archimonde_drain_world_tree_dummy : public SpellScriptLoader
{
public:
spell_archimonde_drain_world_tree_dummy() : SpellScriptLoader("spell_archimonde_drain_world_tree_dummy") { }
class spell_archimonde_drain_world_tree_dummy_SpellScript : public SpellScript
{
PrepareSpellScript(spell_archimonde_drain_world_tree_dummy_SpellScript);
bool Validate(SpellInfo const* /*spellInfo*/) override
{
if (!sSpellMgr->GetSpellInfo(SPELL_DRAIN_WORLD_TREE_TRIGGERED))
return false;
return true;
}
void HandleScript(SpellEffIndex /*effIndex*/)
{
if (Unit* target = GetHitUnit())
target->CastSpell(GetCaster(), SPELL_DRAIN_WORLD_TREE_TRIGGERED, true);
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_archimonde_drain_world_tree_dummy_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_DUMMY);
}
};
SpellScript* GetSpellScript() const override
{
return new spell_archimonde_drain_world_tree_dummy_SpellScript();
}
};
void AddSC_boss_archimonde()
@@ -660,4 +575,5 @@ void AddSC_boss_archimonde()
new npc_doomfire();
new npc_doomfire_targetting();
new npc_ancient_wisp();
new spell_archimonde_drain_world_tree_dummy();
}
@@ -44,7 +44,8 @@ enum DataTypes
DATA_HORDE_RETREAT = 17,
DATA_RAIDDAMAGE = 18,
DATA_RESET_RAIDDAMAGE = 19,
TYPE_RETREAT = 20
TYPE_RETREAT = 20,
DATA_CHANNEL_TARGET = 21
};
enum WorldStateIds
@@ -77,7 +78,8 @@ enum CreaturesIds
KAZROGAL = 17888,
AZGALOR = 17842,
ARCHIMONDE = 17968,
NPC_WORLD_TRIGGER_TINY = 21987
NPC_WORLD_TRIGGER_TINY = 21987,
NPC_CHANNEL_TARGET = 22418
};
enum GameobjectIds
@@ -89,5 +91,6 @@ enum GameobjectIds
GO_ROARING_FLAME = 182592
};
#endif
#define MINRAIDDAMAGE 700000 // minimal damage before trash can drop loot and reputation, resets if faction leader dies
#endif
@@ -26,7 +26,6 @@ enum Spells
SPELL_METEOR = 33814, //infernal visual
SPELL_IMMOLATION = 37059,
SPELL_FLAME_BUFFET = 31724,
NPC_TRIGGER = 21987, //World Trigger (Tiny)
MODEL_INVIS = 11686, //invisible model
SPELL_DISEASE_CLOUD = 31607,
SPELL_KNOCKDOWN = 31610,
@@ -465,10 +464,7 @@ public:
}
if (!meteor)
{
float x, y, z;
me->GetPosition(x, y, z);
Creature* trigger = me->SummonCreature(NPC_TRIGGER, x + 8, y + 8, z + 25 + rand32() % 10, me->GetOrientation(), TEMPSUMMON_TIMED_DESPAWN, 1000);
if (trigger)
if (Creature* trigger = me->SummonCreature(NPC_WORLD_TRIGGER_TINY, me->GetPositionWithOffset({ 8.0f, 8.0f, frand(25.0f, 35.0f), 0.0f }), TEMPSUMMON_TIMED_DESPAWN, 1000))
{
trigger->SetVisible(false);
trigger->setFaction(me->getFaction());
@@ -21,8 +21,6 @@
#include "hyjal.h"
#include "ScriptedEscortAI.h"
#define MINRAIDDAMAGE 700000//minimal damage before trash can drop loot and reputation, resets if faction leader dies
struct hyjal_trashAI : public npc_escortAI
{
hyjal_trashAI(Creature* creature);
@@ -40,8 +40,16 @@ EndScriptData */
4 - Archimonde event
*/
#define YELL_EFFORTS "All of your efforts have been in vain, for the draining of the World Tree has already begun. Soon the heart of your world will beat no more."
#define YELL_EFFORTS_NAME "Archimonde"
enum Yells
{
YELL_ARCHIMONDE_INTRO = 8
};
ObjectData const creatureData[] =
{
{ NPC_CHANNEL_TARGET, DATA_CHANNEL_TARGET },
{ 0, 0 } // END
};
class instance_hyjal : public InstanceMapScript
{
@@ -58,6 +66,7 @@ public:
instance_mount_hyjal_InstanceMapScript(Map* map) : InstanceScript(map)
{
SetHeaders(DataHeader);
LoadObjectData(creatureData, nullptr);
memset(&m_auiEncounter, 0, sizeof(m_auiEncounter));
RaidDamage = 0;
@@ -105,15 +114,35 @@ 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;
}
InstanceScript::OnCreatureCreate(creature);
}
ObjectGuid GetGuidData(uint32 identifier) const override
@@ -147,40 +176,19 @@ public:
m_auiEncounter[2] = data;
break;
case DATA_AZGALOREVENT:
m_auiEncounter[3] = data;
if (data == DONE)
{
m_auiEncounter[3] = data;
if (data == DONE)
instance->LoadGrid(5581.49f, -3445.63f);
if (Creature* archimonde = instance->GetCreature(Archimonde))
{
if (ArchiYell)
break;
archimonde->SetVisible(true);
ArchiYell = true;
Creature* creature = instance->GetCreature(Azgalor);
if (creature)
if (!ArchiYell)
{
Creature* unit = creature->SummonCreature(NPC_WORLD_TRIGGER_TINY, creature->GetPositionX(), creature->GetPositionY(), creature->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 10000);
ArchiYell = true;
archimonde->AI()->Talk(YELL_ARCHIMONDE_INTRO);
Map* map = creature->GetMap();
if (map->IsDungeon() && unit)
{
unit->SetVisible(false);
Map::PlayerList const &PlayerList = map->GetPlayers();
if (PlayerList.isEmpty())
return;
for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
{
if (Player* player = i->GetSource())
{
WorldPacket packet;
ChatHandler::BuildChatPacket(packet, CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, unit, player, YELL_EFFORTS);
player->SendDirectMessage(&packet);
player->PlayDirectSound(10986, player);
}
}
}
}
}
}
@@ -292,6 +292,7 @@ public:
break;
}
player->CLOSE_GOSSIP_MENU();
ai->SetDespawnAtFar(false);
creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
return true;
}
@@ -19,13 +19,15 @@
/* ScriptData
SDName: Dustwallow_Marsh
SD%Complete: 95
SDComment: Quest support: 1270, 1222, 27245
SDComment: Quest support: 558, 11126, 11142, 11174, Vendor Nat Pagle
SDCategory: Dustwallow Marsh
EndScriptData */
/* ContentData
npc_stinky
go_blackhoof_cage
npc_lady_jaina_proudmoore
npc_nat_pagle
npc_private_hendel
npc_cassa_crimsonwing - handled by npc_taxi
EndContentData */
#include "ScriptMgr.h"
@@ -36,99 +38,6 @@ EndContentData */
#include "Player.h"
#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
######*/
@@ -366,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
{
@@ -631,41 +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_stinky();
new npc_lady_jaina_proudmoore();
new npc_nat_pagle();
new npc_private_hendel();
new npc_zelfrax();
new spell_ooze_zap();
new spell_ooze_zap_channel_end();
new spell_energize_aoe();
new go_blackhoof_cage();
}
@@ -362,7 +362,7 @@ class NecroticPlagueTargetCheck : public std::unary_function<Unit*, bool>
bool operator()(Unit* unit) const
{
if (!unit || unit == _sourceObj || !unit->isTargetableForAttack() || unit->IsTotem() || unit->HasAura(SPELL_PLAGUE_AVOIDANCE))
if (!unit || unit == _sourceObj || !unit->isTargetableForAttack() || unit->GetTypeId() != TYPEID_PLAYER || unit->HasAura(SPELL_PLAGUE_AVOIDANCE))
return false;
if ((_notAura1 && unit->HasAura(_notAura1)) || (_notAura2 && unit->HasAura(_notAura2)))
return false;
@@ -30,26 +30,23 @@ EndScriptData */
#include "naxxramas.h"
#include "Player.h"
enum Yells
enum Texts
{
//when shappiron dies. dialog between kel and lich king (in this order)
SAY_SAPP_DIALOG1 = 0, //not used
SAY_SAPP_DIALOG2_LICH = 1, //not used
SAY_SAPP_DIALOG3 = 2, //not used
SAY_SAPP_DIALOG4_LICH = 3, //not used
SAY_SAPP_DIALOG5 = 4, //not used
SAY_CAT_DIED = 5, //when cat dies, not used
//when each of the 4 wing bosses dies
SAY_TAUNT = 6,
SAY_AGGRO = 7,
SAY_SLAY = 8,
SAY_DEATH = 9,
SAY_CHAIN = 10,
SAY_FROST_BLAST = 11,
SAY_REQUEST_AID = 12, //start of phase 3
SAY_ANSWER_REQUEST = 13, //lich king answer
EMOTE_PHASE_TWO = 13,
SAY_SUMMON_MINIONS = 14, //start of phase 1
SAY_SPECIAL = 15
SAY_SPECIAL = 15,
// The Lich King
SAY_ANSWER_REQUEST = 3,
// Old World Trigger
SAY_GUARDIAN_SPAWNED = 0
};
enum Events
@@ -70,7 +67,10 @@ enum Events
EVENT_TRIGGER,
EVENT_PHASE,
EVENT_MORTAL_WOUND
EVENT_MORTAL_WOUND,
EVENT_ANSWER_REQUEST,
EVENT_SUMMON_GUARDIANS
};
enum Spells
@@ -123,6 +123,13 @@ enum Spells
SPELL_MORTAL_WOUND = 28467
};
enum Phases
{
PHASE_ONE = 1, // Players move in the circle and Kel'Thuzad spawns his minions.
PHASE_TWO = 2, // Starts on a timer.
PHASE_THREE = 3 // At 45% health.
};
enum Creatures
{
NPC_WASTE = 16427, // Soldiers of the Frozen Wastes
@@ -270,15 +277,11 @@ public:
void Initialize()
{
nGuardiansOfIcecrownCount = 0;
uiGuardiansOfIcecrownTimer = 5000; // 5 seconds for summoning each Guardian of Icecrown in phase 3
Phase = 0;
nAbomination = 0;
nWeaver = 0;
}
uint32 Phase;
uint32 uiGuardiansOfIcecrownTimer;
uint32 uiFaction;
uint8 nGuardiansOfIcecrownCount;
@@ -345,7 +348,6 @@ public:
void EnterCombat(Unit* /*who*/) override
{
me->setFaction(uiFaction);
_EnterCombat();
for (uint8 i = 0; i <= 3; ++i)
{
@@ -354,10 +356,10 @@ public:
}
DoCast(me, SPELL_KELTHUZAD_CHANNEL, false);
Talk(SAY_SUMMON_MINIONS);
Phase = 1;
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_NOT_SELECTABLE);
me->SetFloatValue(UNIT_FIELD_COMBATREACH, 4);
me->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, 4);
events.SetPhase(PHASE_ONE);
events.ScheduleEvent(EVENT_TRIGGER, 5000);
events.ScheduleEvent(EVENT_WASTE, 15000);
events.ScheduleEvent(EVENT_ABOMIN, 30000);
@@ -365,6 +367,23 @@ public:
events.ScheduleEvent(EVENT_PHASE, 228000);
}
void DamageTaken(Unit* /*attacker*/, uint32& damage) override
{
if (events.IsInPhase(PHASE_TWO) && me->HealthBelowPctDamaged(45, damage))
{
Talk(SAY_REQUEST_AID);
events.SetPhase(PHASE_THREE);
events.ScheduleEvent(EVENT_ANSWER_REQUEST, 4000);
for (uint8 i = 0; i <= 3; ++i)
{
if (GameObject* portal = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(DATA_KELTHUZAD_PORTAL01 + i)))
if (portal->getLootState() == GO_READY)
portal->UseDoorOrButton();
}
}
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
@@ -372,7 +391,7 @@ public:
events.Update(diff);
if (Phase == 1)
if (events.IsInPhase(PHASE_ONE))
{
while (uint32 eventId = events.ExecuteEvent())
{
@@ -405,6 +424,7 @@ public:
case EVENT_PHASE:
events.Reset();
Talk(SAY_AGGRO);
Talk(EMOTE_PHASE_TWO);
spawns.DespawnAll();
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE | UNIT_FLAG_NOT_SELECTABLE);
me->CastStop();
@@ -417,7 +437,7 @@ public:
events.ScheduleEvent(EVENT_BLAST, urand(60000, 120000));
if (GetDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL)
events.ScheduleEvent(EVENT_CHAIN, urand(30000, 60000));
Phase = 2;
events.SetPhase(PHASE_TWO);
break;
default:
break;
@@ -426,38 +446,6 @@ public:
}
else
{
//start phase 3 when we are 45% health
if (Phase != 3)
{
if (HealthBelowPct(45))
{
Phase = 3;
Talk(SAY_REQUEST_AID);
//here Lich King should respond to KelThuzad but I don't know which Creature to make talk
//so for now just make Kelthuzad says it.
Talk(SAY_ANSWER_REQUEST);
for (uint8 i = 0; i <= 3; ++i)
{
if (GameObject* portal = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(DATA_KELTHUZAD_PORTAL01 + i)))
if (portal->getLootState() == GO_READY)
portal->UseDoorOrButton();
}
}
}
else if (nGuardiansOfIcecrownCount < RAID_MODE(2, 4))
{
if (uiGuardiansOfIcecrownTimer <= diff)
{
/// @todo Add missing text
if (Creature* guardian = DoSummon(NPC_ICECROWN, Pos[RAND(2, 5, 8, 11)]))
guardian->SetFloatValue(UNIT_FIELD_COMBATREACH, 2);
++nGuardiansOfIcecrownCount;
uiGuardiansOfIcecrownTimer = 5000;
}
else uiGuardiansOfIcecrownTimer -= diff;
}
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
@@ -609,6 +597,18 @@ public:
Talk(SAY_FROST_BLAST);
events.Repeat(30000, 90000);
break;
case EVENT_ANSWER_REQUEST:
if (Creature* lichKing = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_LICH_KING)))
lichKing->AI()->Talk(SAY_ANSWER_REQUEST);
events.ScheduleEvent(EVENT_SUMMON_GUARDIANS, 5000);
break;
case EVENT_SUMMON_GUARDIANS:
if (Creature* guardian = DoSummon(NPC_ICECROWN, Pos[RAND(2, 5, 8, 11)]))
guardian->SetFloatValue(UNIT_FIELD_COMBATREACH, 2);
++nGuardiansOfIcecrownCount;
if (nGuardiansOfIcecrownCount < RAID_MODE(2, 4))
events.ScheduleEvent(EVENT_SUMMON_GUARDIANS, 5000);
break;
default:
break;
}
@@ -69,6 +69,15 @@ MinionData const minionData[] =
{ 0, 0, }
};
ObjectData const objectData[] =
{
{ GO_NAXX_PORTAL_ARACHNID, DATA_NAXX_PORTAL_ARACHNID },
{ GO_NAXX_PORTAL_CONSTRUCT, DATA_NAXX_PORTAL_CONSTRUCT },
{ GO_NAXX_PORTAL_PLAGUE, DATA_NAXX_PORTAL_PLAGUE },
{ GO_NAXX_PORTAL_MILITARY, DATA_NAXX_PORTAL_MILITARY },
{ 0, 0, }
};
float const HeiganPos[2] = { 2796.0f, -3707.0f };
float const HeiganEruptionSlope[3] =
{
@@ -111,10 +120,12 @@ class instance_naxxramas : public InstanceMapScript
SetBossNumber(EncounterCount);
LoadDoorData(doorData);
LoadMinionData(minionData);
LoadObjectData(nullptr, objectData);
minHorsemenDiedTime = 0;
maxHorsemenDiedTime = 0;
AbominationCount = 0;
CurrentWingTaunt = SAY_KELTHUZAD_FIRST_WING_TAUNT;
playerDied = 0;
}
@@ -156,6 +167,9 @@ class instance_naxxramas : public InstanceMapScript
case NPC_KEL_THUZAD:
KelthuzadGUID = creature->GetGUID();
break;
case NPC_LICH_KING:
LichKingGUID = creature->GetGUID();
break;
default:
break;
}
@@ -201,11 +215,30 @@ class instance_naxxramas : public InstanceMapScript
case GO_KELTHUZAD_TRIGGER:
KelthuzadTriggerGUID = go->GetGUID();
break;
case GO_ROOM_KELTHUZAD:
KelthuzadDoorGUID = go->GetGUID();
break;
case GO_NAXX_PORTAL_ARACHNID:
if (GetBossState(BOSS_MAEXXNA) == DONE)
go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
break;
case GO_NAXX_PORTAL_CONSTRUCT:
if (GetBossState(BOSS_THADDIUS) == DONE)
go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
break;
case GO_NAXX_PORTAL_PLAGUE:
if (GetBossState(BOSS_LOATHEB) == DONE)
go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
break;
case GO_NAXX_PORTAL_MILITARY:
if (GetBossState(BOSS_HORSEMEN) == DONE)
go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
break;
default:
break;
}
AddDoor(go, true);
InstanceScript::OnGameObjectCreate(go);
}
void OnGameObjectRemove(GameObject* go) override
@@ -232,7 +265,7 @@ class instance_naxxramas : public InstanceMapScript
break;
}
AddDoor(go, false);
InstanceScript::OnGameObjectRemove(go);
}
void OnUnitDeath(Unit* unit) override
@@ -242,6 +275,15 @@ class instance_naxxramas : public InstanceMapScript
playerDied = 1;
SaveToDB();
}
if (Creature* creature = unit->ToCreature())
if (creature->GetEntry() == NPC_BIGGLESWORTH)
{
// Loads Kel'Thuzad's grid. We need this as he must be active in order for his texts to work.
instance->LoadGrid(3749.67f, -5114.06f);
if (Creature* kelthuzad = instance->GetCreature(KelthuzadGUID))
kelthuzad->AI()->Talk(SAY_KELTHUZAD_CAT_DIED);
}
}
void SetData(uint32 id, uint32 value) override
@@ -327,6 +369,8 @@ class instance_naxxramas : public InstanceMapScript
return PortalsGUID[3];
case DATA_KELTHUZAD_TRIGGER:
return KelthuzadTriggerGUID;
case DATA_LICH_KING:
return LichKingGUID;
}
return ObjectGuid::Empty;
@@ -337,18 +381,156 @@ class instance_naxxramas : public InstanceMapScript
if (!InstanceScript::SetBossState(id, state))
return false;
if (id == BOSS_HORSEMEN && state == DONE)
switch (id)
{
if (GameObject* horsemenChest = instance->GetGameObject(HorsemenChestGUID))
{
horsemenChest->SetRespawnTime(horsemenChest->GetRespawnDelay());
horsemenChest->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
}
case BOSS_MAEXXNA:
if (state == DONE)
{
if (GameObject* teleporter = GetGameObject(DATA_NAXX_PORTAL_ARACHNID))
teleporter->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
events.ScheduleEvent(EVENT_KELTHUZAD_WING_TAUNT, 6000);
}
break;
case BOSS_LOATHEB:
if (state == DONE)
{
if (GameObject* teleporter = GetGameObject(DATA_NAXX_PORTAL_PLAGUE))
teleporter->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
events.ScheduleEvent(EVENT_KELTHUZAD_WING_TAUNT, 6000);
}
break;
case BOSS_THADDIUS:
if (state == DONE)
{
if (GameObject* teleporter = GetGameObject(DATA_NAXX_PORTAL_CONSTRUCT))
teleporter->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
events.ScheduleEvent(EVENT_KELTHUZAD_WING_TAUNT, 6000);
}
break;
case BOSS_GOTHIK:
if (state == DONE)
events.ScheduleEvent(EVENT_DIALOGUE_GOTHIK_KORTHAZZ, 10000);
break;
case BOSS_HORSEMEN:
if (state == DONE)
{
if (GameObject* horsemenChest = instance->GetGameObject(HorsemenChestGUID))
{
horsemenChest->SetRespawnTime(horsemenChest->GetRespawnDelay());
horsemenChest->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
}
if (GameObject* teleporter = GetGameObject(DATA_NAXX_PORTAL_MILITARY))
teleporter->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
events.ScheduleEvent(EVENT_KELTHUZAD_WING_TAUNT, 6000);
}
break;
case BOSS_SAPPHIRON:
if (state == DONE)
events.ScheduleEvent(EVENT_DIALOGUE_SAPPHIRON_KELTHUZAD, 6000);
break;
default:
break;
}
return true;
}
void Update(uint32 diff) override
{
events.Update(diff);
while (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_DIALOGUE_GOTHIK_KORTHAZZ:
if (Creature* korthazz = instance->GetCreature(ThaneGUID))
korthazz->AI()->Talk(SAY_DIALOGUE_GOTHIK_HORSEMAN);
events.ScheduleEvent(EVENT_DIALOGUE_GOTHIK_ZELIEK, 5000);
break;
case EVENT_DIALOGUE_GOTHIK_ZELIEK:
if (Creature* zeliek = instance->GetCreature(SirGUID))
zeliek->AI()->Talk(SAY_DIALOGUE_GOTHIK_HORSEMAN);
events.ScheduleEvent(EVENT_DIALOGUE_GOTHIK_BLAUMEUX, 6000);
break;
case EVENT_DIALOGUE_GOTHIK_BLAUMEUX:
if (Creature* blaumeux = instance->GetCreature(LadyGUID))
blaumeux->AI()->Talk(SAY_DIALOGUE_GOTHIK_HORSEMAN);
events.ScheduleEvent(EVENT_DIALOGUE_GOTHIK_RIVENDARE, 6000);
break;
case EVENT_DIALOGUE_GOTHIK_RIVENDARE:
if (Creature* rivendare = instance->GetCreature(BaronGUID))
rivendare->AI()->Talk(SAY_DIALOGUE_GOTHIK_HORSEMAN);
events.ScheduleEvent(EVENT_DIALOGUE_GOTHIK_BLAUMEUX2, 6000);
break;
case EVENT_DIALOGUE_GOTHIK_BLAUMEUX2:
if (Creature* blaumeux = instance->GetCreature(LadyGUID))
blaumeux->AI()->Talk(SAY_DIALOGUE_GOTHIK_HORSEMAN2);
events.ScheduleEvent(EVENT_DIALOGUE_GOTHIK_ZELIEK2, 6000);
break;
case EVENT_DIALOGUE_GOTHIK_ZELIEK2:
if (Creature* zeliek = instance->GetCreature(SirGUID))
zeliek->AI()->Talk(SAY_DIALOGUE_GOTHIK_HORSEMAN2);
events.ScheduleEvent(EVENT_DIALOGUE_GOTHIK_KORTHAZZ2, 6000);
break;
case EVENT_DIALOGUE_GOTHIK_KORTHAZZ2:
if (Creature* korthazz = instance->GetCreature(ThaneGUID))
korthazz->AI()->Talk(SAY_DIALOGUE_GOTHIK_HORSEMAN2);
events.ScheduleEvent(EVENT_DIALOGUE_GOTHIK_RIVENDARE2, 6000);
break;
case EVENT_DIALOGUE_GOTHIK_RIVENDARE2:
if (Creature* rivendare = instance->GetCreature(BaronGUID))
rivendare->AI()->Talk(SAY_DIALOGUE_GOTHIK_HORSEMAN2);
break;
case EVENT_KELTHUZAD_WING_TAUNT:
// Loads Kel'Thuzad's grid. We need this as he must be active in order for his texts to work.
instance->LoadGrid(3749.67f, -5114.06f);
if (Creature* kelthuzad = instance->GetCreature(KelthuzadGUID))
kelthuzad->AI()->Talk(CurrentWingTaunt);
++CurrentWingTaunt;
break;
case EVENT_DIALOGUE_SAPPHIRON_KELTHUZAD:
if (Creature* kelthuzad = instance->GetCreature(KelthuzadGUID))
kelthuzad->AI()->Talk(SAY_DIALOGUE_SAPPHIRON_KELTHUZAD);
HandleGameObject(KelthuzadDoorGUID, false);
events.ScheduleEvent(EVENT_DIALOGUE_SAPPHIRON_LICHKING, 6000);
break;
case EVENT_DIALOGUE_SAPPHIRON_LICHKING:
if (Creature* lichKing = instance->GetCreature(LichKingGUID))
lichKing->AI()->Talk(SAY_DIALOGUE_SAPPHIRON_LICH_KING);
events.ScheduleEvent(EVENT_DIALOGUE_SAPPHIRON_KELTHUZAD2, 16000);
break;
case EVENT_DIALOGUE_SAPPHIRON_KELTHUZAD2:
if (Creature* kelthuzad = instance->GetCreature(KelthuzadGUID))
kelthuzad->AI()->Talk(SAY_DIALOGUE_SAPPHIRON_KELTHUZAD2);
events.ScheduleEvent(EVENT_DIALOGUE_SAPPHIRON_LICHKING2, 9000);
break;
case EVENT_DIALOGUE_SAPPHIRON_LICHKING2:
if (Creature* lichKing = instance->GetCreature(LichKingGUID))
lichKing->AI()->Talk(SAY_DIALOGUE_SAPPHIRON_LICH_KING2);
events.ScheduleEvent(EVENT_DIALOGUE_SAPPHIRON_KELTHUZAD3, 12000);
break;
case EVENT_DIALOGUE_SAPPHIRON_KELTHUZAD3:
if (Creature* kelthuzad = instance->GetCreature(KelthuzadGUID))
kelthuzad->AI()->Talk(SAY_DIALOGUE_SAPPHIRON_KELTHUZAD3);
events.ScheduleEvent(EVENT_DIALOGUE_SAPPHIRON_KELTHUZAD4, 6000);
break;
case EVENT_DIALOGUE_SAPPHIRON_KELTHUZAD4:
if (Creature* kelthuzad = instance->GetCreature(KelthuzadGUID))
kelthuzad->AI()->Talk(SAY_DIALOGUE_SAPPHIRON_KELTHUZAD4);
HandleGameObject(KelthuzadDoorGUID, true);
break;
default:
break;
}
}
}
void HeiganErupt(uint32 section)
{
for (uint32 i = 0; i < 4; ++i)
@@ -450,10 +632,15 @@ class instance_naxxramas : public InstanceMapScript
ObjectGuid KelthuzadGUID;
ObjectGuid KelthuzadTriggerGUID;
ObjectGuid PortalsGUID[4];
ObjectGuid KelthuzadDoorGUID;
ObjectGuid LichKingGUID;
uint8 AbominationCount;
uint8 CurrentWingTaunt;
/* The Immortal / The Undying */
uint32 playerDied;
EventMap events;
};
InstanceScript* GetInstanceScript(InstanceMap* map) const override
@@ -52,6 +52,11 @@ enum Data
DATA_HORSEMEN2,
DATA_HORSEMEN3,
DATA_ABOMINATION_KILLED,
DATA_NAXX_PORTAL_ARACHNID,
DATA_NAXX_PORTAL_CONSTRUCT,
DATA_NAXX_PORTAL_PLAGUE,
DATA_NAXX_PORTAL_MILITARY
};
enum Data64
@@ -71,6 +76,7 @@ enum Data64
DATA_KELTHUZAD_PORTAL03,
DATA_KELTHUZAD_PORTAL04,
DATA_KELTHUZAD_TRIGGER,
DATA_LICH_KING
};
enum CreaturesIds
@@ -89,7 +95,10 @@ enum CreaturesIds
NPC_CRYPT_GUARD = 16573,
NPC_NAXXRAMAS_FOLLOWER = 16505,
NPC_FOLLOWER_WORSHIPPER = 16506,
NPC_DK_UNDERSTUDY = 16803
NPC_DK_UNDERSTUDY = 16803,
NPC_BIGGLESWORTH = 16998,
NPC_LICH_KING = 16980,
NPC_OLD_WORLD_TRIGGER = 15384
};
enum GameObjectsIds
@@ -133,7 +142,13 @@ enum GameObjectsIds
GO_CONS_EYE_RAMP_BOSS = 181232,
GO_CONS_NOX_TESLA_FEUGEN = 181477,
GO_CONS_NOX_TESLA_STALAGG = 181478,
GO_BIRTH = 181356
GO_BIRTH = 181356,
// Teleporting pads spawned by the end of every quarter.
GO_NAXX_PORTAL_ARACHNID = 181575,
GO_NAXX_PORTAL_CONSTRUCT = 181576,
GO_NAXX_PORTAL_PLAGUE = 181577,
GO_NAXX_PORTAL_MILITARY = 181578
};
enum SpellIds
@@ -142,6 +157,50 @@ enum SpellIds
SPELL_SLIME = 28801
};
enum InstanceEvents
{
// Dialogue that happens after Gothik's death.
EVENT_DIALOGUE_GOTHIK_KORTHAZZ = 1,
EVENT_DIALOGUE_GOTHIK_ZELIEK,
EVENT_DIALOGUE_GOTHIK_BLAUMEUX,
EVENT_DIALOGUE_GOTHIK_RIVENDARE,
EVENT_DIALOGUE_GOTHIK_BLAUMEUX2,
EVENT_DIALOGUE_GOTHIK_ZELIEK2,
EVENT_DIALOGUE_GOTHIK_KORTHAZZ2,
EVENT_DIALOGUE_GOTHIK_RIVENDARE2,
// Dialogue that happens after each wing.
EVENT_KELTHUZAD_WING_TAUNT,
// Dialogue that happens after Sapphiron's death.
EVENT_DIALOGUE_SAPPHIRON_KELTHUZAD,
EVENT_DIALOGUE_SAPPHIRON_LICHKING,
EVENT_DIALOGUE_SAPPHIRON_KELTHUZAD2,
EVENT_DIALOGUE_SAPPHIRON_LICHKING2,
EVENT_DIALOGUE_SAPPHIRON_KELTHUZAD3,
EVENT_DIALOGUE_SAPPHIRON_KELTHUZAD4
};
enum InstanceTexts
{
// The Four Horsemen
SAY_DIALOGUE_GOTHIK_HORSEMAN = 5,
SAY_DIALOGUE_GOTHIK_HORSEMAN2 = 6,
// Kel'Thuzad
SAY_DIALOGUE_SAPPHIRON_KELTHUZAD = 0,
SAY_DIALOGUE_SAPPHIRON_KELTHUZAD2 = 2,
SAY_DIALOGUE_SAPPHIRON_KELTHUZAD3 = 4,
SAY_DIALOGUE_SAPPHIRON_KELTHUZAD4 = 20,
SAY_KELTHUZAD_CAT_DIED = 5,
SAY_KELTHUZAD_FIRST_WING_TAUNT = 16,
// Lich King
SAY_DIALOGUE_SAPPHIRON_LICH_KING = 1,
SAY_DIALOGUE_SAPPHIRON_LICH_KING2 = 2
};
/*
template<class AI>
CreatureAI* GetNaxxramasAI(Creature* creature)
@@ -100,21 +100,21 @@ class boss_anomalus : public CreatureScript
{
Initialize();
instance->SetData(DATA_ANOMALUS_EVENT, NOT_STARTED);
instance->SetBossState(DATA_ANOMALUS, NOT_STARTED);
}
void EnterCombat(Unit* /*who*/) override
{
Talk(SAY_AGGRO);
instance->SetData(DATA_ANOMALUS_EVENT, IN_PROGRESS);
instance->SetBossState(DATA_ANOMALUS, IN_PROGRESS);
}
void JustDied(Unit* /*killer*/) override
{
Talk(SAY_DEATH);
instance->SetData(DATA_ANOMALUS_EVENT, DONE);
instance->SetBossState(DATA_ANOMALUS, DONE);
}
uint32 GetData(uint32 type) const override
@@ -101,7 +101,7 @@ public:
RemovePrison(CheckContainmentSpheres());
instance->SetData(DATA_KERISTRASZA_EVENT, NOT_STARTED);
instance->SetBossState(DATA_KERISTRASZA, NOT_STARTED);
}
void EnterCombat(Unit* /*who*/) override
@@ -109,14 +109,14 @@ public:
Talk(SAY_AGGRO);
DoCastAOE(SPELL_INTENSE_COLD);
instance->SetData(DATA_KERISTRASZA_EVENT, IN_PROGRESS);
instance->SetBossState(DATA_KERISTRASZA, IN_PROGRESS);
}
void JustDied(Unit* /*killer*/) override
{
Talk(SAY_DEATH);
instance->SetData(DATA_KERISTRASZA_EVENT, DONE);
instance->SetBossState(DATA_KERISTRASZA, DONE);
}
void KilledUnit(Unit* who) override
@@ -31,7 +31,9 @@ enum Spells
SPELL_FIRE_MAGUS_VISUAL = 47705,
SPELL_FROST_MAGUS_VISUAL = 47706,
SPELL_ARCANE_MAGUS_VISUAL = 47704
SPELL_ARCANE_MAGUS_VISUAL = 47704,
SPELL_WEAR_CHRISTMAS_HAT = 61400
};
enum Creatures
@@ -53,7 +55,9 @@ enum Yells
enum Misc
{
ACTION_MAGUS_DEAD = 1,
DATA_SPLIT_PERSONALITY = 2
DATA_SPLIT_PERSONALITY = 2,
GAME_EVENT_WINTER_VEIL = 2,
};
const Position CenterOfRoom = {504.80f, 89.07f, -16.12f, 6.27f};
@@ -128,21 +132,24 @@ public:
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
me->SetVisible(true);
instance->SetData(DATA_MAGUS_TELESTRA_EVENT, NOT_STARTED);
instance->SetBossState(DATA_MAGUS_TELESTRA, NOT_STARTED);
if (IsHeroic() && sGameEventMgr->IsActiveEvent(GAME_EVENT_WINTER_VEIL) && !me->HasAura(SPELL_WEAR_CHRISTMAS_HAT))
me->AddAura(SPELL_WEAR_CHRISTMAS_HAT, me);
}
void EnterCombat(Unit* /*who*/) override
{
Talk(SAY_AGGRO);
instance->SetData(DATA_MAGUS_TELESTRA_EVENT, IN_PROGRESS);
instance->SetBossState(DATA_MAGUS_TELESTRA, IN_PROGRESS);
}
void JustDied(Unit* /*killer*/) override
{
Talk(SAY_DEATH);
instance->SetData(DATA_MAGUS_TELESTRA_EVENT, DONE);
instance->SetBossState(DATA_MAGUS_TELESTRA, DONE);
}
void KilledUnit(Unit* who) override
@@ -68,7 +68,7 @@ public:
struct boss_ormorokAI : public BossAI
{
boss_ormorokAI(Creature* creature) : BossAI(creature, DATA_ORMOROK_EVENT)
boss_ormorokAI(Creature* creature) : BossAI(creature, DATA_ORMOROK)
{
Initialize();
}
@@ -95,8 +95,6 @@ public:
events.ScheduleEvent(EVENT_CRYSTALLINE_TANGLER, 17000);
Talk(SAY_AGGRO);
instance->SetData(DATA_ORMOROK_EVENT, IN_PROGRESS);
}
void DamageTaken(Unit* /*attacker*/, uint32& /*damage*/) override
@@ -112,10 +110,7 @@ public:
void JustDied(Unit* /*killer*/) override
{
_JustDied();
Talk(SAY_DEATH);
instance->SetData(DATA_ORMOROK_EVENT, DONE);
}
void KilledUnit(Unit* who) override
@@ -138,27 +133,27 @@ public:
{
switch (eventId)
{
case EVENT_TRAMPLE:
DoCast(me, SPELL_TRAMPLE);
events.ScheduleEvent(EVENT_TRAMPLE, 10000);
break;
case EVENT_SPELL_REFLECTION:
Talk(SAY_REFLECT);
DoCast(me, SPELL_SPELL_REFLECTION);
events.ScheduleEvent(EVENT_SPELL_REFLECTION, 30000);
break;
case EVENT_CRYSTAL_SPIKES:
Talk(SAY_CRYSTAL_SPIKES);
DoCast(SPELL_CRYSTAL_SPIKES);
events.ScheduleEvent(EVENT_CRYSTAL_SPIKES, 12000);
break;
case EVENT_CRYSTALLINE_TANGLER:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, OrmorokTanglerPredicate(me)))
DoCast(target, SPELL_SUMMON_CRYSTALLINE_TANGLER);
events.ScheduleEvent(EVENT_CRYSTALLINE_TANGLER, 17000);
break;
default:
break;
case EVENT_TRAMPLE:
DoCast(me, SPELL_TRAMPLE);
events.ScheduleEvent(EVENT_TRAMPLE, 10000);
break;
case EVENT_SPELL_REFLECTION:
Talk(SAY_REFLECT);
DoCast(me, SPELL_SPELL_REFLECTION);
events.ScheduleEvent(EVENT_SPELL_REFLECTION, 30000);
break;
case EVENT_CRYSTAL_SPIKES:
Talk(SAY_CRYSTAL_SPIKES);
DoCast(SPELL_CRYSTAL_SPIKES);
events.ScheduleEvent(EVENT_CRYSTAL_SPIKES, 12000);
break;
case EVENT_CRYSTALLINE_TANGLER:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, OrmorokTanglerPredicate(me)))
DoCast(target, SPELL_SUMMON_CRYSTALLINE_TANGLER);
events.ScheduleEvent(EVENT_CRYSTALLINE_TANGLER, 17000);
break;
default:
break;
}
}
@@ -18,10 +18,8 @@
#include "ScriptMgr.h"
#include "InstanceScript.h"
#include "nexus.h"
#include "Player.h"
#define NUMBER_OF_ENCOUNTERS 4
#include "nexus.h"
enum Factions
{
@@ -30,229 +28,163 @@ enum Factions
class instance_nexus : public InstanceMapScript
{
public:
instance_nexus() : InstanceMapScript("instance_nexus", 576) { }
public:
instance_nexus() : InstanceMapScript(NexusScriptName, 576) { }
InstanceScript* GetInstanceScript(InstanceMap* map) const override
{
return new instance_nexus_InstanceMapScript(map);
}
struct instance_nexus_InstanceMapScript : public InstanceScript
{
instance_nexus_InstanceMapScript(Map* map) : InstanceScript(map)
struct instance_nexus_InstanceMapScript : public InstanceScript
{
SetHeaders(DataHeader);
memset(&m_auiEncounter, 0, sizeof(m_auiEncounter));
}
uint32 m_auiEncounter[NUMBER_OF_ENCOUNTERS];
ObjectGuid Anomalus;
ObjectGuid Keristrasza;
ObjectGuid AnomalusContainmentSphere;
ObjectGuid OrmoroksContainmentSphere;
ObjectGuid TelestrasContainmentSphere;
std::string strInstData;
void OnCreatureCreate(Creature* creature) override
{
Map::PlayerList const &players = instance->GetPlayers();
uint32 TeamInInstance = 0;
if (!players.isEmpty())
instance_nexus_InstanceMapScript(Map* map) : InstanceScript(map)
{
if (Player* player = players.begin()->GetSource())
TeamInInstance = player->GetTeam();
}
switch (creature->GetEntry())
{
case 26763:
Anomalus = creature->GetGUID();
break;
case 26723:
Keristrasza = creature->GetGUID();
break;
// Alliance npcs are spawned by default, if you are alliance, you will fight against horde npcs.
case 26800:
{
if (ServerAllowsTwoSideGroups())
creature->setFaction(FACTION_HOSTILE_FOR_ALL);
if (TeamInInstance == ALLIANCE)
creature->UpdateEntry(26799);
break;
}
case 26802:
{
if (ServerAllowsTwoSideGroups())
creature->setFaction(FACTION_HOSTILE_FOR_ALL);
if (TeamInInstance == ALLIANCE)
creature->UpdateEntry(26801);
break;
}
case 26805:
{
if (ServerAllowsTwoSideGroups())
creature->setFaction(FACTION_HOSTILE_FOR_ALL);
if (TeamInInstance == ALLIANCE)
creature->UpdateEntry(26803);
break;
}
case 27949:
{
if (ServerAllowsTwoSideGroups())
creature->setFaction(FACTION_HOSTILE_FOR_ALL);
if (TeamInInstance == ALLIANCE)
creature->UpdateEntry(27947);
break;
}
case 26796:
{
if (ServerAllowsTwoSideGroups())
creature->setFaction(FACTION_HOSTILE_FOR_ALL);
if (TeamInInstance == ALLIANCE)
creature->UpdateEntry(26798);
break;
}
}
}
void OnGameObjectCreate(GameObject* go) override
{
switch (go->GetEntry())
{
case 188527:
{
AnomalusContainmentSphere = go->GetGUID();
if (m_auiEncounter[1] == DONE)
go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
break;
}
case 188528:
{
OrmoroksContainmentSphere = go->GetGUID();
if (m_auiEncounter[2] == DONE)
go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
break;
}
case 188526:
{
TelestrasContainmentSphere = go->GetGUID();
if (m_auiEncounter[0] == DONE)
go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
break;
}
}
}
uint32 GetData(uint32 identifier) const override
{
switch (identifier)
{
case DATA_MAGUS_TELESTRA_EVENT: return m_auiEncounter[0];
case DATA_ANOMALUS_EVENT: return m_auiEncounter[1];
case DATA_ORMOROK_EVENT: return m_auiEncounter[2];
case DATA_KERISTRASZA_EVENT: return m_auiEncounter[3];
}
return 0;
}
void SetData(uint32 identifier, uint32 data) override
{
switch (identifier)
{
case DATA_MAGUS_TELESTRA_EVENT:
{
if (data == DONE)
{
GameObject* Sphere = instance->GetGameObject(TelestrasContainmentSphere);
if (Sphere)
Sphere->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
}
m_auiEncounter[0] = data;
break;
}
case DATA_ANOMALUS_EVENT:
{
if (data == DONE)
{
if (GameObject* Sphere = instance->GetGameObject(AnomalusContainmentSphere))
Sphere->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
}
m_auiEncounter[1] = data;
break;
}
case DATA_ORMOROK_EVENT:
{
if (data == DONE)
{
if (GameObject* Sphere = instance->GetGameObject(OrmoroksContainmentSphere))
Sphere->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
}
m_auiEncounter[2] = data;
break;
}
case DATA_KERISTRASZA_EVENT:
m_auiEncounter[3] = data;
break;
SetHeaders(DataHeader);
SetBossNumber(EncounterCount);
_teamInInstance = 0;
}
if (data == DONE)
void OnPlayerEnter(Player* player) override
{
OUT_SAVE_INST_DATA;
std::ostringstream saveStream;
saveStream << m_auiEncounter[0] << ' ' << m_auiEncounter[1] << ' ' << m_auiEncounter[2] << ' '
<< m_auiEncounter[3];
strInstData = saveStream.str();
SaveToDB();
OUT_SAVE_INST_DATA_COMPLETE;
}
}
ObjectGuid GetGuidData(uint32 uiIdentifier) const override
{
switch (uiIdentifier)
{
case DATA_ANOMALUS: return Anomalus;
case DATA_KERISTRASZA: return Keristrasza;
case ANOMALUS_CONTAINMET_SPHERE: return AnomalusContainmentSphere;
case ORMOROKS_CONTAINMET_SPHERE: return OrmoroksContainmentSphere;
case TELESTRAS_CONTAINMET_SPHERE: return TelestrasContainmentSphere;
}
return ObjectGuid::Empty;
}
std::string GetSaveData() override
{
return strInstData;
}
void Load(const char *chrIn)
{
if (!chrIn)
{
OUT_LOAD_INST_DATA_FAIL;
return;
if (!_teamInInstance)
_teamInInstance = player->GetTeam();
}
OUT_LOAD_INST_DATA(chrIn);
void OnCreatureCreate(Creature* creature) override
{
switch (creature->GetEntry())
{
case NPC_ANOMALUS:
AnomalusGUID = creature->GetGUID();
break;
case NPC_KERISTRASZA:
KeristraszaGUID = creature->GetGUID();
break;
// Alliance npcs are spawned by default, if you are alliance, you will fight against horde npcs.
case NPC_ALLIANCE_BERSERKER:
if (ServerAllowsTwoSideGroups())
creature->setFaction(FACTION_HOSTILE_FOR_ALL);
if (_teamInInstance == ALLIANCE)
creature->UpdateEntry(NPC_HORDE_BERSERKER);
break;
case NPC_ALLIANCE_RANGER:
if (ServerAllowsTwoSideGroups())
creature->setFaction(FACTION_HOSTILE_FOR_ALL);
if (_teamInInstance == ALLIANCE)
creature->UpdateEntry(NPC_HORDE_RANGER);
break;
case NPC_ALLIANCE_CLERIC:
if (ServerAllowsTwoSideGroups())
creature->setFaction(FACTION_HOSTILE_FOR_ALL);
if (_teamInInstance == ALLIANCE)
creature->UpdateEntry(NPC_HORDE_CLERIC);
break;
case NPC_ALLIANCE_COMMANDER:
if (ServerAllowsTwoSideGroups())
creature->setFaction(FACTION_HOSTILE_FOR_ALL);
if (_teamInInstance == ALLIANCE)
creature->UpdateEntry(NPC_HORDE_COMMANDER);
break;
case NPC_COMMANDER_STOUTBEARD:
if (ServerAllowsTwoSideGroups())
creature->setFaction(FACTION_HOSTILE_FOR_ALL);
if (_teamInInstance == ALLIANCE)
creature->UpdateEntry(NPC_COMMANDER_KOLURG);
break;
default:
break;
}
}
std::istringstream loadStream(chrIn);
loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3];
void OnGameObjectCreate(GameObject* go) override
{
switch (go->GetEntry())
{
case GO_ANOMALUS_CONTAINMET_SPHERE:
AnomalusContainmentSphere = go->GetGUID();
if (GetBossState(DATA_ANOMALUS) == DONE)
go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
break;
case GO_ORMOROKS_CONTAINMET_SPHERE:
OrmoroksContainmentSphere = go->GetGUID();
if (GetBossState(DATA_ORMOROK) == DONE)
go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
break;
case GO_TELESTRAS_CONTAINMET_SPHERE:
TelestrasContainmentSphere = go->GetGUID();
if (GetBossState(DATA_MAGUS_TELESTRA) == DONE)
go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
break;
default:
break;
}
}
for (uint8 i = 0; i < NUMBER_OF_ENCOUNTERS; ++i)
if (m_auiEncounter[i] == IN_PROGRESS)
m_auiEncounter[i] = NOT_STARTED;
bool SetBossState(uint32 type, EncounterState state) override
{
if (!InstanceScript::SetBossState(type, state))
return false;
OUT_LOAD_INST_DATA_COMPLETE;
switch (type)
{
case DATA_MAGUS_TELESTRA:
if (state == DONE)
{
if (GameObject* sphere = instance->GetGameObject(TelestrasContainmentSphere))
sphere->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
}
break;
case DATA_ANOMALUS:
if (state == DONE)
{
if (GameObject* sphere = instance->GetGameObject(AnomalusContainmentSphere))
sphere->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
}
break;
case DATA_ORMOROK:
if (state == DONE)
{
if (GameObject* sphere = instance->GetGameObject(OrmoroksContainmentSphere))
sphere->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
}
break;
default:
break;
}
return true;
}
ObjectGuid GetGuidData(uint32 type) const override
{
switch (type)
{
case DATA_ANOMALUS:
return AnomalusGUID;
case DATA_KERISTRASZA:
return KeristraszaGUID;
case ANOMALUS_CONTAINMET_SPHERE:
return AnomalusContainmentSphere;
case ORMOROKS_CONTAINMET_SPHERE:
return OrmoroksContainmentSphere;
case TELESTRAS_CONTAINMET_SPHERE:
return TelestrasContainmentSphere;
default:
break;
}
return ObjectGuid::Empty;
}
private:
ObjectGuid AnomalusGUID;
ObjectGuid KeristraszaGUID;
ObjectGuid AnomalusContainmentSphere;
ObjectGuid OrmoroksContainmentSphere;
ObjectGuid TelestrasContainmentSphere;
uint32 _teamInInstance;
};
InstanceScript* GetInstanceScript(InstanceMap* map) const override
{
return new instance_nexus_InstanceMapScript(map);
}
};
};
void AddSC_instance_nexus()
@@ -18,21 +18,48 @@
#ifndef DEF_NEXUS_H
#define DEF_NEXUS_H
#define NexusScriptName "instance_nexus"
#define DataHeader "NEX"
uint32 const EncounterCount = 4;
enum DataTypes
{
DATA_MAGUS_TELESTRA_EVENT,
DATA_ANOMALUS_EVENT,
DATA_ORMOROK_EVENT,
DATA_KERISTRASZA_EVENT,
DATA_MAGUS_TELESTRA = 0,
DATA_ANOMALUS = 1,
DATA_ORMOROK = 2,
DATA_KERISTRASZA = 3,
DATA_ANOMALUS,
DATA_KERISTRASZA,
ANOMALUS_CONTAINMET_SPHERE = 4,
ORMOROKS_CONTAINMET_SPHERE = 5,
TELESTRAS_CONTAINMET_SPHERE = 6
};
ANOMALUS_CONTAINMET_SPHERE,
ORMOROKS_CONTAINMET_SPHERE,
TELESTRAS_CONTAINMET_SPHERE
enum CreatureIds
{
NPC_ANOMALUS = 26763,
NPC_KERISTRASZA = 26723,
// Alliance
NPC_ALLIANCE_BERSERKER = 26800,
NPC_ALLIANCE_RANGER = 26802,
NPC_ALLIANCE_CLERIC = 26805,
NPC_ALLIANCE_COMMANDER = 27949,
NPC_COMMANDER_STOUTBEARD = 26796,
// Horde
NPC_HORDE_BERSERKER = 26799,
NPC_HORDE_RANGER = 26801,
NPC_HORDE_CLERIC = 26803,
NPC_HORDE_COMMANDER = 27947,
NPC_COMMANDER_KOLURG = 26798
};
enum GameObjectIds
{
GO_ANOMALUS_CONTAINMET_SPHERE = 188527,
GO_ORMOROKS_CONTAINMET_SPHERE = 188528,
GO_TELESTRAS_CONTAINMET_SPHERE = 188526
};
#endif
@@ -192,6 +192,7 @@ class instance_oculus : public InstanceMapScript
FreeDragons();
if (Creature* varos = instance->GetCreature(VarosGUID))
varos->SetPhaseMask(1, true);
events.ScheduleEvent(EVENT_VAROS_INTRO, 15000);
}
break;
case DATA_VAROS:
@@ -209,6 +210,7 @@ class instance_oculus : public InstanceMapScript
{
eregos->SetPhaseMask(1, true);
GreaterWhelps();
events.ScheduleEvent(EVENT_EREGOS_INTRO, 5000);
}
}
break;
@@ -267,6 +269,28 @@ class instance_oculus : public InstanceMapScript
}
}
void Update(uint32 diff) override
{
events.Update(diff);
while (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_VAROS_INTRO:
if (Creature* varos = instance->GetCreature(VarosGUID))
varos->AI()->Talk(SAY_VAROS_INTRO_TEXT);
break;
case EVENT_EREGOS_INTRO:
if (Creature* eregos = instance->GetCreature(EregosGUID))
eregos->AI()->Talk(SAY_EREGOS_INTRO_TEXT);
break;
default:
break;
}
}
}
void GreaterWhelps()
{
for (ObjectGuid guid : GreaterWhelpList)
@@ -289,6 +313,8 @@ class instance_oculus : public InstanceMapScript
ObjectGuid EregosCacheGUID;
GuidList GreaterWhelpList;
EventMap events;
};
InstanceScript* GetInstanceScript(InstanceMap* map) const override
@@ -79,6 +79,18 @@ enum OculusSpells
SPELL_DEATH_SPELL = 50415
};
enum InstanceTexts
{
SAY_EREGOS_INTRO_TEXT = 0,
SAY_VAROS_INTRO_TEXT = 4
};
enum InstanceEvents
{
EVENT_VAROS_INTRO = 1,
EVENT_EREGOS_INTRO
};
enum Misc
{
POINT_MOVE_OUT = 1
@@ -28,7 +28,7 @@ EndScriptData */
#include "SpellScript.h"
#include "halls_of_lightning.h"
enum Yells
enum Texts
{
SAY_INTRO_1 = 0,
SAY_INTRO_2 = 1,
@@ -51,6 +51,21 @@ enum Spells
SPELL_PULSING_SHOCKWAVE_AURA = 59414
};
enum Events
{
EVENT_ARC_LIGHTNING = 1,
EVENT_LIGHTNING_NOVA,
EVENT_RESUME_PULSING_SHOCKWAVE,
EVENT_INTRO_DIALOGUE
};
enum Phases
{
// Phases are used to allow executing the intro event while UpdateVictim() returns false and convenience.
PHASE_INTRO = 1,
PHASE_NORMAL
};
enum Misc
{
ACHIEV_TIMELY_DEATH_START_EVENT = 20384
@@ -65,57 +80,41 @@ class boss_loken : public CreatureScript
public:
boss_loken() : CreatureScript("boss_loken") { }
CreatureAI* GetAI(Creature* creature) const override
struct boss_lokenAI : public BossAI
{
return GetInstanceAI<boss_lokenAI>(creature);
}
struct boss_lokenAI : public ScriptedAI
{
boss_lokenAI(Creature* creature) : ScriptedAI(creature)
boss_lokenAI(Creature* creature) : BossAI(creature, DATA_LOKEN)
{
Initialize();
instance = creature->GetInstanceScript();
_isIntroDone = false;
}
void Initialize()
{
m_uiArcLightning_Timer = 15000;
m_uiLightningNova_Timer = 20000;
m_uiResumePulsingShockwave_Timer = 1000;
m_uiHealthAmountModifier = 1;
_healthAmountModifier = 1;
}
InstanceScript* instance;
uint32 m_uiArcLightning_Timer;
uint32 m_uiLightningNova_Timer;
uint32 m_uiResumePulsingShockwave_Timer;
uint32 m_uiHealthAmountModifier;
void Reset() override
{
Initialize();
instance->SetBossState(DATA_LOKEN, NOT_STARTED);
_Reset();
instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMELY_DEATH_START_EVENT);
}
void EnterCombat(Unit* /*who*/) override
{
_EnterCombat();
Talk(SAY_AGGRO);
instance->SetBossState(DATA_LOKEN, IN_PROGRESS);
events.SetPhase(PHASE_NORMAL);
events.ScheduleEvent(EVENT_ARC_LIGHTNING, 15000);
events.ScheduleEvent(EVENT_LIGHTNING_NOVA, 20000);
events.ScheduleEvent(EVENT_RESUME_PULSING_SHOCKWAVE, 1000);
instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMELY_DEATH_START_EVENT);
}
void JustDied(Unit* /*killer*/) override
{
Talk(SAY_DEATH);
instance->SetBossState(DATA_LOKEN, DONE);
_JustDied();
instance->DoRemoveAurasDueToSpellOnPlayers(SPELL_PULSING_SHOCKWAVE_AURA);
}
@@ -125,66 +124,89 @@ public:
Talk(SAY_SLAY);
}
void UpdateAI(uint32 uiDiff) override
void MoveInLineOfSight(Unit* who) override
{
//Return since we have no target
if (!UpdateVictim())
if (!_isIntroDone && me->IsValidAttackTarget(who) && me->IsWithinDistInMap(who, 40.0f))
{
_isIntroDone = true;
Talk(SAY_INTRO_1);
events.ScheduleEvent(EVENT_INTRO_DIALOGUE, 20000, 0, PHASE_INTRO);
}
BossAI::MoveInLineOfSight(who);
}
void UpdateAI(uint32 diff) override
{
if (events.IsInPhase(PHASE_NORMAL) && !UpdateVictim())
return;
if (m_uiResumePulsingShockwave_Timer)
events.Update(diff);
while (uint32 eventId = events.ExecuteEvent())
{
if (m_uiResumePulsingShockwave_Timer <= uiDiff)
switch (eventId)
{
DoCast(me, SPELL_PULSING_SHOCKWAVE_AURA, true);
me->ClearUnitState(UNIT_STATE_CASTING); // this flag breaks movement
DoCast(me, SPELL_PULSING_SHOCKWAVE, true);
m_uiResumePulsingShockwave_Timer = 0;
case EVENT_ARC_LIGHTNING:
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
DoCast(target, SPELL_ARC_LIGHTNING);
events.ScheduleEvent(EVENT_ARC_LIGHTNING, urand(15000, 16000));
break;
case EVENT_LIGHTNING_NOVA:
Talk(SAY_NOVA);
Talk(EMOTE_NOVA);
DoCastAOE(SPELL_LIGHTNING_NOVA);
me->RemoveAurasDueToSpell(sSpellMgr->GetSpellIdForDifficulty(SPELL_PULSING_SHOCKWAVE, me));
events.ScheduleEvent(EVENT_RESUME_PULSING_SHOCKWAVE, DUNGEON_MODE(5000, 4000)); // Pause Pulsing Shockwave aura
events.ScheduleEvent(EVENT_LIGHTNING_NOVA, urand(20000, 21000));
break;
case EVENT_RESUME_PULSING_SHOCKWAVE:
DoCast(me, SPELL_PULSING_SHOCKWAVE_AURA, true);
me->ClearUnitState(UNIT_STATE_CASTING); // This flag breaks movement.
DoCast(me, SPELL_PULSING_SHOCKWAVE, true);
break;
case EVENT_INTRO_DIALOGUE:
Talk(SAY_INTRO_2);
events.SetPhase(PHASE_NORMAL);
break;
default:
break;
}
else
m_uiResumePulsingShockwave_Timer -= uiDiff;
}
if (m_uiArcLightning_Timer <= uiDiff)
{
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
DoCast(target, SPELL_ARC_LIGHTNING);
m_uiArcLightning_Timer = urand(15000, 16000);
}
else
m_uiArcLightning_Timer -= uiDiff;
if (m_uiLightningNova_Timer <= uiDiff)
{
Talk(SAY_NOVA);
Talk(EMOTE_NOVA);
DoCast(me, SPELL_LIGHTNING_NOVA);
me->RemoveAurasDueToSpell(sSpellMgr->GetSpellIdForDifficulty(SPELL_PULSING_SHOCKWAVE, me));
m_uiResumePulsingShockwave_Timer = DUNGEON_MODE(5000, 4000); // Pause Pulsing Shockwave aura
m_uiLightningNova_Timer = urand(20000, 21000);
}
else
m_uiLightningNova_Timer -= uiDiff;
// Health check
if (HealthBelowPct(100 - 25 * m_uiHealthAmountModifier))
{
switch (m_uiHealthAmountModifier)
{
case 1: Talk(SAY_75HEALTH); break;
case 2: Talk(SAY_50HEALTH); break;
case 3: Talk(SAY_25HEALTH); break;
}
++m_uiHealthAmountModifier;
}
DoMeleeAttackIfReady();
}
void DamageTaken(Unit* /*attacker*/, uint32& damage) override
{
if (me->HealthBelowPctDamaged(100 - 25 * _healthAmountModifier, damage))
{
switch (_healthAmountModifier)
{
case 1:
Talk(SAY_75HEALTH);
break;
case 2:
Talk(SAY_50HEALTH);
break;
case 3:
Talk(SAY_25HEALTH);
break;
default:
break;
}
++_healthAmountModifier;
}
}
private:
uint32 _healthAmountModifier;
bool _isIntroDone;
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetInstanceAI<boss_lokenAI>(creature);
}
};
class spell_loken_pulsing_shockwave : public SpellScriptLoader
@@ -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();
@@ -209,52 +209,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
######*/
@@ -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();
}
@@ -21,8 +21,14 @@
DoorData const doorData[] =
{
{ GO_IKISS_DOOR, DATA_TALON_KING_IKISS, DOOR_TYPE_PASSAGE, BOUNDARY_NONE },
{ 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE } // END
{ GO_IKISS_DOOR, DATA_TALON_KING_IKISS, DOOR_TYPE_PASSAGE, BOUNDARY_NONE },
{ 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE } // END
};
ObjectData const gameObjectData[] =
{
{ GO_TALON_KING_COFFER, DATA_TALON_KING_COFFER },
{ 0, 0 } // END
};
class instance_sethekk_halls : public InstanceMapScript
@@ -37,6 +43,7 @@ class instance_sethekk_halls : public InstanceMapScript
SetHeaders(DataHeader);
SetBossNumber(EncounterCount);
LoadDoorData(doorData);
LoadObjectData(nullptr, gameObjectData);
}
void OnCreatureCreate(Creature* creature) override
@@ -50,16 +57,27 @@ class instance_sethekk_halls : public InstanceMapScript
}
}
void OnGameObjectCreate(GameObject* go) override
bool SetBossState(uint32 type, EncounterState state) override
{
if (go->GetEntry() == GO_IKISS_DOOR)
AddDoor(go, true);
}
if (!InstanceScript::SetBossState(type, state))
return false;
void OnGameObjectRemove(GameObject* go) override
{
if (go->GetEntry() == GO_IKISS_DOOR)
AddDoor(go, false);
switch (type)
{
case DATA_TALON_KING_IKISS:
if (state == DONE)
{
/// @workaround: GO_FLAG_INTERACT_COND remains on the gob, but it is not handled correctly in this case
/// gameobject should have GO_DYNFLAG_LO_ACTIVATE too, which makes gobs interactable with GO_FLAG_INTERACT_COND
/// so just removed GO_FLAG_INTERACT_COND
if (GameObject* coffer = GetGameObject(DATA_TALON_KING_COFFER))
coffer->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_INTERACT_COND | GO_FLAG_NOT_SELECTABLE);
}
break;
default:
break;
}
return true;
}
};
@@ -28,7 +28,10 @@ enum DataTypes
// Encounter States/Boss GUIDs
DATA_DARKWEAVER_SYTH = 0,
DATA_TALON_KING_IKISS = 1,
DATA_ANZU = 2
DATA_ANZU = 2,
// Additional Data
DATA_TALON_KING_COFFER = 3
};
enum CreatureIds
@@ -39,7 +42,8 @@ enum CreatureIds
enum GameObjectIds
{
GO_IKISS_DOOR = 177203
GO_IKISS_DOOR = 177203,
GO_TALON_KING_COFFER = 187372
};
template<class AI>
@@ -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)
@@ -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
-67
View File
@@ -40,8 +40,6 @@ go_dragonflayer_cage
go_tadpole_cage
go_amberpine_outhouse
go_hive_pod
go_gjalerbron_cage
go_large_gjalerbron_cage
go_veil_skith_cage
EndContentData */
@@ -1040,69 +1038,6 @@ class go_massive_seaforium_charge : public GameObjectScript
};
/*######
## go_gjalerbron_cage
######*/
enum OfKeysAndCages
{
QUEST_ALLIANCE_OF_KEYS_AND_CAGES = 11231,
QUEST_HORDE_OF_KEYS_AND_CAGES = 11265,
NPC_GJALERBRON_PRISONER = 24035,
SAY_FREE = 0,
};
class go_gjalerbron_cage : public GameObjectScript
{
public:
go_gjalerbron_cage() : GameObjectScript("go_gjalerbron_cage") { }
bool OnGossipHello(Player* player, GameObject* go) override
{
go->UseDoorOrButton();
if ((player->GetTeamId() == TEAM_ALLIANCE && player->GetQuestStatus(QUEST_ALLIANCE_OF_KEYS_AND_CAGES) == QUEST_STATUS_INCOMPLETE) ||
(player->GetTeamId() == TEAM_HORDE && player->GetQuestStatus(QUEST_HORDE_OF_KEYS_AND_CAGES) == QUEST_STATUS_INCOMPLETE))
{
if (Creature* prisoner = go->FindNearestCreature(NPC_GJALERBRON_PRISONER, 5.0f))
{
player->KilledMonsterCredit(NPC_GJALERBRON_PRISONER);
prisoner->AI()->Talk(SAY_FREE);
prisoner->DespawnOrUnsummon(6000);
}
}
return true;
}
};
/*########
## go_large_gjalerbron_cage
#####*/
class go_large_gjalerbron_cage : public GameObjectScript
{
public:
go_large_gjalerbron_cage() : GameObjectScript("go_large_gjalerbron_cage") { }
bool OnGossipHello(Player* player, GameObject* go) override
{
go->UseDoorOrButton();
if ((player->GetTeamId() == TEAM_ALLIANCE && player->GetQuestStatus(QUEST_ALLIANCE_OF_KEYS_AND_CAGES) == QUEST_STATUS_INCOMPLETE) ||
(player->GetTeamId() == TEAM_HORDE && player->GetQuestStatus(QUEST_HORDE_OF_KEYS_AND_CAGES) == QUEST_STATUS_INCOMPLETE))
{
std::list<Creature*> prisonerList;
GetCreatureListWithEntryInGrid(prisonerList, go, NPC_GJALERBRON_PRISONER, INTERACTION_DISTANCE);
for (std::list<Creature*>::const_iterator itr = prisonerList.begin(); itr != prisonerList.end(); ++itr)
{
player->KilledMonsterCredit(NPC_GJALERBRON_PRISONER, (*itr)->GetGUID());
(*itr)->DespawnOrUnsummon(6000);
(*itr)->AI()->Talk(SAY_FREE);
}
}
return false;
}
};
/*########
#### go_veil_skith_cage
#####*/
@@ -1222,8 +1157,6 @@ void AddSC_go_scripts()
new go_amberpine_outhouse();
new go_hive_pod();
new go_massive_seaforium_charge();
new go_gjalerbron_cage();
new go_large_gjalerbron_cage();
new go_veil_skith_cage();
new go_frostblade_shrine();
new go_midsummer_bonfire();
+3
View File
@@ -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
@@ -81,6 +81,14 @@ public:
}
}
// Ensures there's "some" free space, make sure to call Normalize() before this
void EnsureFreeSpace()
{
// Double the size of the buffer if it's already full
if (GetRemainingSpace() == 0)
_storage.resize(_storage.size() * 2);
}
void Write(void const* data, std::size_t size)
{
if (size)
+2 -1
View File
@@ -90,7 +90,8 @@ public:
return;
_readBuffer.Normalize();
_socket.async_read_some(boost::asio::buffer(_readBuffer.GetWritePointer(), READ_BLOCK_SIZE),
_readBuffer.EnsureFreeSpace();
_socket.async_read_some(boost::asio::buffer(_readBuffer.GetWritePointer(), _readBuffer.GetRemainingSpace()),
std::bind(&Socket<T>::ReadHandlerInternal, this->shared_from_this(), std::placeholders::_1, std::placeholders::_2));
}
+10 -1
View File
@@ -46,7 +46,16 @@ public:
return false;
}
_acceptor = new AsyncAcceptor(service, bindIp, port);
try
{
_acceptor = new AsyncAcceptor(service, bindIp, port);
}
catch (boost::system::system_error const& err)
{
TC_LOG_ERROR("network", "Exception caught in SocketMgr.StartNetwork (%s:%u): %s", bindIp.c_str(), port, err.what());
return false;
}
_threads = CreateThreads();
ASSERT(_threads);
@@ -581,6 +581,22 @@ MinCharterName = 2
MinPetName = 2
#
# Guild.CharterCost
# ArenaTeam.CharterCost.2v2
# ArenaTeam.CharterCost.3v3
# ArenaTeam.CharterCost.5v5
# Description: Amount of money (in Copper) the petitions costs.
# Default: 1000 - (10 Silver)
# 800000 - (80 Gold)
# 1200000 - (120 Gold)
# 2000000 - (200 Gold)
Guild.CharterCost = 1000
ArenaTeam.CharterCost.2v2 = 800000
ArenaTeam.CharterCost.3v3 = 1200000
ArenaTeam.CharterCost.5v5 = 2000000
#
# MaxWhoListReturns
# Description: Set the max number of players returned in the /who list and interface.