From 795d01bc1b6b67e4d086be884f08549534f3297e Mon Sep 17 00:00:00 2001 From: Ascathor Date: Mon, 25 Feb 2013 18:14:29 +0100 Subject: [PATCH 01/13] Some documentation additions within player.h and Creature.h --- src/server/game/Entities/Creature/Creature.h | 8 +++----- src/server/game/Entities/Player/Player.h | 5 +++++ 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index e8996db608f..5402ca979af 100644 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -484,15 +484,13 @@ class Creature : public Unit, public GridObject, public MapCreature SetReactState(REACT_DEFENSIVE);*/; } - ///// TODO RENAME THIS!!!!! + /// @todo Rename this to proper functions bool isCanTrainingOf(Player* player, bool msg) const; bool isCanInteractWithBattleMaster(Player* player, bool msg) const; bool isCanTrainingAndResetTalentsOf(Player* player) const; bool canCreatureAttack(Unit const* victim, bool force = true) const; - bool IsImmunedToSpell(SpellInfo const* spellInfo); - // redefine Unit::IsImmunedToSpell - bool IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index) const; - // redefine Unit::IsImmunedToSpellEffect + bool IsImmunedToSpell(SpellInfo const* spellInfo); // redefine Unit::IsImmunedToSpell + bool IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index) const; // redefine Unit::IsImmunedToSpellEffect bool isElite() const { if (isPet()) diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 362b6aca631..7da9878eddf 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -1188,10 +1188,15 @@ class Player : public Unit, public GridObject void RemovePet(Pet* pet, PetSaveMode mode, bool returnreagent = false); uint32 GetPhaseMaskForSpawn() const; // used for proper set phase for DB at GM-mode creature/GO spawn + /// Handles said message in regular chat based on declared language and in config pre-defined Range. void Say(std::string const& text, const uint32 language); + /// Handles yelled message in regular chat based on declared language and in config pre-defined Range. void Yell(std::string const& text, const uint32 language); + /// Outputs an universal text which is supposed to be an action. void TextEmote(std::string const& text); + /// Handles whispers from Addons and players based on sender, reciever's guid and language. void Whisper(std::string const& text, const uint32 language, uint64 receiver); + /// Constructs the player Chat data for the specific functions to use void BuildPlayerChat(WorldPacket* data, uint8 msgtype, std::string const& text, uint32 language) const; /*********************************************************/ From 6db8fed2ff9fd82df8ed8840058cf4d376dde4b4 Mon Sep 17 00:00:00 2001 From: Ascathor Date: Mon, 25 Feb 2013 20:43:06 +0100 Subject: [PATCH 02/13] Additional changes and requests as by @subv --- src/server/game/Entities/Creature/Creature.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index 5402ca979af..b40229d4748 100644 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -484,13 +484,13 @@ class Creature : public Unit, public GridObject, public MapCreature SetReactState(REACT_DEFENSIVE);*/; } - /// @todo Rename this to proper functions + /// @todo Rename these properly bool isCanTrainingOf(Player* player, bool msg) const; bool isCanInteractWithBattleMaster(Player* player, bool msg) const; bool isCanTrainingAndResetTalentsOf(Player* player) const; bool canCreatureAttack(Unit const* victim, bool force = true) const; - bool IsImmunedToSpell(SpellInfo const* spellInfo); // redefine Unit::IsImmunedToSpell - bool IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index) const; // redefine Unit::IsImmunedToSpellEffect + bool IsImmunedToSpell(SpellInfo const* spellInfo); //override Unit::IsImmunedToSpell + bool IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index) const; //override Unit::IsImmunedToSpellEffect bool isElite() const { if (isPet()) From dec38b12a0203d5cb829ee4faba02d4bccffe68e Mon Sep 17 00:00:00 2001 From: Ascathor Date: Tue, 26 Feb 2013 17:28:10 +0100 Subject: [PATCH 03/13] Fixing some Engrish. --- src/server/game/Entities/Creature/Creature.h | 4 ++-- src/server/game/Entities/Player/Player.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index b40229d4748..df41690c15e 100644 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -770,10 +770,10 @@ class Creature : public Unit, public GridObject, public MapCreature bool DisableReputationGain; - CreatureTemplate const* m_creatureInfo; // in difficulty mode > 0 can different from sObjectMgr->GetCreatureTemplate(GetEntry()) + CreatureTemplate const* m_creatureInfo; // Can differ from sObjectMgr->GetCreatureTemplate(GetEntry()) in difficulty mode > 0 CreatureData const* m_creatureData; - uint16 m_LootMode; // bitmask, default LOOT_MODE_DEFAULT, determines what loot will be lootable + uint16 m_LootMode; // Bitmask (default: LOOT_MODE_DEFAULT) that determines what loot will be lootable uint32 guid_transport; bool IsInvisibleDueToDespawn() const; diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 7da9878eddf..3f1bd277d0c 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -1194,7 +1194,7 @@ class Player : public Unit, public GridObject void Yell(std::string const& text, const uint32 language); /// Outputs an universal text which is supposed to be an action. void TextEmote(std::string const& text); - /// Handles whispers from Addons and players based on sender, reciever's guid and language. + /// Handles whispers from Addons and players based on sender, receiver's guid and language. void Whisper(std::string const& text, const uint32 language, uint64 receiver); /// Constructs the player Chat data for the specific functions to use void BuildPlayerChat(WorldPacket* data, uint8 msgtype, std::string const& text, uint32 language) const; From 1d3f35af18b5e8af31c41d84e63c7a33d9b5913e Mon Sep 17 00:00:00 2001 From: Ascathor Date: Tue, 26 Feb 2013 18:39:11 +0100 Subject: [PATCH 04/13] Additional fixes and some clean ups --- .../game/Battlefield/Zones/BattlefieldWG.h | 36 +++++++++---------- .../game/Battlegrounds/Zones/BattlegroundAV.h | 28 +++++++-------- 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/src/server/game/Battlefield/Zones/BattlefieldWG.h b/src/server/game/Battlefield/Zones/BattlefieldWG.h index 2f750de7b3a..fcd000e75af 100644 --- a/src/server/game/Battlefield/Zones/BattlefieldWG.h +++ b/src/server/game/Battlefield/Zones/BattlefieldWG.h @@ -102,21 +102,21 @@ enum WintergraspData enum WintergraspAchievements { ACHIEVEMENTS_WIN_WG = 1717, - ACHIEVEMENTS_WIN_WG_100 = 1718, // todo - ACHIEVEMENTS_WG_GNOMESLAUGHTER = 1723, // todo + ACHIEVEMENTS_WIN_WG_100 = 1718, /// @todo: Has to be implemented + ACHIEVEMENTS_WG_GNOMESLAUGHTER = 1723, /// @todo: Has to be implemented ACHIEVEMENTS_WG_TOWER_DESTROY = 1727, - ACHIEVEMENTS_DESTRUCTION_DERBY_A = 1737, // todo - ACHIEVEMENTS_WG_TOWER_CANNON_KILL = 1751, // todo - ACHIEVEMENTS_WG_MASTER_A = 1752, // todo + ACHIEVEMENTS_DESTRUCTION_DERBY_A = 1737, /// @todo: Has to be implemented + ACHIEVEMENTS_WG_TOWER_CANNON_KILL = 1751, /// @todo: Has to be implemented + ACHIEVEMENTS_WG_MASTER_A = 1752, /// @todo: Has to be implemented ACHIEVEMENTS_WIN_WG_TIMER_10 = 1755, - ACHIEVEMENTS_STONE_KEEPER_50 = 2085, // todo - ACHIEVEMENTS_STONE_KEEPER_100 = 2086, // todo - ACHIEVEMENTS_STONE_KEEPER_250 = 2087, // todo - ACHIEVEMENTS_STONE_KEEPER_500 = 2088, // todo - ACHIEVEMENTS_STONE_KEEPER_1000 = 2089, // todo - ACHIEVEMENTS_WG_RANGER = 2199, // todo - ACHIEVEMENTS_DESTRUCTION_DERBY_H = 2476, // todo - ACHIEVEMENTS_WG_MASTER_H = 2776 // todo + ACHIEVEMENTS_STONE_KEEPER_50 = 2085, /// @todo: Has to be implemented + ACHIEVEMENTS_STONE_KEEPER_100 = 2086, /// @todo: Has to be implemented + ACHIEVEMENTS_STONE_KEEPER_250 = 2087, /// @todo: Has to be implemented + ACHIEVEMENTS_STONE_KEEPER_500 = 2088, /// @todo: Has to be implemented + ACHIEVEMENTS_STONE_KEEPER_1000 = 2089, /// @todo: Has to be implemented + ACHIEVEMENTS_WG_RANGER = 2199, /// @todo: Has to be implemented + ACHIEVEMENTS_DESTRUCTION_DERBY_H = 2476, /// @todo: Has to be implemented + ACHIEVEMENTS_WG_MASTER_H = 2776 /// @todo: Has to be implemented }; enum WintergraspWorldStates @@ -499,7 +499,7 @@ enum WintergraspTeamControl BATTLEFIELD_WG_TEAM_NEUTRAL }; -// TODO: Handle this with creature_text ? +/// @todo: Can this be handled with creature_text or SmartAI ? enum WintergraspText { BATTLEFIELD_WG_TEXT_WORKSHOP_NAME_NE = 12055, @@ -562,7 +562,7 @@ struct WintergraspObjectPositionData }; // ***************************************************** -// ************ Destructible (Wall, Tower..) ************ +// ************ Destructible (Wall, Tower..) *********** // ***************************************************** struct WintergraspBuildingSpawnData @@ -755,7 +755,7 @@ const WintergraspTeleporterData WGPortalDefenderData[WG_MAX_TELEPORTER] = }; // ********************************************************* -// **********Tower Element(GameObject, Creature)************* +// **********Tower Element(GameObject, Creature)************ // ********************************************************* struct WintergraspTowerData @@ -764,7 +764,7 @@ struct WintergraspTowerData uint8 nbObject; // Number of gameobjects spawned on this point WintergraspObjectPositionData GameObject[6]; // Gameobject position and entry (Horde/Alliance) - // Creature : Turrets and Guard, TODO: check if killed on tower destruction? tower damage? + // Creature: Turrets and Guard /// @todo: Killed on Tower destruction ? Tower damage ? Requires confirming uint8 nbCreatureBottom; WintergraspObjectPositionData CreatureBottom[9]; uint8 nbCreatureTop; @@ -1055,7 +1055,7 @@ const WGWorkshopData WorkshopsData[WG_MAX_WORKSHOP] = }; // ******************************************************************** -// * Structs using for Building, Graveyard, Workshop * +// * Structs using for Building, Graveyard, Workshop * // ******************************************************************** // Structure for different buildings that can be destroyed during battle struct BfWGGameObjectBuilding diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundAV.h b/src/server/game/Battlegrounds/Zones/BattlegroundAV.h index 7cd4d571cad..7a0af0b06d7 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundAV.h +++ b/src/server/game/Battlegrounds/Zones/BattlegroundAV.h @@ -53,7 +53,7 @@ #define AV_EVENT_START_BATTLE 9166 // Achievement: The Alterac Blitz enum BG_AV_Sounds -{ //TODO: get out if there comes a sound when neutral team captures mine +{ /// @todo: get out if there comes a sound when neutral team captures mine /* 8212: @@ -86,7 +86,7 @@ horde: horde wins */ - AV_SOUND_NEAR_VICTORY = 8456, //not confirmed yet + AV_SOUND_NEAR_VICTORY = 8456, /// @todo: Not confirmed yet AV_SOUND_ALLIANCE_ASSAULTS = 8212, //tower, grave + enemy boss if someone tries to attack him AV_SOUND_HORDE_ASSAULTS = 8174, @@ -104,7 +104,7 @@ enum BG_AV_OTHER_VALUES AV_NORTH_MINE = 0, AV_SOUTH_MINE = 1, AV_MINE_TICK_TIMER = 45000, - AV_MINE_RECLAIM_TIMER = 1200000, //TODO: get the right value.. this is currently 20 minutes + AV_MINE_RECLAIM_TIMER = 1200000, /// @todo: get the right value.. this is currently 20 minutes AV_NEUTRAL_TEAM = 0 //this is the neutral owner of snowfall }; enum BG_AV_ObjectIds @@ -547,7 +547,7 @@ enum BG_AV_CreaturePlace AV_CPLACE_SPIRIT_FROST_HUT = 6, AV_CPLACE_SPIRIT_MAIN_ALLIANCE = 7, AV_CPLACE_SPIRIT_MAIN_HORDE = 8, -//i don't will add for all 4 positions a variable.. i think one is enough to compute the rest +//I don't add a variable for all 4 positions... I think one is enough to compute the rest AV_CPLACE_DEFENSE_STORM_AID = 9, AV_CPLACE_DEFEMSE_STORM_GRAVE = 13, AV_CPLACE_DEFENSE_STONE_GRAVE = 17, @@ -680,7 +680,7 @@ const float BG_AV_CreaturePos[AV_CPLACE_MAX][4] = {575.411f, -83.597f, 52.3626f, 6.26573f}, {571.352f, -75.6582f, 52.479f, 0.523599f}, //dun north - OK - {668.60f, -122.53f, 64.12f, 2.34f}, //not 100% ok + {668.60f, -122.53f, 64.12f, 2.34f}, /// @todo: To be confirm - Not completely okay {662.253f, -129.105f, 64.1794f, 2.77507f}, {661.209f, -138.877f, 64.2251f, 3.38594f}, {665.481f, -146.857f, 64.1271f, 3.75246f}, @@ -720,7 +720,7 @@ const float BG_AV_CreaturePos[AV_CPLACE_MAX][4] = {723.058f, -14.1548f, 50.7046f, 3.40339f}, // north {715.691f, -4.72233f, 50.2187f, 3.47321f}, // icewing {720.046f, -19.9413f, 50.2187f, 3.36849f}, // stone -//horde (coords not 100% ok) +/// horde @todo: Confirm positions {-1363.99f, -221.99f, 98.4053f, 4.93012f}, {-1370.96f, -223.532f, 98.4266f, 4.93012f}, {-1378.37f, -228.614f, 99.3546f, 5.38565f}, @@ -1039,14 +1039,14 @@ enum BG_AV_CreatureIds }; //entry, team, minlevel, maxlevel -//TODO this array should be removed, the only needed things are the entrys (for spawning(?) and handlekillunit) +/// @todo: this array should be removed, the only needed things are the entrys (for spawning(?) and handlekillunit) const uint32 BG_AV_CreatureInfo[AV_NPC_INFO_MAX][4] = { { 12050, 1216, 58, 58 }, //Stormpike Defender { 13326, 1216, 59, 59 }, //Seasoned Defender { 13331, 1216, 60, 60 }, //Veteran Defender { 13422, 1216, 61, 61 }, //Champion Defender - { 13358, 1216, 59, 60 }, //Stormpike Bowman //i think its 60, 61 and 69, 70.. but this is until now not possible TODO look if this is ok + { 13358, 1216, 59, 60 }, //Stormpike Bowman /// @todo: Confirm if this is correct. Author assumpted 60,61 & 69,70, but wouldn't work here { 11949, 469, 0, 0}, //not spawned with this data, but used for handlekillunit { 11948, 469, 0, 0}, //not spawned with this data, but used for handlekillunit { 12053, 1214, 58, 58 }, //Frostwolf Guardian @@ -1071,7 +1071,7 @@ const uint32 BG_AV_CreatureInfo[AV_NPC_INFO_MAX][4] = { 11602, 59, 54, 55 }, //Irondeep Skullthumper { 11657, 59, 58, 58 }, //Morloch - {13396, 469, 52, 53}, //irondeep alliance TODO: get the right ids + {13396, 469, 52, 53}, // irondeep alliance /// @todo: Correct and give correct ids {13080, 469, 53, 54}, {13098, 469, 54, 55}, {13078, 469, 58, 58}, @@ -1246,7 +1246,7 @@ const uint32 BG_AV_StaticCreatureInfo[51][4] = { 11675, 514, 53, 53 }, //Snowblind Windcaller { 11678, 14, 52, 53 }, //Snowblind Ambusher { 11839, 39, 56, 56 }, //Wildpaw Brute - { 11947, 1214, 61, 61 }, //Captain Galvangar --TODO: doubled + { 11947, 1214, 61, 61 }, // Captain Galvangar /// @todo: Duplicate ? Check and confirm { 11948, 1216, 63, 63 }, //Vanndar Stormpike { 11949, 1216, 61, 61 }, //Captain Balinda Stonehearth { 11997, 1334, 60, 60 }, //Stormpike Herald @@ -1277,7 +1277,7 @@ const uint32 BG_AV_StaticCreatureInfo[51][4] = { 14282, 1214, 53, 54 }, //Frostwolf Bloodhound { 14283, 1216, 53, 54 }, //Stormpike Owl { 14284, 1216, 61, 61 }, //Stormpike Battleguard - { 11946, 1214, 63, 63 }, //Drek'Thar //TODO: make the levels right (boss=0 maybe) + { 11946, 1214, 63, 63 }, //Drek'Thar /// @todo: Correct the level (Level 80 for boss ?) { 11948, 1216, 63, 63 }, //Vanndar Stormpike { 11947, 1214, 61, 61 }, //Captain Galvangar { 11949, 1216, 61, 61 } //Captain Balinda Stonehearth @@ -1310,7 +1310,7 @@ const uint32 BG_AV_GraveyardIds[9]= }; enum BG_AV_BUFF -{ //TODO add all other buffs here +{ /// @todo: Add all other buffs here AV_BUFF_ARMOR = 21163, AV_BUFF_A_CAPTAIN = 23693, //the buff which the alliance captain does AV_BUFF_H_CAPTAIN = 22751 //the buff which the horde captain does @@ -1607,7 +1607,7 @@ class BattlegroundAV : public Battleground /*general */ Creature* AddAVCreature(uint16 cinfoid, uint16 type); - uint16 GetBonusHonor(uint8 kills); //TODO remove this when the core handles this right + uint16 GetBonusHonor(uint8 kills); /// @todo: Remove this when the core handles this properly /*variables */ int32 m_Team_Scores[2]; @@ -1622,7 +1622,7 @@ class BattlegroundAV : public Battleground uint32 m_CaptainBuffTimer[2]; bool m_CaptainAlive[2]; - uint8 m_MaxLevel; //TODO remove this when battleground-getmaxlevel() returns something usefull + uint8 m_MaxLevel; /// @todo: Remove this once battleground->getmaxlevel() returns something usefull/is reworked (?) bool m_IsInformedNearVictory[2]; }; From d6d066f014417649a33229d07991e4cbd4ee9f35 Mon Sep 17 00:00:00 2001 From: Ascathor Date: Tue, 26 Feb 2013 20:05:17 +0100 Subject: [PATCH 05/13] Several todo corrections for documentation --- src/server/game/Entities/Creature/Creature.h | 2 +- src/server/game/Entities/Item/ItemPrototype.h | 9 ++------- src/server/game/Globals/ObjectAccessor.h | 2 +- src/server/game/Instances/InstanceSaveMgr.h | 4 ++-- 4 files changed, 6 insertions(+), 11 deletions(-) diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index df41690c15e..ab9b81009dd 100644 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -169,7 +169,7 @@ struct CreatureTemplate typedef UNORDERED_MAP CreatureTemplateContainer; // Represents max amount of expansions. -// TODO: Add MAX_EXPANSION constant. +/// @todo: Add MAX_EXPANSION constant. #define MAX_CREATURE_BASE_HP 3 // GCC have alternative #pragma pack(N) syntax and old gcc version not support pack(push, N), also any gcc version not support it at some platform diff --git a/src/server/game/Entities/Item/ItemPrototype.h b/src/server/game/Entities/Item/ItemPrototype.h index f68923706ff..5fc49c99f0a 100644 --- a/src/server/game/Entities/Item/ItemPrototype.h +++ b/src/server/game/Entities/Item/ItemPrototype.h @@ -102,10 +102,8 @@ enum ItemBondingType #define MAX_BIND_TYPE 6 -/* TODO - // need to know cases when using item is not allowed in shapeshift - ITEM_PROTO_FLAG_USABLE_WHEN_SHAPESHIFTED = 0x00800000, // Item can be used in shapeshift forms -*/ +/* /// @todo: Requiring actual cases in which using (an) item isn't allowed while shapeshifted. Else, this flag would need an implementation. + ITEM_PROTO_FLAG_USABLE_WHEN_SHAPESHIFTED = 0x00800000, // Item can be used in shapeshift forms */ enum ItemProtoFlags { @@ -143,9 +141,6 @@ enum ItemProtoFlags ITEM_PROTO_FLAG_UNK12 = 0x80000000 // ? }; -/* TODO -*/ - enum ItemFieldFlags { ITEM_FLAG_SOULBOUND = 0x00000001, // Item is soulbound and cannot be traded <<-- diff --git a/src/server/game/Globals/ObjectAccessor.h b/src/server/game/Globals/ObjectAccessor.h index 113ef1dec83..6a53d58c57f 100644 --- a/src/server/game/Globals/ObjectAccessor.h +++ b/src/server/game/Globals/ObjectAccessor.h @@ -90,7 +90,7 @@ class ObjectAccessor ObjectAccessor& operator=(const ObjectAccessor&); public: - // TODO: override these template functions for each holder type and add assertions + /// @todo: Override these template functions for each holder type and add assertions template static T* GetObjectInOrOutOfWorld(uint64 guid, T* /*typeSpecifier*/) { diff --git a/src/server/game/Instances/InstanceSaveMgr.h b/src/server/game/Instances/InstanceSaveMgr.h index a99b4c66b27..c5dcaf32463 100644 --- a/src/server/game/Instances/InstanceSaveMgr.h +++ b/src/server/game/Instances/InstanceSaveMgr.h @@ -101,8 +101,8 @@ class InstanceSave private: bool UnloadIfEmpty(); /* the only reason the instSave-object links are kept is because - the object-instSave links need to be broken at reset time - TODO: maybe it's enough to just store the number of players/groups */ + the object-instSave links need to be broken at reset time */ + /// @todo: Check if maybe it's enough to just store the number of players/groups PlayerListType m_playerList; GroupListType m_groupList; time_t m_resetTime; From 58ac8207eccbaf056cb1ae7a046bdef48a2483ad Mon Sep 17 00:00:00 2001 From: click Date: Wed, 27 Feb 2013 22:31:25 +0100 Subject: [PATCH 06/13] Core: Add support for compiling core in a cygwin-environment - rename/readd/add G3D-patches - give a history on the changes (some G3D-changes didn't even HAVE a patch - boo!) DON'T MESS ABOUT WITH CHANGING DEP/* LIBRARIES AND NOT LEAVING A DIFF IN THE SOURCETRE, MKAY!? --- .../{G3D-v8.0.diff => G3D-v8.0_hotfix1.diff} | 66 ++++++++--------- dep/g3dlite/G3D-v8.0_hotfix2.diff | 14 ++++ dep/g3dlite/G3D-v8.0_hotfix3.diff | 12 ++++ ...-v8.0_extra.diff => G3D-v8.0_hotfix4.diff} | 12 ---- dep/g3dlite/G3D-v8.0_hotfix5.diff | 71 +++++++++++++++++++ dep/g3dlite/Readme.txt | 11 ++- dep/g3dlite/include/G3D/System.h | 1 + dep/g3dlite/include/G3D/platform.h | 2 + dep/g3dlite/source/BinaryOutput.cpp | 4 ++ dep/g3dlite/source/FileSystem.cpp | 4 ++ dep/g3dlite/source/System.cpp | 4 ++ .../collision/BoundingIntervalHierarchy.cpp | 2 + src/server/shared/Common.h | 2 +- 13 files changed, 156 insertions(+), 49 deletions(-) rename dep/g3dlite/{G3D-v8.0.diff => G3D-v8.0_hotfix1.diff} (83%) create mode 100644 dep/g3dlite/G3D-v8.0_hotfix2.diff create mode 100644 dep/g3dlite/G3D-v8.0_hotfix3.diff rename dep/g3dlite/{G3D-v8.0_extra.diff => G3D-v8.0_hotfix4.diff} (59%) create mode 100644 dep/g3dlite/G3D-v8.0_hotfix5.diff diff --git a/dep/g3dlite/G3D-v8.0.diff b/dep/g3dlite/G3D-v8.0_hotfix1.diff similarity index 83% rename from dep/g3dlite/G3D-v8.0.diff rename to dep/g3dlite/G3D-v8.0_hotfix1.diff index a82d5378a8b..ec90cebbecf 100644 --- a/dep/g3dlite/G3D-v8.0.diff +++ b/dep/g3dlite/G3D-v8.0_hotfix1.diff @@ -1,6 +1,6 @@ -diff -urN g3d-beta4/include/G3D/debugAssert.h g3d-mangos/include/G3D/debugAssert.h ---- g3d-beta4/include/G3D/debugAssert.h 2010-02-07 23:39:20.000000000 +0100 -+++ g3d-mangos/include/G3D/debugAssert.h 2010-08-26 21:36:32.000000000 +0200 +diff -urN a/dep/g3dlite/include/G3D/debugAssert.h b/dep/g3dlite/include/G3D/debugAssert.h +--- a/dep/g3dlite/include/G3D/debugAssert.h 2010-02-07 23:39:20.000000000 +0100 ++++ b/dep/g3dlite/include/G3D/debugAssert.h 2010-08-26 21:36:32.000000000 +0200 @@ -39,10 +39,12 @@ #ifdef G3D_LINUX // Needed so we can define a global display @@ -30,9 +30,9 @@ diff -urN g3d-beta4/include/G3D/debugAssert.h g3d-mangos/include/G3D/debugAssert /** Pops up an assertion dialog or prints an assertion -diff -urN g3d-beta4/include/G3D/g3dmath.h g3d-mangos/include/G3D/g3dmath.h ---- g3d-beta4/include/G3D/g3dmath.h 2010-02-07 23:39:20.000000000 +0100 -+++ g3d-mangos/include/G3D/g3dmath.h 2010-08-26 21:36:32.000000000 +0200 +diff -urN a/dep/g3dlite/include/G3D/g3dmath.h b/dep/g3dlite/include/G3D/g3dmath.h +--- a/dep/g3dlite/include/G3D/g3dmath.h 2010-02-07 23:39:20.000000000 +0100 ++++ b/dep/g3dlite/include/G3D/g3dmath.h 2010-08-26 21:36:32.000000000 +0200 @@ -65,6 +65,8 @@ return ::rand() / double(RAND_MAX); } @@ -62,9 +62,9 @@ diff -urN g3d-beta4/include/G3D/g3dmath.h g3d-mangos/include/G3D/g3dmath.h #endif -diff -urN g3d-beta4/include/G3D/platform.h g3d-mangos/include/G3D/platform.h ---- g3d-beta4/include/G3D/platform.h 2010-02-07 23:39:20.000000000 +0100 -+++ g3d-mangos/include/G3D/platform.h 2010-08-26 21:36:32.000000000 +0200 +diff -urN a/dep/g3dlite/include/G3D/platform.h b/dep/g3dlite/include/G3D/platform.h +--- a/dep/g3dlite/include/G3D/platform.h 2010-02-07 23:39:20.000000000 +0100 ++++ b/dep/g3dlite/include/G3D/platform.h 2010-08-26 21:36:32.000000000 +0200 @@ -56,12 +57,15 @@ // pi as a constant, which creates a conflict with G3D #define __FP__ @@ -97,9 +97,9 @@ diff -urN g3d-beta4/include/G3D/platform.h g3d-mangos/include/G3D/platform.h /** @def G3D_CHECK_PRINTF_METHOD_ARGS() Enables printf parameter validation on gcc. */ -diff -urN g3d-beta4/include/G3D/System.h g3d-mangos/include/G3D/System.h ---- g3d-beta4/include/G3D/System.h 2010-02-07 23:39:20.000000000 +0100 -+++ g3d-mangos/include/G3D/System.h 2010-08-26 21:36:32.000000000 +0200 +diff -urN a/dep/g3dlite/include/G3D/System.h b/dep/g3dlite/include/G3D/System.h +--- a/dep/g3dlite/include/G3D/System.h 2010-02-07 23:39:20.000000000 +0100 ++++ b/dep/g3dlite/include/G3D/System.h 2010-08-26 21:36:32.000000000 +0200 @@ -375,10 +375,10 @@ // count now contains the cycle count for the intervening operation. @@ -141,9 +141,9 @@ diff -urN g3d-beta4/include/G3D/System.h g3d-mangos/include/G3D/System.h } // namespace -diff -urN g3d-beta4/source/BinaryInput.cpp g3d-mangos/source/BinaryInput.cpp ---- g3d-beta4/source/BinaryInput.cpp 2010-02-07 23:39:20.000000000 +0100 -+++ g3d-mangos/source/BinaryInput.cpp 2010-08-15 11:37:26.000000000 +0200 +diff -urN a/dep/g3dlite/source/BinaryInput.cpp b/dep/g3dlite/source/BinaryInput.cpp +--- a/dep/g3dlite/source/BinaryInput.cpp 2010-02-07 23:39:20.000000000 +0100 ++++ b/dep/g3dlite/source/BinaryInput.cpp 2010-08-15 11:37:26.000000000 +0200 @@ -39,7 +39,9 @@ #include "G3D/Log.h" #include "G3D/FileSystem.h" @@ -171,9 +171,9 @@ diff -urN g3d-beta4/source/BinaryInput.cpp g3d-mangos/source/BinaryInput.cpp // Figure out how big the file is and verify that it exists. m_length = FileSystem::size(m_filename); -diff -urN g3d-beta4/source/debugAssert.cpp g3d-mangos/source/debugAssert.cpp ---- g3d-beta4/source/debugAssert.cpp 2010-02-07 23:39:20.000000000 +0100 -+++ g3d-mangos/source/debugAssert.cpp 2010-08-15 11:37:26.000000000 +0200 +diff -urN a/dep/g3dlite/source/debugAssert.cpp b/dep/g3dlite/source/debugAssert.cpp +--- a/dep/g3dlite/source/debugAssert.cpp 2010-02-07 23:39:20.000000000 +0100 ++++ b/dep/g3dlite/source/debugAssert.cpp 2010-08-15 11:37:26.000000000 +0200 @@ -37,9 +37,11 @@ AssertionHook _failureHook = _handleErrorCheck_; @@ -202,9 +202,9 @@ diff -urN g3d-beta4/source/debugAssert.cpp g3d-mangos/source/debugAssert.cpp #elif defined(G3D_OSX) // TODO: OS X #endif -diff -urN g3d-beta4/source/FileSystem.cpp g3d-mangos/source/FileSystem.cpp ---- g3d-beta4/source/FileSystem.cpp 2010-02-07 23:39:20.000000000 +0100 -+++ g3d-mangos/source/FileSystem.cpp 2010-08-15 11:37:26.000000000 +0200 +diff -urN a/dep/g3dlite/source/FileSystem.cpp b/dep/g3dlite/source/FileSystem.cpp +--- a/dep/g3dlite/source/FileSystem.cpp 2010-02-07 23:39:20.000000000 +0100 ++++ b/dep/g3dlite/source/FileSystem.cpp 2010-08-15 11:37:26.000000000 +0200 @@ -12,7 +12,9 @@ #include "G3D/fileutils.h" #include @@ -252,9 +252,9 @@ diff -urN g3d-beta4/source/FileSystem.cpp g3d-mangos/source/FileSystem.cpp } return st.st_size; -diff -urN g3d-beta4/source/fileutils.cpp g3d-mangos/source/fileutils.cpp ---- g3d-beta4/source/fileutils.cpp 2010-02-07 23:39:20.000000000 +0100 -+++ g3d-mangos/source/fileutils.cpp 2010-08-15 11:37:26.000000000 +0200 +diff -urN a/dep/g3dlite/source/fileutils.cpp b/dep/g3dlite/source/fileutils.cpp +--- a/dep/g3dlite/source/fileutils.cpp 2010-02-07 23:39:20.000000000 +0100 ++++ b/dep/g3dlite/source/fileutils.cpp 2010-08-15 11:37:26.000000000 +0200 @@ -20,7 +20,9 @@ #include @@ -368,9 +368,9 @@ diff -urN g3d-beta4/source/fileutils.cpp g3d-mangos/source/fileutils.cpp } -diff -urN g3d-beta4/source/prompt.cpp g3d-mangos/source/prompt.cpp ---- g3d-beta4/source/prompt.cpp 2010-02-07 23:39:20.000000000 +0100 -+++ g3d-mangos/source/prompt.cpp 2010-08-15 11:37:26.000000000 +0200 +diff -urN a/dep/g3dlite/source/prompt.cpp b/dep/g3dlite/source/prompt.cpp +--- a/dep/g3dlite/source/prompt.cpp 2010-02-07 23:39:20.000000000 +0100 ++++ b/dep/g3dlite/source/prompt.cpp 2010-08-15 11:37:26.000000000 +0200 @@ -21,6 +21,7 @@ # define _getch getchar #endif @@ -433,9 +433,9 @@ diff -urN g3d-beta4/source/prompt.cpp g3d-mangos/source/prompt.cpp return textPrompt(windowTitle, prompt, choice, numChoices); } -diff -urN g3d-beta4/source/RegistryUtil.cpp g3d-mangos/source/RegistryUtil.cpp ---- g3d-beta4/source/RegistryUtil.cpp 2010-02-07 23:39:20.000000000 +0100 -+++ g3d-mangos/source/RegistryUtil.cpp 2010-08-15 11:37:26.000000000 +0200 +diff -urN a/dep/g3dlite/source/RegistryUtil.cpp b/dep/g3dlite/source/RegistryUtil.cpp +--- a/dep/g3dlite/source/RegistryUtil.cpp 2010-02-07 23:39:20.000000000 +0100 ++++ b/dep/g3dlite/source/RegistryUtil.cpp 2010-08-15 11:37:26.000000000 +0200 @@ -257,7 +257,7 @@ @@ -445,9 +445,9 @@ diff -urN g3d-beta4/source/RegistryUtil.cpp g3d-mangos/source/RegistryUtil.cpp debugAssert(str); if (str) { -diff -urN g3d-beta4/source/System.cpp g3d-mangos/source/System.cpp ---- g3d-beta4/source/System.cpp 2010-02-07 23:39:20.000000000 +0100 -+++ g3d-mangos/source/System.cpp 2010-08-15 11:37:26.000000000 +0200 +diff -urN a/dep/g3dlite/source/System.cpp b/dep/g3dlite/source/System.cpp +--- a/dep/g3dlite/source/System.cpp 2010-02-07 23:39:20.000000000 +0100 ++++ b/dep/g3dlite/source/System.cpp 2010-08-15 11:37:26.000000000 +0200 @@ -80,8 +80,9 @@ #endif diff --git a/dep/g3dlite/G3D-v8.0_hotfix2.diff b/dep/g3dlite/G3D-v8.0_hotfix2.diff new file mode 100644 index 00000000000..bb66c4a6a29 --- /dev/null +++ b/dep/g3dlite/G3D-v8.0_hotfix2.diff @@ -0,0 +1,14 @@ +diff --git a/dep/g3dlite/source/g3dmath.cpp b/dep/g3dlite/source/g3dmath.cpp +index e846f8c..84e8345 100644 +--- a/dep/g3dlite/source/g3dmath.cpp ++++ b/dep/g3dlite/source/g3dmath.cpp +@@ -41,7 +41,7 @@ double inf() { + } + + bool isNaN(float x) { +- static const float n = nan(); ++ static const float n = fnan(); + return memcmp(&x, &n, sizeof(float)) == 0; + } + + diff --git a/dep/g3dlite/G3D-v8.0_hotfix3.diff b/dep/g3dlite/G3D-v8.0_hotfix3.diff new file mode 100644 index 00000000000..d556103c96d --- /dev/null +++ b/dep/g3dlite/G3D-v8.0_hotfix3.diff @@ -0,0 +1,12 @@ +diff --git a/dep/g3dlite/include/G3D/GMutex.h b/dep/g3dlite/include/G3D/GMutex.h +index 3469b81..9fe098d 100644 +--- a/dep/g3dlite/include/G3D/GMutex.h ++++ b/dep/g3dlite/include/G3D/GMutex.h +@@ -16,6 +16,7 @@ + #ifndef G3D_WIN32 + # include + # include ++# include + #endif + + diff --git a/dep/g3dlite/G3D-v8.0_extra.diff b/dep/g3dlite/G3D-v8.0_hotfix4.diff similarity index 59% rename from dep/g3dlite/G3D-v8.0_extra.diff rename to dep/g3dlite/G3D-v8.0_hotfix4.diff index 62c513435b9..cae92747a9a 100644 --- a/dep/g3dlite/G3D-v8.0_extra.diff +++ b/dep/g3dlite/G3D-v8.0_hotfix4.diff @@ -1,15 +1,3 @@ -diff --git a/dep/g3dlite/include/G3D/GMutex.h b/dep/g3dlite/include/G3D/GMutex.h -index 3469b81..9fe098d 100644 ---- a/dep/g3dlite/include/G3D/GMutex.h -+++ b/dep/g3dlite/include/G3D/GMutex.h -@@ -16,6 +16,7 @@ - #ifndef G3D_WIN32 - # include - # include -+# include - #endif - - diff --git a/dep/g3dlite/include/G3D/platform.h b/dep/g3dlite/include/G3D/platform.h index c8d2f0b..11093f4 100644 --- a/dep/g3dlite/include/G3D/platform.h diff --git a/dep/g3dlite/G3D-v8.0_hotfix5.diff b/dep/g3dlite/G3D-v8.0_hotfix5.diff new file mode 100644 index 00000000000..29b7eba811b --- /dev/null +++ b/dep/g3dlite/G3D-v8.0_hotfix5.diff @@ -0,0 +1,71 @@ +diff --git a/dep/g3dlite/include/G3D/System.h b/dep/g3dlite/include/G3D/System.h +index 1c0cf99..f160774 100644 +--- a/dep/g3dlite/include/G3D/System.h ++++ b/dep/g3dlite/include/G3D/System.h +@@ -19,6 +19,7 @@ + #include "G3D/G3DGameUnits.h" + #include "G3D/BinaryFormat.h" + #include ++#include + + #ifdef G3D_OSX + # include +diff --git a/dep/g3dlite/include/G3D/platform.h b/dep/g3dlite/include/G3D/platform.h +index 11093f4..614c0ed 100644 +--- a/dep/g3dlite/include/G3D/platform.h ++++ b/dep/g3dlite/include/G3D/platform.h +@@ -56,6 +56,8 @@ + #define G3D_LINUX + #elif defined(__linux__) + #define G3D_LINUX ++#elif defined(__CYGWIN__) ++ #define G3D_LINUX + #elif defined(__APPLE__) + #define G3D_LINUX + +diff --git a/dep/g3dlite/source/BinaryOutput.cpp b/dep/g3dlite/source/BinaryOutput.cpp +index 054211d..81fa982 100644 +--- a/dep/g3dlite/source/BinaryOutput.cpp ++++ b/dep/g3dlite/source/BinaryOutput.cpp +@@ -22,6 +22,10 @@ + # include + #endif + ++#ifdef __CYGWIN__ ++# include ++#endif ++ + // Largest memory buffer that the system will use for writing to + // disk. After this (or if the system runs out of memory) + // chunks of the file will be dumped to disk. +diff --git a/dep/g3dlite/source/FileSystem.cpp b/dep/g3dlite/source/FileSystem.cpp +index 2cf890a..76a3611 100644 +--- a/dep/g3dlite/source/FileSystem.cpp ++++ b/dep/g3dlite/source/FileSystem.cpp +@@ -35,6 +35,10 @@ + # define _stat stat + #endif + ++#ifdef __CYGWIN__ ++#define stat64 stat ++#endif ++ + namespace G3D { + + static FileSystem* common = NULL; +diff --git a/dep/g3dlite/source/System.cpp b/dep/g3dlite/source/System.cpp +index 809f05c..f6b0e03 100644 +--- a/dep/g3dlite/source/System.cpp ++++ b/dep/g3dlite/source/System.cpp +@@ -888,7 +888,11 @@ void System::initTime() { + + if (localTimeVals) { + // tm_gmtoff is already corrected for daylight savings. ++ #ifdef __CYGWIN__ ++ local = local + _timezone; ++ #else + local = local + localTimeVals->tm_gmtoff; ++ #endif + } + + m_realWorldGetTickTime0 = local; diff --git a/dep/g3dlite/Readme.txt b/dep/g3dlite/Readme.txt index b91c20dce38..055574ee654 100644 --- a/dep/g3dlite/Readme.txt +++ b/dep/g3dlite/Readme.txt @@ -1,3 +1,8 @@ - Due to issues with G3D (normally requiring X11 and the ZIP-library), the -sourcetree version contains a modified version. The applied patch is -commited to the repository for future reference. + Due to issues with G3D normally requiring X11 and the ZIP-library, the library version in this sourcetree contains a modified version. +The applied patches are added as .diff-files to the repository for future reference (knowing what was changed is quite handy). + +G3D-v8.0_hotfix1.diff - 2010-08-27 - remove dependency on zip/z11 libraries, add support for 64-bit arch +G3D-v8.0_hotfix2.diff - 2012-01-14 - fix typo in isNaN(float x) +G3D-v8.0_hotfix3.diff - 2012-08-26 - fix compilation on Fedora Linux +G3D-v8.0_hotfix4.diff - 2012-11-09 - fix compilation on OSX +G3D-v8.0_hotfix5.diff - 2013-02-27 - fix compilation in cygwin environments diff --git a/dep/g3dlite/include/G3D/System.h b/dep/g3dlite/include/G3D/System.h index 1c0cf99410c..f1607747bbe 100644 --- a/dep/g3dlite/include/G3D/System.h +++ b/dep/g3dlite/include/G3D/System.h @@ -19,6 +19,7 @@ #include "G3D/G3DGameUnits.h" #include "G3D/BinaryFormat.h" #include +#include #ifdef G3D_OSX # include diff --git a/dep/g3dlite/include/G3D/platform.h b/dep/g3dlite/include/G3D/platform.h index 11093f4a6ce..614c0ed7cad 100644 --- a/dep/g3dlite/include/G3D/platform.h +++ b/dep/g3dlite/include/G3D/platform.h @@ -56,6 +56,8 @@ #define G3D_LINUX #elif defined(__linux__) #define G3D_LINUX +#elif defined(__CYGWIN__) + #define G3D_LINUX #elif defined(__APPLE__) #define G3D_LINUX diff --git a/dep/g3dlite/source/BinaryOutput.cpp b/dep/g3dlite/source/BinaryOutput.cpp index 054211d906c..81fa9822206 100644 --- a/dep/g3dlite/source/BinaryOutput.cpp +++ b/dep/g3dlite/source/BinaryOutput.cpp @@ -22,6 +22,10 @@ # include #endif +#ifdef __CYGWIN__ +# include +#endif + // Largest memory buffer that the system will use for writing to // disk. After this (or if the system runs out of memory) // chunks of the file will be dumped to disk. diff --git a/dep/g3dlite/source/FileSystem.cpp b/dep/g3dlite/source/FileSystem.cpp index 2cf890a1cd5..76a361162c9 100644 --- a/dep/g3dlite/source/FileSystem.cpp +++ b/dep/g3dlite/source/FileSystem.cpp @@ -35,6 +35,10 @@ # define _stat stat #endif +#ifdef __CYGWIN__ +#define stat64 stat +#endif + namespace G3D { static FileSystem* common = NULL; diff --git a/dep/g3dlite/source/System.cpp b/dep/g3dlite/source/System.cpp index 809f05c0ab4..f6b0e038f27 100644 --- a/dep/g3dlite/source/System.cpp +++ b/dep/g3dlite/source/System.cpp @@ -888,7 +888,11 @@ void System::initTime() { if (localTimeVals) { // tm_gmtoff is already corrected for daylight savings. + #ifdef __CYGWIN__ + local = local + _timezone; + #else local = local + localTimeVals->tm_gmtoff; + #endif } m_realWorldGetTickTime0 = local; diff --git a/src/server/collision/BoundingIntervalHierarchy.cpp b/src/server/collision/BoundingIntervalHierarchy.cpp index bca738d1ff6..4c1f449da25 100644 --- a/src/server/collision/BoundingIntervalHierarchy.cpp +++ b/src/server/collision/BoundingIntervalHierarchy.cpp @@ -20,6 +20,8 @@ #if defined __APPLE__ #define isnan std::isnan +#elif defined __CYGWIN__ + #define isnan std::isnan #elif defined _MSC_VER #define isnan _isnan #endif diff --git a/src/server/shared/Common.h b/src/server/shared/Common.h index f4e4ce7fe06..44a7749334d 100644 --- a/src/server/shared/Common.h +++ b/src/server/shared/Common.h @@ -170,7 +170,7 @@ enum LocaleConstant }; const uint8 TOTAL_LOCALES = 9; -const LocaleConstant DEFAULT_LOCALE = LOCALE_enUS; +#define DEFAULT_LOCALE LOCALE_enUS #define MAX_LOCALES 8 #define MAX_ACCOUNT_TUTORIAL_VALUES 8 From 523e732c03b0cbd49aa367f435c75891167e7823 Mon Sep 17 00:00:00 2001 From: click Date: Thu, 28 Feb 2013 13:23:15 +0100 Subject: [PATCH 07/13] Core/Dep: G3D: Correction to patch G3D-v8.0_hotfix5.diff, add missing #ifdef -test (applied to sourcetree as well) --- dep/g3dlite/G3D-v8.0_hotfix5.diff | 6 ++++-- dep/g3dlite/include/G3D/System.h | 4 +++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/dep/g3dlite/G3D-v8.0_hotfix5.diff b/dep/g3dlite/G3D-v8.0_hotfix5.diff index 29b7eba811b..fd02b329c4a 100644 --- a/dep/g3dlite/G3D-v8.0_hotfix5.diff +++ b/dep/g3dlite/G3D-v8.0_hotfix5.diff @@ -2,11 +2,13 @@ diff --git a/dep/g3dlite/include/G3D/System.h b/dep/g3dlite/include/G3D/System.h index 1c0cf99..f160774 100644 --- a/dep/g3dlite/include/G3D/System.h +++ b/dep/g3dlite/include/G3D/System.h -@@ -19,6 +19,7 @@ +@@ -19,6 +19,9 @@ #include "G3D/G3DGameUnits.h" #include "G3D/BinaryFormat.h" #include -+#include ++#ifdef G3D_LINUX ++# include ++#endif #ifdef G3D_OSX # include diff --git a/dep/g3dlite/include/G3D/System.h b/dep/g3dlite/include/G3D/System.h index f1607747bbe..45aef1549b6 100644 --- a/dep/g3dlite/include/G3D/System.h +++ b/dep/g3dlite/include/G3D/System.h @@ -19,7 +19,9 @@ #include "G3D/G3DGameUnits.h" #include "G3D/BinaryFormat.h" #include -#include +#ifdef G3D_LINUX +# include +#endif #ifdef G3D_OSX # include From 6801314881598f0b1cce7a2e614ca7f314c1e129 Mon Sep 17 00:00:00 2001 From: Trista Date: Thu, 28 Feb 2013 18:44:07 +0200 Subject: [PATCH 08/13] Scripts/Eye of Eternity: Rewrite most of it. Closes: #1133, #8212, #1150, #5003, #6794 * More stuff will be done, a lot to clean maybe, as of raiding it's good to go now pretty much*. * Big thx to Shauren, Horn, manuel, Machiavelli, Nay, Krofna and rest who helped. --- .../2013_02_28_00_world_eye_of_eternity.sql | 200 ++ src/server/game/Spells/SpellMgr.cpp | 31 +- .../Nexus/EyeOfEternity/boss_malygos.cpp | 2858 ++++++++++++----- .../Nexus/EyeOfEternity/eye_of_eternity.h | 32 +- .../instance_eye_of_eternity.cpp | 83 +- 5 files changed, 2433 insertions(+), 771 deletions(-) create mode 100644 sql/updates/world/2013_02_28_00_world_eye_of_eternity.sql diff --git a/sql/updates/world/2013_02_28_00_world_eye_of_eternity.sql b/sql/updates/world/2013_02_28_00_world_eye_of_eternity.sql new file mode 100644 index 00000000000..9aef8f358d2 --- /dev/null +++ b/sql/updates/world/2013_02_28_00_world_eye_of_eternity.sql @@ -0,0 +1,200 @@ +-- Add spell script names +DELETE FROM `spell_script_names` WHERE `spell_id` IN (56046,56047,61693,61694,57459,56438,61210,56397,58842,59084,59099,56070,56072,60936,60939,61028,61023); +INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES +(56046, 'spell_malygos_portal_beam'), +(56047, 'spell_malygos_random_portal'), +(61693, 'spell_malygos_arcane_storm'), -- Phase I /10/ +(61694, 'spell_malygos_arcane_storm'), -- Phase I /25/ +(57459, 'spell_malygos_arcane_storm'), -- Phase III +(56438, 'spell_arcane_overload'), +(61210, 'spell_nexus_lord_align_disk_aggro'), +(56397, 'spell_scion_of_eternity_arcane_barrage'), +(58842, 'spell_malygos_destroy_platform_channel'), +(59084, 'spell_alexstrasza_bunny_destroy_platform_boom_visual'), +(59099, 'spell_alexstrasza_bunny_destroy_platform_event'), +(56070, 'spell_wyrmrest_skytalon_summon_red_dragon_buddy'), +(56072, 'spell_wyrmrest_skytalon_ride_red_dragon_buddy_trigger'), +(60936, 'spell_malygos_surge_of_power_25'), +(60939, 'spell_malygos_surge_of_power_warning_selector_25'), +(61028, 'spell_alexstrasza_gift_beam'), +(61023, 'spell_alexstrasza_gift_beam_visual'); + +-- Add spell difficulties +DELETE FROM `spelldifficulty_dbc` WHERE `id` IN (61693,56272,57058); +INSERT INTO `spelldifficulty_dbc` (`id`,`spellid0`,`spellid1`,`spellid2`,`spellid3`) VALUES +(61693,61693,61694,0,0), -- Arcane Storm - Phase I +(56272,56272,60072,0,0), -- Arcane Breath +(57058,57058,60073,0,0); -- Arcane Shock (Nexus Lord) + +-- Insert missing creature template addon +DELETE FROM `creature_template_addon` WHERE `entry` IN (28859,30234,30248,32295,30592,31748,31749); +INSERT INTO `creature_template_addon` (`entry`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES +(28859,0,0,0x1000000|0x2000000,0x1,0, ''), -- Malygos +(30234,0,0,0x1000000|0x2000000,0x1,0, '43775'), -- Hover Disk (Nexus Lord), add aura "Flight" +(30248,0,0,0x1000000|0x2000000,0x1,0, '43775'), -- Hover Disk (Scion of Eternity), add aura "Flight" +(31748,0,0,0x1000000|0x2000000,0x1,0, '43775'), -- Hover Disk Difficulty (Nexus Lord), add aura "Flight" +(31749,0,0,0x1000000|0x2000000,0x1,0, '43775'), -- Hover Disk Difficulty (Scion of Eternity), add aura "Flight" +(32295,0,0,0x1000000|0x2000000,0x1,0, ''), -- Alexstrasza +(30592,0,0,0x1000000|0x2000000,0x1,0, '57428'); -- Static Field bunny + +-- Add, restructure and update missing texts and sounds +DELETE FROM `creature_text` WHERE `entry` IN (28859,32295); +INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`language`,`probability`,`emote`,`duration`,`sound`,`comment`) VALUES +(28859,0,0, 'Lesser beings, intruding here! A shame that your excess courage does not compensate for your stupidity!',14,0,100,0,10000,14512,'Malygos - Intro'), +(28859,0,1, 'None but the blue dragonflight are welcome here. Perhaps this is the work of Alexstrasza? Well, then, she has sent you to your deaths!',14,0,100,0,11000,14513,'Malygos - Intro'), +(28859,0,2, 'What could you hope to accomplish? To storm brazenly into my domain... to employ magic... against ME?',14,0,100,0,13000,14514,'Malygos - Intro'), +(28859,0,3, 'I am without limits here. The rules of your cherished reality do not apply. In this realm, I am in control!',14,0,100,0,10000,14515,'Malygos - Intro'), +(28859,0,4, 'I give you one chance. Pledge fealty to me, and perhaps I will not slaughter you for your insolence.',14,0,100,0,7000,14516,'Malygos - Intro'), +(28859,1,0, 'My patience has reached its limit, I will be rid of you!',14,0,100,0,4000,14517,'Malygos - Start phase 1'), +(28859,2,0, 'You will not succeed while I draw breath!',14,0,100,0,3000,14518,'Malygos - Begin to cast Deep Breath'), +(28859,3,0, 'Your stupidity has finally caught up to you!',14,0,100,0,3250,14519,'Malygos - Killed Player (Phase 1)'), +(28859,3,1, 'More artifacts to confiscate...',14,0,100,0,2800,14520,'Malygos - Killed Player (Phase 1)'), +(28859,3,2, 'How very naive.',14,0,100,0,4800,14521,'Malygos - Killed Player (Phase 1)'), +(28859,4,0, 'I had hoped to end your lives quickly, but you have proven more... resilient than I anticipated. Nonetheless, your efforts are in vain. It is you reckless, careless mortals who are to blame for this war. I do what I must, and if it means your extinction.... then SO BE IT!!',14,0,100,0,22900,14522,'Malygos - End Phase One'), +(28859,5,0, 'Few have experienced the pain I will now inflict upon you!',14,0,100,0,5500,14523,'Malygos - Start phase 2'), -- Unused by Blizzard for some reason +(28859,6,0, 'I will teach you IGNORANT children just how little you know of magic...',14,0,100,0,7000,14524,'Malygos - Anti-Magic Shell'), +(28859,7,0, 'Watch helplessly as your hopes are swept away...',14,0,100,0,4000,14525,'Malygos - Magic Blast'), +(28859,8,0, 'Your energy will be put to good use!',14,0,100,0,2000,14526,'Malygos - Killed Player (Phase 2)'), +(28859,8,1, 'I am the spell-weaver! My power is infinite!',14,0,100,0,5200,14527,'Malygos - Killed Player (Phase 2)'), +(28859,8,2, 'Your spirit will linger here forever!',14,0,100,0,3800,14528,'Malygos - Killed Player (Phase 2)'), +(28859,9,0, 'ENOUGH! If you intend to reclaim Azeroth''s magic, then you shall have it...',14,0,100,0,7000,14529,'Malygos - End Phase 2'), +(28859,10,0, 'Now your benefactors make their appearance... But they are too late. The powers contained here are sufficient to destroy the world ten times over! What do you think they will do to you?',14,0,100,0,13000,14530,'Intro Phase 3'), +(28859,11,0, 'SUBMIT!',14,0,100,0,1000,14531,'Malygos - Start phase 3'), -- Unused by Blizzard for some reason +(28859,12,0, 'Malygos takes a deep breath.',41,0,100,0,10000,0,'Malygos - Surge of Power warning (Phase 2)'), +(28859,13,0, 'The powers at work here exceed anything you could possibly imagine!',14,0,100,0,5000,14532,'Malygos - Surge of Power'), +(28859,14,0, 'I AM UNSTOPPABLE!',14,0,100,0,2000,14533,'Malygos - Buffed by a spark'), +(28859,15,0, 'Alexstrasza! Another of your brood falls!',14,0,100,0,3600,14534,'Malygos - Killed Player (Phase 3)'), +(28859,15,1, 'Little more then gnats!',14,0,100,0,2650,14535,'Malygos - Killed Player (Phase 3)'), +(28859,15,2, 'Your red allies will share your fate...',14,0,100,0,3000,14536,'Malygos - Killed Player (Phase 3)'), +(28859,16,0, 'Still standing? Not for long...',14,0,100,0,3600,14537,'Malygos - Spell Casting 1(Phase 3)'), +(28859,16,1, 'Your cause is lost!',14,0,100,0,2000,14538,'Malygos - Spell Casting 2 (Phase 3)'), +(28859,16,2, 'Your fragile mind will be shattered!',14,0,100,0,4000,14539,'Malygos - Spell Casting 3 (Phase 3)'), +(28859,17,0, 'Unthinkable! The mortals will destroy... everything! My sister, what have you...',14,0,100,0,8500,14540,'Malygos - Death'), +(28859,18,0, '%s fixes his eyes on you!',42,0,100,0,3000,0,'Malygos - Surge of Power warning (Phase 3)'), +(28859,19,0, '%s goes into a berserker rage!',41,0,100,0,10000,0,'Malygos - Hit berserk timer (Any phase)'), +(32295,0,0, 'I did what I had to, brother. You gave me no alternative.',14,0,100,0,4000,14406,'Alexstrasza - Yell text 1'), +(32295,1,0, 'And so ends the Nexus War.',14,0,100,0,4000,14407,'Alexstrasza - Yell text 2'), +(32295,2,0, 'This resolution pains me deeply, but the destruction, the monumental loss of life had to end. Regardless of Malygos''s recent transgressions, I will mourn his loss. He was once a guardian, a protector. This day, one of the world''s mightiest has fallen.',14,0,100,0,24000,14408,'Alexstrasza - Yell text 3'), +(32295,3,0, 'The red dragonflight will take on the burden of mending the devastation wrought on Azeroth. Return home to your people and rest. Tomorrow will bring you new challenges, and you must be ready to face them. Life... goes on.',14,0,100,0,22000,14409,'Alexstrasza - Yell text 4'); +-- Update wrong sound and add duration for Power Sparks warning +UPDATE `creature_text` SET `duration`=10000,`sound`=0 WHERE `entry`=30084 AND `groupid`=0 AND`id`=0; + +-- Add conditions +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry` IN (56047,58846,61028,56429,56505,59099,61714,61715,57432,57429,61210,56548,56431,56438); +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`SourceId`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionTarget`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorType`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES +(13,1,56047,0,0,31,0,3,30118,0,0,0,0,'', 'Random Portal can implicitly hit only Portal (Malygos)'), +(13,1,56047,0,0,29,0,28859,30,0,1,0,0,'', 'Random Portal can implicitly hit only target that is not in 30 yards near Malygos'), +(13,1,58846,0,0,32,0,0x0010,0,0,0,0,0,'', 'Summon Red Dragon Buddy force cast can implicitly hit only players'), +(13,1,61028,0,0,31,0,3,32448,0,0,0,0,'', 'Alexstrasza''s Gift Beam can hit only Alexstrasza''s Gift'), +(13,1,56429,0,0,31,0,3,31253,0,0,0,0,'', 'Summon Arcane Bomb can hit only Alexstrasza the Life-Binder (bunny)'), +(13,1,56505,0,0,31,0,3,30334,0,0,0,0,'', 'Surge of Power (phase II) can hit only Surge of Power'), +(13,1,56548,0,0,31,0,3,30234,0,1,0,0,'', 'Surge of Power triggered damage spell (phase II) can''t hit melee Hover Disk'), +(13,3,56431,0,0,31,0,3,30234,0,1,0,0,'', 'Arcane Overload damage and knockback spell can''t hit melee Hover Disk'), +(13,1,56438,0,0,1,0,1,56438,0,1,0,0,'', 'Arcane Overload damage reduce aura can''t apply to target that already is affected by such'), +(13,6,59099,0,0,32,0,0x0010,0,0,0,0,0,'', 'Destroy Platform Event effect 1 and 2 can hit only players'), +(13,7,61714,0,0,31,0,3,30245,0,0,0,0,'', 'Berserk (spell 2) can hit Nexus Lord'), +(13,7,61714,0,1,31,0,3,30249,0,0,0,0,'', 'Berserk (spell 2) can hit Scion of Eternity'), +(13,7,61715,0,0,31,0,3,30592,0,0,0,0,'', 'Berserk (spell 3) can hit Static Field bunny'), +(13,1,57432,0,0,31,0,3,30161,0,0,0,0,'', 'Arcane Pulse can hit only drakes'), +(13,3,57429,0,0,31,0,3,30161,0,0,0,0,'', 'Static Field can hit only drakes'), +(13,1,61210,0,0,33,1,0,4,0,0,0,0,'', 'Align Disk Aggro can only hit the vehicle of the passenger caster'); + +-- Add missing equipment +DELETE FROM `creature_equip_template` WHERE `entry` IN (30245,31750,30249,31751); +INSERT INTO `creature_equip_template` (`entry`,`id`,`itemEntry1`,`itemEntry2`,`itemEntry3`) VALUES +(30245,1,30714,0,0), -- Nexus Lord +(31750,1,30714,0,0), -- Nexus Lord (Difficulty) +(30249,1,29107,0,0), -- Scion of Eternity +(31751,1,29107,0,0); -- Scion of Eternity (Difficulty) + +-- Update accessories of hover disks to die with the vehicle and have lower despawn time. They should fall from hover disks, +-- and despawn after 5 sec, but for some reason they keep staying standing while dead. This needs to be fixed coreside. +UPDATE `vehicle_template_accessory` SET `minion`=1,`summontype`=6,`summontimer`=1000 WHERE `entry`=30234 AND `seat_id`=0; +UPDATE `vehicle_template_accessory` SET `minion`=1,`summontype`=6,`summontimer`=1000 WHERE `entry`=30248 AND `seat_id`=0; + +-- Add flag GO not selectable for both and extra condition for Heart of Magic +UPDATE `gameobject_template` SET `flags`=16 WHERE `entry`=193967; -- Alexstrasza Gift +UPDATE `gameobject_template` SET `flags`=20 WHERE `entry`=194159; -- Heart of Magic + +-- Add some gameobject data update +UPDATE `gameobject` SET `animprogress`=255,`spawntimesecs`=300 WHERE `guid` IN (151791,193960); -- that spawn time has no influence, but having different values doesn't look correct + +-- Delete static GO spawns of Alexstrasza's Gift Boxes, they are dynamic (10/25) +DELETE FROM `gameobject` WHERE `guid` IN (151792,151793); + +-- Add map difficulty checks for achievement "Denyin the Scion" +DELETE FROM `achievement_criteria_data` WHERE `criteria_id` IN (7573,7574) AND `type`=12; +INSERT INTO `achievement_criteria_data` (`criteria_id`,`type`,`value1`) VALUES +(7573,12,0), -- 10 mode +(7574,12,1); -- 25 mode + +-- Delete Nexus Lords SAI script, because of incapacity to handle the combat spell mechanic of Arcane Shock correctly +-- Delete Scions of Eternity SAI script, because of incapacity to handle non reactive AI when being attacked in a way it won't bug other encounter mechanics. +DELETE FROM `smart_scripts` WHERE `entryorguid` IN (30245,30249) AND `source_type`=0; + +-- Add SAI support for Alexstrasza since is only short timed event after boss mechanic ends +SET @NPC_ALEXSTRASZA := 32295; +SET @ACTIONLIST := @NPC_ALEXSTRASZA * 100; +SET @SPELL_GIFT_BEAM := 61028; + +UPDATE `creature_template` SET `AIName`='SmartAI',`ScriptName`='' WHERE `entry`=@NPC_ALEXSTRASZA; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@NPC_ALEXSTRASZA AND `source_type`=0; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@ACTIONLIST AND `source_type`=9; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@NPC_ALEXSTRASZA,0,0,0,54,0,100,0,0,0,0,0,69,1,0,0,0,0,0,8,0,0,0,788.07,1276.09,246.9,0,'Alexstrasza - On just summoned - Move to pos'), +(@NPC_ALEXSTRASZA,0,1,0,34,0,100,0,8,1,0,0,80,@ACTIONLIST,2,0,0,0,0,1,0,0,0,0,0,0,0,'Alexstrasza - On point 1 reached - Start actionlist'), +(@ACTIONLIST,9,0,0,0,0,100,0,0,0,0,0,11,@SPELL_GIFT_BEAM,0,0,0,0,0,1,0,0,0,0,0,0,0,'Alexstrasza - Action 0 - Cast Gift Beam'), +(@ACTIONLIST,9,1,0,0,0,100,0,4000,4000,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,'Alexstrasza - Action 1 - Yell 0'), +(@ACTIONLIST,9,2,0,0,0,100,0,6000,6000,0,0,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,'Alexstrasza - Action 2 - Yell 1'), +(@ACTIONLIST,9,3,0,0,0,100,0,5000,5000,0,0,1,2,0,0,0,0,0,1,0,0,0,0,0,0,0,'Alexstrasza - Action 3 - Yell 2'), +(@ACTIONLIST,9,4,0,0,0,100,0,24000,24000,0,0,1,3,0,0,0,0,0,1,0,0,0,0,0,0,0,'Alexstrasza - Action 4 - Yell 3'); + +-- Add areatrigger script for the improvised platform that is killing/rooting falling players +DELETE FROM `areatrigger_scripts` WHERE `entry`=5342; +INSERT INTO `areatrigger_scripts` (`entry`,`ScriptName`) VALUES +(5342, 'at_eye_of_eternity_improvised_floor'); + +-- /////////////// Various misc in creature, creature template and creature addon /////////////// +-- Update some guids spawn positions +UPDATE `creature` SET `position_x`=754.362,`position_y`=1301.61,`position_z`=266.171,`orientation`=4.24115 WHERE `guid`=132302; -- Alexstrasza the Life-Binder (Bunny) +UPDATE `creature` SET `position_x`=747.61,`position_y`=1393.43,`position_z`=295.9722,`orientation`=3.03832 WHERE `guid`=132313; -- Malygos + +-- Update some creature guids to be have static MovementType and spawn dist to 0 accordingly +UPDATE `creature` SET `spawndist`=0,`MovementType`=0 WHERE `guid` IN +(132313, -- Malygos +132314, -- Alexstrasza''s Gift Bunny +132302); -- Alexstrasza the Life-Binder (Bunny) + +-- Update template to InhabitType "Air" for various creatures +UPDATE `creature_template` SET `InhabitType`=4 WHERE `entry` IN (28859,31734,30245,31750,30249,31751,32295,32448); + +-- Clear scripts names for Alexstrasza the Life-Binder (Bunny) +UPDATE `creature_template` SET `AIName`='',`ScriptName`='' WHERE `entry`=31253; + +-- Update Portal (Malygos) initial flags before the encounter starts +UPDATE `creature_template` SET `unit_flags`=`unit_flags`|0x00000100|0x02000000,`flags_extra`=128 WHERE `entry`=30118; -- Immunity to Players + Not selectable + +-- Update flags extra to trigger & civilian for Static Field and add script name +UPDATE `creature_template` SET `AIName`='',`ScriptName`='npc_static_field',`flags_extra`=130 WHERE `entry`=30592; + +-- Update flags extra to extra trigger & extra civilian for Alexstrasza Bunny +UPDATE `creature_template` SET `flags_extra`=130, `ScriptName`='' WHERE `entry`=31253; + +-- Remove uneeded creature_addon data +DELETE FROM `creature_addon` WHERE `guid` IN +(30592, -- The spawn for Static Field is dynamique, so not fixed guid. +132313); -- Malygos is boss so is unique and needs only the template addon. + +-- Update templates for both types of hover disks +UPDATE `creature_template` SET `faction_A`=14,`faction_H`=14,`VehicleId`=223,`InhabitType`=4 WHERE `entry` IN (30248,31749); -- Hover disk for Scions +UPDATE `creature_template` SET `ScriptName`='npc_caster_hover_disk' WHERE `entry`=30248; +UPDATE `creature_template` SET `faction_A`=14,`faction_H`=14,`InhabitType`=4 WHERE `entry` IN (30234,31748); -- Hover disk for Nexus Lords +UPDATE `creature_template` SET `ScriptName`='npc_melee_hover_disk' WHERE `entry`=30234; +UPDATE `creature_template` SET `AIName`='',`ScriptName`='npc_nexus_lord' WHERE `entry`=30245; -- Nexus Lord +UPDATE `creature_template` SET `AIName`='',`ScriptName`='npc_scion_of_eternity' WHERE `entry`=30249; -- Scion of Eternity + +-- Fix model display for Vortex Triggers (in creature handling). +-- Remove extra trigger flag because for some reason it was bugging model displaying as always visible, +-- since it has the invisible one for triggers first and other as second, this is the only nonhacky way (don't try to change it unless core side != c++ hack in instance script) +UPDATE `creature_template` SET `flags_extra`=flags_extra &~ 0x00000080 WHERE `entry`=30090; +UPDATE `creature` SET `modelid`=11686 WHERE `guid` BETWEEN 132304 AND 132308; diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index 1795c46b342..059e552d95e 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -3609,6 +3609,30 @@ void SpellMgr::LoadDbcDataCorrections() break; // ENDOF RUBY SANCTUM SPELLS // + // EYE OF ETERNITY SPELLS + // All spells below work even without these changes. The LOS attribute is due to problem + // from collision between maps & gos with active destroyed state. + case 57473: // Arcane Storm bonus explicit visual spell + case 57430: // Summon Static Field + case 56091: // Flame Spike (Wyrmrest Skytalon) + case 56092: // Engulf in Flames (Wyrmrest Skytalon) + case 57090: // Revivify (Wyrmrest Skytalon) + case 57143: // Life Burst (Wyrmrest Skytalon) + spellInfo->AttributesEx2 |= SPELL_ATTR2_CAN_TARGET_NOT_IN_LOS; + break; + // ENDOF EYE OF ETERNITY SPELLS + // + // OCULUS SPELLS + // The spells below are here because their effect 1 is giving warning due to + // triggered spell not found in any dbc and is missing from encounter source* of data. + // Even judged as clientside these spells can't be guessed for* now. + case 49462: // Call Ruby Drake + case 49461: // Call Amber Drake + case 49345: // Call Emerald Drake + spellInfo->Effect[1] = 0; + break; + // ENDOF OCULUS SPELLS + // case 40055: // Introspection case 40165: // Introspection case 40166: // Introspection @@ -3622,13 +3646,6 @@ void SpellMgr::LoadDbcDataCorrections() spellInfo->manaCost = 0; spellInfo->manaPerSecond = 0; break; - // OCULUS SPELLS - // The spells below are here, because their effect 1 is giving warning, because the triggered spell is not found in dbc and is missing from encounter sniff. - case 49462: // Call Ruby Drake - case 49461: // Call Amber Drake - case 49345: // Call Emerald Drake - spellInfo->Effect[1] = 0; - break; case 24314: // Threatening Gaze spellInfo->AuraInterruptFlags |= AURA_INTERRUPT_FLAG_CAST | AURA_INTERRUPT_FLAG_MOVE | AURA_INTERRUPT_FLAG_JUMP; default: diff --git a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp index b0a34047c0e..658fa48fd3a 100644 --- a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp +++ b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp @@ -16,143 +16,208 @@ */ /* Script Data Start -SDName: Boss malygos +SDName: Boss Malygos Script Data End */ -// TO-DOs: -// Implement a better pathing for Malygos. -// Find sniffed spawn position for chest -// Implement a better way to disappear the gameobjects -// Implement achievements -// Remove hack that re-adds targets to the aggro list after they enter to a vehicle when it works as expected -// Improve whatever can be improved :) +/* Check TO DOs in the script, but here is one essential hack to be removed only if core changes are made: + At Wyrmrest Skytalon script I make it kill player if the drake dies, because at 100.0f z yards the map is + supposed to handle the air as ground or something to which you will fall and die. However, currently maps/movements + stop flying below it, however they don't stop movementflag FALLING. Which leads to % player falling at - 1200000.0 z, + Which leads due to some desynch to not being able to press "release spirit". + Also the teleport using while on vehicle is lacking support, but soon will have. + You can still click afer leaving vehicle. */ #include "ScriptMgr.h" #include "ScriptedCreature.h" #include "SpellScript.h" #include "SpellAuraEffects.h" -#include "PassiveAI.h" #include "eye_of_eternity.h" -#include "ScriptedEscortAI.h" #include "Player.h" #include "Vehicle.h" #include "CombatAI.h" +#include "GameObjectAI.h" #include "CreatureTextMgr.h" - -enum Achievements -{ - ACHIEV_TIMED_START_EVENT = 20387, -}; +#include "MoveSplineInit.h" enum Events { + // =========== INTRO BEFORE WE START ENCOUNTER =============== + EVENT_STOP_PORTAL_BEAM = 1, + EVENT_RANDOM_PORTAL = 2, + EVENT_SAY_INTRO = 3, + EVENT_LAND_START_ENCOUNTER = 4, + // =========== PHASE ONE =============== - EVENT_ARCANE_BREATH = 1, - EVENT_ARCANE_STORM = 2, - EVENT_VORTEX = 3, - EVENT_POWER_SPARKS = 4, + EVENT_ARCANE_BREATH = 5, + EVENT_ARCANE_STORM = 6, + EVENT_VORTEX = 7, + EVENT_POWER_SPARKS = 8, // =========== PHASE TWO =============== - EVENT_SURGE_POWER = 5, // wowhead is wrong, Surge of Power is casted instead of Arcane Pulse (source sniffs!) - EVENT_SUMMON_ARCANE = 6, + EVENT_FLY_OUT_OF_PLATFORM = 9, + EVENT_DELAYED_REINFORCEMENTS = 10, + EVENT_PATHING_AROUND_PLATFORM = 11, + EVENT_SURGE_OF_POWER_P_TWO = 12, + EVENT_SUMMON_ARCANE_BOMB = 13, + EVENT_MOVE_TO_POINT_SURGE_P_TWO = 14, + EVENT_LIGHT_DIMENSION_CHANGE = 15, + EVENT_MOVE_TO_P_THREE_POINT = 16, + EVENT_START_P_THREE = 17, - // =========== PHASE TWO =============== - EVENT_SURGE_POWER_PHASE_3 = 7, - EVENT_STATIC_FIELD = 8, + // =========== PHASE THREE ============= + EVENT_ARCANE_PULSE = 18, + EVENT_SURGE_OF_POWER_P_THREE = 19, + EVENT_STATIC_FIELD = 20, - // =============== YELLS =============== - EVENT_YELL_0 = 9, - EVENT_YELL_1 = 10, - EVENT_YELL_2 = 11, - EVENT_YELL_3 = 12, - EVENT_YELL_4 = 13, + // ========== MISC MECHANICS =========== + EVENT_PREVENT_SAY_SPAM_ON_KILL = 21, + EVENT_MOVE_TO_VORTEX_POINT = 22, // This should be fixed someday in core, we can't call new movement from MovementInform + EVENT_START_FIRST_RANDOM_PORTAL = 23, // There is something that is still loading when we first enter instance and it breaks + // first visual cast of intro portal beam mechanic, so we need short delay from the event. + // ============ NEXUS LORDS ============ + EVENT_ARCANE_SHOCK = 1, + EVENT_HASTE_BUFF = 2, + EVENT_NUKE_DUMMY = 3, + + // ======== SCIONS OF ETERNITY ========= + EVENT_ARCANE_BARRAGE = 1 }; enum Phases { - PHASE_ONE = 1, - PHASE_TWO = 2, - PHASE_THREE = 3 + PHASE_NOT_STARTED = 1, + PHASE_ONE = 2, + PHASE_TWO = 3, + PHASE_THREE = 4 }; enum Spells { - SPELL_ARCANE_BREATH = 56272, - SPELL_ARCANE_STORM = 57459, - SPELL_BERSEKER = 60670, + // Intro + SPELL_RANDOM_PORTAL = 56047, + SPELL_PORTAL_BEAM = 56046, // Malygos cast on portal to activate it during PHASE_NOT_STARTED - SPELL_VORTEX_1 = 56237, // seems that frezze object animation - SPELL_VORTEX_2 = 55873, // visual effect - SPELL_VORTEX_3 = 56105, // this spell must handle all the script - casted by the boss and to himself - //SPELL_VORTEX_4 = 55853, // damage | used to enter to the vehicle - defined in eye_of_eternity.h - //SPELL_VORTEX_5 = 56263, // damage | used to enter to the vehicle - defined in eye_of_eternity.h - SPELL_VORTEX_6 = 73040, // teleport - (casted to all raid) | caster 30090 | target player + //Phase I + SPELL_BERSEKER = 60670, + SPELL_MALYGOS_BERSERK = 47008, // it's the berserk spell that will hit only Malygos after 10 min of 60670 + SPELL_PORTAL_VISUAL_CLOSED = 55949, + SPELL_SUMMON_POWER_PARK = 56142, + SPELL_POWER_SPARK_DEATH = 55852, + SPELL_POWER_SPARK_MALYGOS = 56152, + SPELL_ARCANE_BREATH = 56272, + SPELL_ARCANE_STORM_P_I = 61693, + SPELL_VORTEX_1 = 56237, // seems that frezze object animation + SPELL_VORTEX_2 = 55873, // visual effect + SPELL_VORTEX_3 = 56105, // this spell must handle all the script - casted by the boss and to himself + SPELL_VORTEX_6 = 73040, // teleport - (casted to all raid), caster vortex bunnies, targets players. - SPELL_PORTAL_VISUAL_CLOSED = 55949, - SPELL_SUMMON_POWER_PARK = 56142, - SPELL_POWER_SPARK_DEATH = 55852, - SPELL_POWER_SPARK_MALYGOS = 56152, + // Phase II + SPELL_TELEPORT_VISUAL_ONLY = 41232, // Light blue animation cast by arcane NPCs when spawned on Hover Disks + SPELL_RIDE_HOVER_DISK = 61421, + SPELL_ALIGN_DISK_AGGRO = 61210, + SPELL_DUMMY_NUKE = 61215, + SPELL_SUMMON_ARCANE_BOMB = 56429, + SPELL_ARCANE_BOMB_TRIGGER = 56430, + SPELL_ARCANE_BOMB_KNOCKBACK_DAMAGE = 56431, + SPELL_ARCANE_OVERLOAD_1 = 56432, // casted by npc Arcane Overload ID: 30282 + // SPELL_ARCANE_OVERLOAD_2 = 56435, // Triggered by 56432 + // SPELL_ARCANE_OVERLOAD_3 = 56438, // Triggered by 56432 + SPELL_SURGE_OF_POWER_P_II = 56505, + // SPELL_SURGE_OF_POWER_TRIGGERED = 56548, + SPELL_ARCANE_SHOCK = 57058, // used by Nexus Lords + SPELL_HASTE = 57060, // used by Nexus Lords + SPELL_ARCANE_BARRAGE = 56397, // used by Scions of Eternity - SPELL_SURGE_POWER = 56505, // used in phase 2 - SPELL_SUMMON_ARCANE_BOMB = 56429, - SPELL_ARCANE_OVERLOAD = 56432, - SPELL_SUMMOM_RED_DRAGON = 56070, - SPELL_SURGE_POWER_PHASE_3 = 57407, - SPELL_STATIC_FIELD = 57430 + // Transition /II-III/ + SPELL_SUMMOM_RED_DRAGON_BUDYY = 56070, + SPELL_RIDE_RED_DRAGON_BUDDY = 56071, + SPELL_SUMMON_RED_DRAGON_BUDDY_F_CAST = 58846, // After implicitly hit player targets they will force cast 56070 on self + SPELL_DESTROY_PLATFORM_CHANNEL = 58842, + SPELL_DESTROY_PLATFORM_BOOM_VISUAL = 59084, + SPELL_DESTROY_PLATFORM_EVENT = 59099, + + // Phase III + SPELL_CLEAR_ALL_DEBUFFS = 34098, + SPELL_IMMUNE_CURSES = 64515, + SPELL_STATIC_FIELD_MISSLE = 57430, + SPELL_ARCANE_PULSE = 57432, + SPELL_SURGE_OF_POWER_PHASE_3_10 = 57407, + SPELL_SURGE_OF_POWER_PHASE_3_25 = 60936, + SPELL_SURGE_OF_POWER_WARNING_SELECTOR_25 = 60939, // used in 25 player mode for selecting targets for warnings and then sends to actual spell + SPELL_ARCANE_STORM_P_III = 57459, + + // Phase I and III + SPELL_ARCANE_STORM_EXTRA_VISUAL = 57473, + + // Outro + SPELL_ALEXSTRASZAS_GIFT_BEAM_VISUAL = 61023 }; enum Movements { - MOVE_VORTEX = 1, - MOVE_PHASE_TWO, - MOVE_DEEP_BREATH_ROTATION, - MOVE_INIT_PHASE_ONE, - MOVE_CENTER_PLATFORM + POINT_NEAR_RANDOM_PORTAL_P_NONE = 1, + POINT_LAND_P_ONE, + POINT_VORTEX_P_ONE, + POINT_LAND_AFTER_VORTEX_P_ONE, + POINT_LIFT_IN_AIR_P_ONE, + POINT_PHASE_ONE_TO_TWO_TRANSITION, + POINT_FLY_OUT_OF_PLATFORM_P_TWO, + POINT_SURGE_OF_POWER_P_TWO, + POINT_DESTROY_PLATFORM_P_TWO, + POINT_IDLE_P_THREE, }; enum Seats { - SEAT_0 = 0, + SEAT_0 = 0 }; enum Factions { - FACTION_FRIENDLY = 35, - FACTION_HOSTILE = 14 + // Needed for melee hover disks /when Nexus Lords die/ + FACTION_FRIENDLY = 35 }; enum Actions { - ACTION_HOVER_DISK_START_WP_1, - ACTION_HOVER_DISK_START_WP_2 -}; + // Malygos + ACTION_LAND_ENCOUNTER_START = 0, + ACTION_EXECUTE_VORTEX = 1, + ACTION_HANDLE_P_THREE_INTRO = 2, + ACTION_LIFT_IN_AIR = 3, + ACTION_HANDLE_RESPAWN = 4, + ACTION_CYCLIC_MOVEMENT = 5, -enum MalygosEvents -{ - DATA_SUMMON_DEATHS, // phase 2 - DATA_PHASE -}; + // Caster hover disk despawn action + ACTION_DELAYED_DESPAWN = 8, -#define TEN_MINUTES 600000 + // Nexus Lord's action used to shedule casting spell that determine disk's target to chase + ACTION_SET_DISK_VICTIM_CHASE = 0 +}; enum Texts { // Malygos - SAY_AGGRO_P_ONE = 0, - SAY_KILLED_PLAYER_P_ONE = 1, - SAY_END_P_ONE = 2, - SAY_AGGRO_P_TWO = 3, - SAY_ANTI_MAGIC_SHELL = 4, // not sure when execute it - SAY_MAGIC_BLAST = 5, // not sure when execute it - SAY_KILLED_PLAYER_P_TWO = 6, - SAY_END_P_TWO = 7, - SAY_INTRO_P_THREE = 8, - SAY_AGGRO_P_THREE = 9, - SAY_SURGE_POWER = 10, // not sure when execute it - SAY_BUFF_SPARK = 11, - SAY_KILLED_PLAYER_P_THREE = 12, - SAY_SPELL_CASTING_P_THREE = 13, - SAY_DEATH, + SAY_INTRO_EVENT = 0, + SAY_START_P_ONE = 1, + SAY_DEEP_BREATH = 2, + SAY_KILLED_PLAYER_P_ONE = 3, + SAY_END_P_ONE = 4, + // SAY_START_P_TWO = 5, // Unused by Blizzard for some reason on any version + SAY_ANTI_MAGIC_SHELL = 6, + SAY_MAGIC_BLAST = 7, + SAY_KILLED_PLAYER_P_TWO = 8, + SAY_END_P_TWO = 9, + SAY_START_P_THREE = 10, + // SAY_START_P_THREE = 11, // Unused by Blizzard for some reason on any version + EMOTE_SURGE_OF_POWER_WARNING_P2 = 12, + SAY_SURGE_OF_POWER = 13, + SAY_BUFF_SPARK = 14, + SAY_KILLED_PLAYER_P_THREE = 15, + SAY_SPELL_CASTING_P_THREE = 16, + SAY_DEATH = 17, + EMOTE_SURGE_OF_POWER_WARNING_P3 = 18, + EMOTE_HIT_BERSERKER_TIMER = 19, // Alexstrasza SAY_ONE = 0, @@ -161,252 +226,438 @@ enum Texts SAY_FOUR = 3, // Power Sparks - EMOTE_POWER_SPARK_SUMMONED = 0 + EMOTE_POWER_SPARK_SUMMONED = 0 }; +#define MAX_SUMMONS_PHASE_TWO_10MAN 6 +#define MAX_SUMMONS_PHASE_TWO_25MAN 12 -#define MAX_HOVER_DISK_WAYPOINTS 18 - -// Sniffed data (x, y, z) -const Position HoverDiskWaypoints[MAX_HOVER_DISK_WAYPOINTS] = +#define MAX_RANGE_HOVER_DISK_SPAWNPOINTS 8 +Position const RangeHoverDisksSpawnPositions[MAX_RANGE_HOVER_DISK_SPAWNPOINTS] = { - {782.9821f, 1296.652f, 282.1114f, 0.0f}, - {779.5459f, 1287.228f, 282.1393f, 0.0f}, - {773.0028f, 1279.52f, 282.4164f, 0.0f}, - {764.3626f, 1274.476f, 282.4731f, 0.0f}, - {754.3961f, 1272.639f, 282.4171f, 0.0f}, - {744.4422f, 1274.412f, 282.222f, 0.0f}, - {735.575f, 1279.742f, 281.9674f, 0.0f}, - {729.2788f, 1287.187f, 281.9943f, 0.0f}, - {726.1191f, 1296.688f, 282.2997f, 0.0f}, - {725.9396f, 1306.531f, 282.2448f, 0.0f}, - {729.3045f, 1316.122f, 281.9108f, 0.0f}, - {735.8322f, 1323.633f, 282.1887f, 0.0f}, - {744.4616f, 1328.999f, 281.9948f, 0.0f}, - {754.4739f, 1330.666f, 282.049f, 0.0f}, - {764.074f, 1329.053f, 281.9949f, 0.0f}, - {772.8409f, 1323.951f, 282.077f, 0.0f}, - {779.5085f, 1316.412f, 281.9145f, 0.0f}, - {782.8365f, 1306.778f, 282.3035f, 0.0f}, + { 782.9821f, 1296.652f, 282.1114f, 0.0f }, + { 764.3126f, 1328.871f, 282.3091f, 0.0f }, + { 725.8506f, 1306.749f, 282.2698f, 0.0f }, + { 744.5175f, 1274.396f, 282.3402f, 0.0f }, + { 764.3936f, 1274.371f, 282.6011f, 0.0f }, + { 779.3761f, 1316.166f, 282.1653f, 0.0f }, + { 744.4915f, 1328.901f, 282.2112f, 0.0f }, + { 729.2364f, 1287.328f, 282.4173f, 0.0f } }; -#define GROUND_Z 268 - -// Source: Sniffs (x, y, z) -#define MALYGOS_MAX_WAYPOINTS 16 -const Position MalygosPhaseTwoWaypoints[MALYGOS_MAX_WAYPOINTS] = +#define MAX_MELEE_HOVER_DISK_SPAWNPOINTS 4 +Position const MeleeHoverDisksSpawnPositions[MAX_RANGE_HOVER_DISK_SPAWNPOINTS] = { - {812.7299f, 1391.672f, 283.2763f, 0.0f}, - {848.2912f, 1358.61f, 283.2763f, 0.0f}, - {853.9227f, 1307.911f, 283.2763f, 0.0f}, - {847.1437f, 1265.538f, 283.2763f, 0.0f}, - {839.9229f, 1245.245f, 283.2763f, 0.0f}, - {827.3463f, 1221.818f, 283.2763f, 0.0f}, - {803.2727f, 1203.851f, 283.2763f, 0.0f}, - {772.9372f, 1197.981f, 283.2763f, 0.0f}, - {732.1138f, 1200.647f, 283.2763f, 0.0f}, - {693.8761f, 1217.995f, 283.2763f, 0.0f}, - {664.5038f, 1256.539f, 283.2763f, 0.0f}, - {650.1497f, 1303.485f, 283.2763f, 0.0f}, - {662.9109f, 1350.291f, 283.2763f, 0.0f}, - {677.6391f, 1377.607f, 283.2763f, 0.0f}, - {704.8198f, 1401.162f, 283.2763f, 0.0f}, - {755.2642f, 1417.1f, 283.2763f, 0.0f}, + { 754.4617f, 1283.859f, 285.0522f, 0.0f }, + { 771.7864f, 1301.853f, 285.0522f, 0.0f }, + { 753.9635f, 1319.003f, 285.0522f, 0.0f }, + { 736.4914f, 1301.683f, 285.0522f, 0.0f } }; -#define MAX_SUMMONS_PHASE_TWO 4 - -#define MAX_MALYGOS_POS 2 -const Position MalygosPositions[MAX_MALYGOS_POS] = +#define MAX_MELEE_HOVER_DISK_WAYPOINTS 16 +Position const MeleeHoverDisksWaypoints[MAX_MELEE_HOVER_DISK_WAYPOINTS] = { - {754.544f, 1301.71f, 320.0f, 0.0f}, - {754.39f, 1301.27f, 292.91f, 0.0f}, + // First melee hover disk wps + { 766.2931f, 1312.904f, 277.0551f, 0.0f }, + { 754.3397f, 1319.759f, 274.0536f, 0.0f }, + { 742.1018f, 1312.714f, 270.1367f, 0.0f }, + { 735.6851f, 1301.422f, 266.7208f, 0.0f }, + // Second melee hover disk wps + { 742.6257f, 1313.471f, 275.9713f, 0.0f }, + { 736.8845f, 1301.921f, 274.0264f, 0.0f }, + { 742.6632f, 1289.951f, 269.8603f, 0.0f }, + { 754.3682f, 1283.942f, 266.6098f, 0.0f }, + // Third melee hover disk wps + { 742.2078f, 1290.518f, 276.2484f, 0.0f }, + { 754.5398f, 1284.311f, 273.5815f, 0.0f }, + { 766.5588f, 1290.345f, 269.6655f, 0.0f }, + { 773.4768f, 1301.474f, 266.5821f, 0.0f }, + // Forth melee hover disk wps + { 766.1189f, 1290.197f, 276.9436f, 0.0f }, + { 771.9507f, 1301.602f, 273.9712f, 0.0f }, + { 766.1253f, 1313.451f, 270.4991f, 0.0f }, + { 754.5378f, 1319.399f, 266.6653f, 0.0f } +}; + +#define MAX_MALYGOS_POS 10 +Position const MalygosPositions[MAX_MALYGOS_POS] = +{ + { 754.544f, 1301.71f, 320.01f, 0.0f }, // Point destroy platform + { 754.393f, 1301.27f, 292.91f, 0.0f }, // Point vortex + { 754.362f, 1301.61f, 266.17f, 0.0f }, // Land after vortex + { 754.695f, 1301.66f, 316.65f, 0.0f }, // Point surge of Power phase II + { 755.681f, 1298.41f, 220.06f, 0.0f } // Point idle phase III +}; + +Position const AlexstraszaSpawnPos = { 854.551f, 1225.31f, 300.901f, 0.0f }; // Alexstrasza's spawn position +Position const HeartOfMagicSpawnPos = { 755.351f, 1298.31f, 223.909f, 0.0f }; // Heart of Magic spawn position + +#define TEN_MINUTES (10*MINUTE*IN_MILLISECONDS) + +enum Achievements +{ + ACHIEV_TIMED_START_EVENT = 20387 +}; + +enum AreaIds +{ + AREA_EYE_OF_ETERNITY = 4500 +}; + +enum MiscData +{ + // Lights + LIGHT_GET_DEFAULT_FOR_MAP = 0, + LIGHT_OBSCURE_SPACE = 1822, + LIGHT_CHANGE_DIMENSIONS = 1823, + LIGHT_ARCANE_RUNES = 1824, + LIGHT_OBSCURE_ARCANE_RUNES = 1825, + + // Data (setters/getters) + DATA_SUMMON_DEATHS = 0, // phase 2 + DATA_PHASE = 1, + + // Target guids + DATA_LAST_OVERLOAD_GUID = 13, // used to store last Arcane Overload guid + DATA_FIRST_SURGE_TARGET_GUID = 14, + DATA_SECOND_SURGE_TARGET_GUID = 15, + DATA_THIRD_SURGE_TARGET_GUID = 16 +}; + +// Used to check if summons guids come from vehicles +class VehicleCheckPredicate +{ + public: + bool operator()(uint64 guid) { return IS_VEHICLE_GUID(guid); } }; class boss_malygos : public CreatureScript { public: - boss_malygos() : CreatureScript("boss_malygos") {} - - CreatureAI* GetAI(Creature* creature) const - { - return new boss_malygosAI(creature); - } + boss_malygos() : CreatureScript("boss_malygos") { } struct boss_malygosAI : public BossAI { boss_malygosAI(Creature* creature) : BossAI(creature, DATA_MALYGOS_EVENT) { - // If we enter in combat when MovePoint generator is active, it overrwrites our homeposition - _homePosition = creature->GetHomePosition(); + _despawned = false; // We determine if Malygos will be realocated to spawning position on reset triggered by boss despawn on evade + _flySpeed = me->GetSpeed(MOVE_FLIGHT); // Get initial fly speed, otherwise on each wipe fly speed would add up if we get it } void Reset() { - _Reset(); - - _bersekerTimer = 0; - _currentPos = 0; - - SetPhase(PHASE_ONE, true); - - _delayedMovementTimer = 8000; - _delayedMovement = false; + // EnterEvadeMode and Reset() links are cut for the sake of properly functioning despawner. + if (!_despawned) + _Reset(); _summonDeaths = 0; + _preparingPulsesChecker = 0; + _arcaneOverloadGUID = NULL; + _firstSelectedSurgeTargetGUID = NULL; + _secondSelectedSurgeTargetGUID = NULL; + _thirdSelectedSurgeTargetGUID = NULL; + _killSpamFilter = false; + _canAttack = false; + _executingVortex = false; + _arcaneReinforcements = true; + _flyingOutOfPlatform = false; + _firstCyclicMovementStarted = false; + _performingSurgeOfPower = false; + _performingDestroyPlatform = false; + + me->SetDisableGravity(true); + me->SetByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER); + // TO DO: find what in core is making boss slower than in retail (when correct speed data) or find missing movement flag update or forced spline change + me->SetSpeed(MOVE_FLIGHT, _flySpeed * 0.25f); + if (_despawned) + DoAction(ACTION_HANDLE_RESPAWN); + + SetPhase(PHASE_NOT_STARTED, true); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - - _cannotMove = true; - - me->SetCanFly(true); - + me->SetReactState(REACT_PASSIVE); if (instance) instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); } uint32 GetData(uint32 data) const { - if (data == DATA_SUMMON_DEATHS) - return _summonDeaths; - else if (data == DATA_PHASE) - return _phase; + switch (data) + { + case DATA_SUMMON_DEATHS: + return _summonDeaths; + case DATA_PHASE: + return _phase; + } return 0; } void SetData(uint32 data, uint32 value) { - if (data == DATA_SUMMON_DEATHS && _phase == PHASE_TWO) + if (data == DATA_SUMMON_DEATHS && _phase == PHASE_TWO && !_despawned) { _summonDeaths = value; - if (_summonDeaths >= MAX_SUMMONS_PHASE_TWO) - StartPhaseThree(); + if (GetDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL) + { + if (_summonDeaths == MAX_SUMMONS_PHASE_TWO_10MAN) + { + _performingDestroyPlatform = true; + DoAction(ACTION_HANDLE_P_THREE_INTRO); + } + } + else if (GetDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL) + { + if (_summonDeaths == MAX_SUMMONS_PHASE_TWO_25MAN) + { + _performingDestroyPlatform = true; + DoAction(ACTION_HANDLE_P_THREE_INTRO); + } + } + } + } + + uint64 GetGUID(int32 data) const + { + switch (data) + { + case DATA_FIRST_SURGE_TARGET_GUID: + return _firstSelectedSurgeTargetGUID; + case DATA_SECOND_SURGE_TARGET_GUID: + return _secondSelectedSurgeTargetGUID; + case DATA_THIRD_SURGE_TARGET_GUID: + return _thirdSelectedSurgeTargetGUID; + } + + return 0; + } + + void SetGUID(uint64 guid, int32 type) + { + switch (type) + { + case DATA_LAST_OVERLOAD_GUID: + _arcaneOverloadGUID = guid; + case DATA_FIRST_SURGE_TARGET_GUID: + _firstSelectedSurgeTargetGUID = guid; + case DATA_SECOND_SURGE_TARGET_GUID: + _secondSelectedSurgeTargetGUID = guid; + case DATA_THIRD_SURGE_TARGET_GUID: + _thirdSelectedSurgeTargetGUID = guid; } } - void EnterEvadeMode() + void DoAction(int32 action) { - me->SetHomePosition(_homePosition); - - me->SetDisableGravity(true); - - BossAI::EnterEvadeMode(); - - if (instance) - instance->SetBossState(DATA_MALYGOS_EVENT, FAIL); + switch (action) + { + case ACTION_LAND_ENCOUNTER_START: + events.CancelEventGroup(1); + if (Creature* alexstraszaBunny = me->GetMap()->GetCreature(instance->GetData64(DATA_ALEXSTRASZA_BUNNY_GUID))) + { + Position pos; + pos.m_positionZ = alexstraszaBunny->GetPositionZ(); + alexstraszaBunny->GetNearPoint2D(pos.m_positionX, pos.m_positionY, 30.0f, alexstraszaBunny->GetAngle(me)); + me->GetMotionMaster()->MoveLand(POINT_LAND_P_ONE, pos); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetReactState(REACT_AGGRESSIVE); + me->SetInCombatWithZone(); + events.ScheduleEvent(EVENT_LAND_START_ENCOUNTER, 7*IN_MILLISECONDS, 1, PHASE_NOT_STARTED); + } + break; + case ACTION_EXECUTE_VORTEX: + DoCast(me, SPELL_VORTEX_1, true); + DoCast(me, SPELL_VORTEX_2, true); + // the vortex execution continues in the dummy effect of this spell (see it's script) + DoCast(me, SPELL_VORTEX_3, true); + break; + case ACTION_LIFT_IN_AIR: + Position _zToLift; + me->GetPosition(&_zToLift); + if (_phase == PHASE_ONE) + { + _zToLift.m_positionZ += 20.0f; + me->GetMotionMaster()->MoveTakeoff(POINT_LIFT_IN_AIR_P_ONE, _zToLift); + } + else if (_phase == PHASE_TWO) + { + _zToLift.m_positionZ = 300.1f; + me->GetMotionMaster()->MoveTakeoff(POINT_PHASE_ONE_TO_TWO_TRANSITION, _zToLift); + } + break; + case ACTION_HANDLE_P_THREE_INTRO: + events.CancelEventGroup(0); + events.CancelEventGroup(1); + events.CancelEventGroup(2); + me->GetMotionMaster()->Initialize(); + me->StopMoving(); + // Vehicles shouldn't be despawned with 0 delay if the call comes from virtual function that overrides PassengerBoarded. + // Aside from that he doesn't despawn both vehicles and arcane overloads right away, but with some delay. + DummyEntryCheckPredicate pred; + summons.DoAction(ACTION_DELAYED_DESPAWN, pred); + Talk(SAY_END_P_TWO); + me->GetMotionMaster()->MovePoint(POINT_DESTROY_PLATFORM_P_TWO, MalygosPositions[0]); + events.ScheduleEvent(EVENT_LIGHT_DIMENSION_CHANGE, 1*IN_MILLISECONDS, 0, PHASE_TWO); + break; + case ACTION_HANDLE_RESPAWN: + // Teleport to spawn position, we can't use normal relocate + float x, y, z, o; + me->GetRespawnPosition(x, y, z, &o); + me->NearTeleportTo(x, y, z, o); + // Respawn Iris + instance->SetData(DATA_RESPAWN_IRIS, 0); + _despawned = false; + break; + case ACTION_CYCLIC_MOVEMENT: + Movement::MoveSplineInit init(me); + FillCirclePath(MalygosPositions[3], 130.0f, 283.2763f, init.Path(), true); + init.SetFly(); + init.SetCyclic(); + init.Launch(); + break; + } } void SetPhase(uint8 phase, bool setEvents = false) { events.Reset(); - events.SetPhase(phase); _phase = phase; - if (setEvents) SetPhaseEvents(); } - void StartPhaseThree() - { - if (!instance) - return; - - SetPhase(PHASE_THREE, true); - - // this despawns Hover Disks - summons.DespawnAll(); - // players that used Hover Disk are no in the aggro list - me->SetInCombatWithZone(); - ThreatContainer::StorageType const& m_threatlist = me->getThreatManager().getThreatList(); - for (ThreatContainer::StorageType::const_iterator itr = m_threatlist.begin(); itr!= m_threatlist.end(); ++itr) - { - if (Unit* target = (*itr)->getTarget()) - { - if (target->GetTypeId() != TYPEID_PLAYER) - continue; - - // The rest is handled in the AI of the vehicle. - target->CastSpell(target, SPELL_SUMMOM_RED_DRAGON, true); - me->Attack(target, false); - } - } - - if (GameObject* go = GameObject::GetGameObject(*me, instance->GetData64(DATA_PLATFORM))) - go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_DESTROYED); // In sniffs it has this flag, but i don't know how is applied. - - // pos sniffed - me->GetMotionMaster()->MoveIdle(); - me->GetMotionMaster()->MovePoint(MOVE_CENTER_PLATFORM, MalygosPositions[0].GetPositionX(), MalygosPositions[0].GetPositionY(), MalygosPositions[0].GetPositionZ()); - } - void SetPhaseEvents() { switch (_phase) { + case PHASE_NOT_STARTED: + events.ScheduleEvent(EVENT_SAY_INTRO, 1*IN_MILLISECONDS, 1, _phase); + events.ScheduleEvent(EVENT_START_FIRST_RANDOM_PORTAL, 2*IN_MILLISECONDS, 1, _phase); + break; case PHASE_ONE: events.ScheduleEvent(EVENT_ARCANE_BREATH, urand(15, 20)*IN_MILLISECONDS, 0, _phase); - events.ScheduleEvent(EVENT_ARCANE_STORM, urand(5, 10)*IN_MILLISECONDS, 0, _phase); + events.ScheduleEvent(EVENT_ARCANE_STORM, 10*IN_MILLISECONDS, 0, _phase); events.ScheduleEvent(EVENT_VORTEX, urand(30, 40)*IN_MILLISECONDS, 0, _phase); events.ScheduleEvent(EVENT_POWER_SPARKS, urand(30, 35)*IN_MILLISECONDS, 0, _phase); break; case PHASE_TWO: - events.ScheduleEvent(EVENT_YELL_0, 0, 0, _phase); - events.ScheduleEvent(EVENT_YELL_1, 24*IN_MILLISECONDS, 0, _phase); - events.ScheduleEvent(EVENT_SURGE_POWER, urand(60, 70)*IN_MILLISECONDS, 0, _phase); - events.ScheduleEvent(EVENT_SUMMON_ARCANE, urand(2, 5)*IN_MILLISECONDS, 0, _phase); + events.ScheduleEvent(EVENT_MOVE_TO_POINT_SURGE_P_TWO, 60*IN_MILLISECONDS, 0, _phase); + me->AI()->DoAction(ACTION_LIFT_IN_AIR); break; case PHASE_THREE: - events.ScheduleEvent(EVENT_YELL_2, 0, 0, _phase); - events.ScheduleEvent(EVENT_YELL_3, 8*IN_MILLISECONDS, 0, _phase); - events.ScheduleEvent(EVENT_YELL_4, 16*IN_MILLISECONDS, 0, _phase); - events.ScheduleEvent(EVENT_SURGE_POWER_PHASE_3, urand(7, 16)*IN_MILLISECONDS, 0, _phase); + events.ScheduleEvent(EVENT_ARCANE_PULSE, 13*IN_MILLISECONDS, 0, _phase); + events.ScheduleEvent(EVENT_ARCANE_STORM, 20*IN_MILLISECONDS, 0, _phase); + events.ScheduleEvent(EVENT_SURGE_OF_POWER_P_THREE, urand(7, 16)*IN_MILLISECONDS, 0, _phase); events.ScheduleEvent(EVENT_STATIC_FIELD, urand(20, 30)*IN_MILLISECONDS, 0, _phase); break; - default: - break; } } + // There are moments where boss will do nothing while being attacked + void AttackStart(Unit* target) + { + if (_canAttack) + BossAI::AttackStart(target); + } + void EnterCombat(Unit* /*who*/) { - _EnterCombat(); + // We can't call full function here since it includes DoZoneInCombat(), + // if someone does it will be returned with a warning. + me->setActive(true); + if (instance) + { + if (!instance->CheckRequiredBosses(DATA_MALYGOS_EVENT)) + { + EnterEvadeMode(); + return; + } - me->SetDisableGravity(false); - me->SetCanFly(false); - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - - Talk(SAY_AGGRO_P_ONE); + instance->SetBossState(DATA_MALYGOS_EVENT, IN_PROGRESS); + } + Talk(SAY_START_P_ONE); DoCast(SPELL_BERSEKER); // periodic aura, first tick in 10 minutes - if (instance) instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); } - void KilledUnit(Unit* who) + void EnterEvadeMode() { - if (who->GetTypeId() != TYPEID_PLAYER) - return; + if (instance) + instance->SetBossState(DATA_MALYGOS_EVENT, FAIL); - switch (_phase) + SendLightOverride(LIGHT_GET_DEFAULT_FOR_MAP, 1*IN_MILLISECONDS); + + if (_phase == PHASE_THREE) + me->SetControlled(false, UNIT_STATE_ROOT); + + uint32 corpseDelay = me->GetCorpseDelay(); + uint32 respawnDelay = me->GetRespawnDelay(); + me->SetCorpseDelay(1); + me->SetRespawnDelay(29); + me->DespawnOrUnsummon(); + me->SetCorpseDelay(corpseDelay); + me->SetRespawnDelay(respawnDelay); + + // Set speed to normal value + me->SetSpeed(MOVE_FLIGHT, _flySpeed); + me->RemoveAllAuras(); + me->CombatStop(); // Sometimes threat can remain, so it's a safety measure + + if (!_despawned) + _despawned = true; + + me->ResetLootMode(); + events.Reset(); + if (!summons.empty()) { - case PHASE_ONE: - Talk(SAY_KILLED_PLAYER_P_ONE); - break; - case PHASE_TWO: - Talk(SAY_KILLED_PLAYER_P_TWO); - break; - case PHASE_THREE: - Talk(SAY_KILLED_PLAYER_P_THREE); - break; + if (_phase == PHASE_TWO) + { + VehicleCheckPredicate pred; + summons.DoAction(ACTION_DELAYED_DESPAWN, pred); + summons.remove_if(pred); + summons.DespawnAll(); + } + else if (_phase == PHASE_THREE) + summons.DespawnAll(); + } + + if (instance) + instance->SetBossState(DATA_MALYGOS_EVENT, NOT_STARTED); + } + + void KilledUnit(Unit* victim) + { + if (victim->GetTypeId() != TYPEID_PLAYER) + return; + + if (!_killSpamFilter) + { + switch (_phase) + { + case PHASE_ONE: + Talk(SAY_KILLED_PLAYER_P_ONE); + events.ScheduleEvent(EVENT_PREVENT_SAY_SPAM_ON_KILL, 5*IN_MILLISECONDS, 0, _phase); + _killSpamFilter = true; + break; + case PHASE_TWO: + Talk(SAY_KILLED_PLAYER_P_TWO); + events.ScheduleEvent(EVENT_PREVENT_SAY_SPAM_ON_KILL, 5*IN_MILLISECONDS, 0, _phase); + _killSpamFilter = true; + break; + case PHASE_THREE: + Talk(SAY_KILLED_PLAYER_P_THREE); + events.ScheduleEvent(EVENT_PREVENT_SAY_SPAM_ON_KILL, 5*IN_MILLISECONDS, 0, _phase); + _killSpamFilter = true; + break; + } } } - void SpellHit(Unit* caster, const SpellInfo* spell) + void SpellHit(Unit* caster, SpellInfo const* spell) { if (spell->Id == SPELL_POWER_SPARK_MALYGOS) { @@ -415,38 +666,600 @@ public: Talk(SAY_BUFF_SPARK); } + else if (spell->Id == SPELL_MALYGOS_BERSERK) + sCreatureTextMgr->SendChat(me, EMOTE_HIT_BERSERKER_TIMER, 0, CHAT_MSG_ADDON, LANG_ADDON, TEXT_RANGE_MAP); } void MoveInLineOfSight(Unit* who) { - if (!me->isInCombat()) + if (!me->isInCombat() || _phase != PHASE_ONE) return; if (who->GetEntry() == NPC_POWER_SPARK) - { - // not sure about the distance | I think it is better check this here than in the UpdateAI function... if (who->GetDistance(me) <= 2.5f) who->CastSpell(me, SPELL_POWER_SPARK_MALYGOS, true); + } + + void MovementInform(uint32 type, uint32 id) + { + if (type != POINT_MOTION_TYPE && type != EFFECT_MOTION_TYPE) + return; + + switch (id) + { + case POINT_NEAR_RANDOM_PORTAL_P_NONE: + if (Creature* portal = me->FindNearestCreature(NPC_PORTAL_TRIGGER, 31.0f, true)) + { + events.ScheduleEvent(EVENT_STOP_PORTAL_BEAM, 10*IN_MILLISECONDS, 1, PHASE_NOT_STARTED); + events.ScheduleEvent(EVENT_RANDOM_PORTAL, 14*IN_MILLISECONDS, 1, PHASE_NOT_STARTED); + DoCast(portal, SPELL_PORTAL_BEAM); + } + break; + case POINT_LAND_P_ONE: + me->SetDisableGravity(false); + break; + case POINT_VORTEX_P_ONE: + me->GetMotionMaster()->MoveIdle(); + DoAction(ACTION_EXECUTE_VORTEX); + break; + case POINT_LAND_AFTER_VORTEX_P_ONE: + me->SetDisableGravity(false); + _executingVortex = false; + _canAttack = true; + break; + case POINT_LIFT_IN_AIR_P_ONE: + me->SetDisableGravity(true); + events.ScheduleEvent(EVENT_MOVE_TO_VORTEX_POINT, 1, 0, PHASE_ONE); + break; + case POINT_FLY_OUT_OF_PLATFORM_P_TWO: + if (!_firstCyclicMovementStarted) + { + _firstCyclicMovementStarted = true; + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetFacingToObject(me->GetMap()->GetCreature(instance->GetData64(DATA_ALEXSTRASZA_BUNNY_GUID))); + events.ScheduleEvent(EVENT_SUMMON_ARCANE_BOMB, 1*IN_MILLISECONDS, 0, PHASE_TWO); + } + _flyingOutOfPlatform = false; + _performingSurgeOfPower = false; + events.ScheduleEvent(EVENT_PATHING_AROUND_PLATFORM, 1*IN_MILLISECONDS, 0, PHASE_TWO); + break; + case POINT_PHASE_ONE_TO_TWO_TRANSITION: + me->SetDisableGravity(true); + me->SetFacingToObject(me->GetMap()->GetCreature(instance->GetData64(DATA_ALEXSTRASZA_BUNNY_GUID))); + SendLightOverride(LIGHT_ARCANE_RUNES, 5*IN_MILLISECONDS); + events.ScheduleEvent(EVENT_FLY_OUT_OF_PLATFORM, 18*IN_MILLISECONDS, 0, PHASE_TWO); + break; + case POINT_SURGE_OF_POWER_P_TWO: + if (!_performingDestroyPlatform) + { + Talk(EMOTE_SURGE_OF_POWER_WARNING_P2); + DoCastAOE(SPELL_SURGE_OF_POWER_P_II, true); + events.ScheduleEvent(EVENT_FLY_OUT_OF_PLATFORM, 7*IN_MILLISECONDS, 0, PHASE_TWO); + } + break; + case POINT_DESTROY_PLATFORM_P_TWO: + SendLightOverride(LIGHT_OBSCURE_SPACE, 1*IN_MILLISECONDS); + DoCast(me, SPELL_DESTROY_PLATFORM_CHANNEL); + events.ScheduleEvent(EVENT_MOVE_TO_P_THREE_POINT, 11*IN_MILLISECONDS, 0, PHASE_TWO); + break; + case POINT_IDLE_P_THREE: + me->SetControlled(true, UNIT_STATE_ROOT); + events.ScheduleEvent(EVENT_START_P_THREE, 5*IN_MILLISECONDS, 0, PHASE_TWO); + break; } } - void PrepareForVortex() + void UpdateAI(uint32 diff) { - me->SetDisableGravity(true); - me->SetCanFly(true); + if (!UpdateVictim() && _phase != PHASE_NOT_STARTED && _phase != PHASE_TWO) + return; - me->GetMotionMaster()->MovementExpired(); - me->GetMotionMaster()->MovePoint(MOVE_VORTEX, MalygosPositions[1].GetPositionX(), MalygosPositions[1].GetPositionY(), MalygosPositions[1].GetPositionZ()); - // continues in MovementInform function. + events.Update(diff); + + // we can't cast if we are casting already unless in PHASE_NOT_STARTED channeling PORTAL_BEAM + if (me->HasUnitState(UNIT_STATE_CASTING) && _phase != PHASE_NOT_STARTED) + return; + + // at 50% hp Malygos switchs to phase 2 and removes hovering until reset or end of encounter + if (_phase == PHASE_ONE && me->GetHealthPct() <= 50.0f) + { + SetPhase(PHASE_TWO, true); + _canAttack = false; + me->AttackStop(); + Talk(SAY_END_P_ONE); + } + + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_START_FIRST_RANDOM_PORTAL: + me->CastCustomSpell(SPELL_RANDOM_PORTAL, SPELLVALUE_MAX_TARGETS, 1); + break; + case EVENT_STOP_PORTAL_BEAM: + me->InterruptNonMeleeSpells(true); + break; + case EVENT_RANDOM_PORTAL: + me->CastCustomSpell(SPELL_RANDOM_PORTAL, SPELLVALUE_MAX_TARGETS, 1); + break; + case EVENT_LAND_START_ENCOUNTER: + if (GameObject* iris = me->GetMap()->GetGameObject(instance->GetData64(DATA_FOCUSING_IRIS_GUID))) + { + me->SetFacingToObject(iris); + iris->Delete(); // this is not the best way. + } + _canAttack = true; + SetPhase(PHASE_ONE, true); + break; + case EVENT_SAY_INTRO: + Talk(SAY_INTRO_EVENT); + events.ScheduleEvent(EVENT_SAY_INTRO, urand(85, 95)*IN_MILLISECONDS, 1, PHASE_NOT_STARTED); + break; + case EVENT_VORTEX: + _executingVortex = true; + DoAction(ACTION_LIFT_IN_AIR); + events.ScheduleEvent(EVENT_VORTEX, urand(60, 80)*IN_MILLISECONDS, 0, PHASE_ONE); + break; + case EVENT_MOVE_TO_VORTEX_POINT: + _canAttack = false; + me->AttackStop(); + me->GetMotionMaster()->MovePoint(POINT_VORTEX_P_ONE, MalygosPositions[1]); + break; + case EVENT_POWER_SPARKS: + instance->SetData(DATA_POWER_SPARKS_HANDLING, 0); + events.ScheduleEvent(EVENT_POWER_SPARKS, urand(30, 35)*IN_MILLISECONDS, 0, PHASE_ONE); + break; + case EVENT_ARCANE_BREATH: + if (_executingVortex) + { + events.ScheduleEvent(EVENT_ARCANE_BREATH, 20*IN_MILLISECONDS, 0, PHASE_ONE); + break; + } + + me->CastSpell(me->getVictim(), SPELL_ARCANE_BREATH); + events.ScheduleEvent(EVENT_ARCANE_BREATH, 20*IN_MILLISECONDS, 0, PHASE_ONE); + break; + case EVENT_ARCANE_STORM: + if (_phase == PHASE_ONE) + { + if (_executingVortex) + { + events.ScheduleEvent(EVENT_ARCANE_STORM, 10*IN_MILLISECONDS, 0, PHASE_ONE); + break; + } + + DoCast(me, SPELL_ARCANE_STORM_P_I, true); + events.ScheduleEvent(EVENT_ARCANE_STORM, 10*IN_MILLISECONDS, 0, PHASE_ONE); + } + else if (_phase == PHASE_THREE) + { + DoCast(me, SPELL_ARCANE_STORM_P_III, true); + events.ScheduleEvent(EVENT_ARCANE_STORM, urand(6, 12)*IN_MILLISECONDS, 0, PHASE_THREE); + } + break; + case EVENT_FLY_OUT_OF_PLATFORM: + if (Creature* alexstraszaBunny = me->GetMap()->GetCreature(instance->GetData64(DATA_ALEXSTRASZA_BUNNY_GUID))) + { + Position randomPosOnRadius; + // Hardcodded retail value, reason is Z getters can fail... (TO DO: Change to getter when height calculation works on 100%!) + randomPosOnRadius.m_positionZ = 283.0521f; + alexstraszaBunny->GetNearPoint2D(randomPosOnRadius.m_positionX, randomPosOnRadius.m_positionY, 130.0f, alexstraszaBunny->GetAngle(me)); + me->GetMotionMaster()->MovePoint(POINT_FLY_OUT_OF_PLATFORM_P_TWO, randomPosOnRadius); + _flyingOutOfPlatform = true; + } + + if (_arcaneReinforcements && instance) + { + for (uint8 rangeDisks = 0; rangeDisks < (GetDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL ? 4 : 5); rangeDisks++) + { + Creature* casterDiskSummon = me->SummonCreature(NPC_HOVER_DISK_CASTER, RangeHoverDisksSpawnPositions[rangeDisks]); + + if (casterDiskSummon->IsAIEnabled) + casterDiskSummon->AI()->DoAction(rangeDisks); + } + + for (uint8 meleeDisks = 0; meleeDisks < 2; meleeDisks++) + { + Creature* meleeDiskSummon = me->SummonCreature(NPC_HOVER_DISK_MELEE, MeleeHoverDisksSpawnPositions[meleeDisks]); + meleeDiskSummon->GetMotionMaster()->MovePoint(meleeDisks * MAX_MELEE_HOVER_DISK_SPAWNPOINTS, MeleeHoverDisksWaypoints[meleeDisks * MAX_MELEE_HOVER_DISK_SPAWNPOINTS]); + } + + _arcaneReinforcements = false; + + if (GetDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL) + events.ScheduleEvent(EVENT_DELAYED_REINFORCEMENTS, 1*IN_MILLISECONDS, 0, PHASE_TWO); + } + break; + case EVENT_DELAYED_REINFORCEMENTS: + for (uint8 rangeDisks = 5; rangeDisks < 8; rangeDisks++) + { + Creature* casterDiskSummon = me->SummonCreature(NPC_HOVER_DISK_CASTER, RangeHoverDisksSpawnPositions[rangeDisks]); + + if (casterDiskSummon->IsAIEnabled) + casterDiskSummon->AI()->DoAction(rangeDisks); + } + + for (uint8 meleeDisks = 2; meleeDisks < 4; meleeDisks++) + { + Creature* meleeDiskSummon = me->SummonCreature(NPC_HOVER_DISK_MELEE, MeleeHoverDisksSpawnPositions[meleeDisks]); + meleeDiskSummon->GetMotionMaster()->MovePoint(meleeDisks * MAX_MELEE_HOVER_DISK_SPAWNPOINTS, MeleeHoverDisksWaypoints[meleeDisks * MAX_MELEE_HOVER_DISK_SPAWNPOINTS]); + } + break; + case EVENT_PATHING_AROUND_PLATFORM: + DoAction(ACTION_CYCLIC_MOVEMENT); + break; + case EVENT_MOVE_TO_POINT_SURGE_P_TWO: + if (!_performingDestroyPlatform) + { + _performingSurgeOfPower = true; + Talk(SAY_DEEP_BREATH); + me->GetMotionMaster()->MovePoint(POINT_SURGE_OF_POWER_P_TWO, MalygosPositions[3]); + events.ScheduleEvent(EVENT_MOVE_TO_POINT_SURGE_P_TWO, 60*IN_MILLISECONDS, 2, PHASE_TWO); + } + break; + case EVENT_SUMMON_ARCANE_BOMB: + if (!_performingSurgeOfPower && !_performingDestroyPlatform) + { + me->StopMoving(); + events.ScheduleEvent(EVENT_PATHING_AROUND_PLATFORM, 3*IN_MILLISECONDS, 0, PHASE_TWO); + } + + if (!_flyingOutOfPlatform) + { + DoCast(me, SPELL_SUMMON_ARCANE_BOMB, true); + if (Creature* lastArcaneOverloadBunny = me->GetMap()->GetCreature(_arcaneOverloadGUID)) + DoCast(lastArcaneOverloadBunny, SPELL_ARCANE_BOMB_TRIGGER, true); + } + events.ScheduleEvent(EVENT_SUMMON_ARCANE_BOMB, urand(15, 16)*IN_MILLISECONDS, 2, PHASE_TWO); + break; + case EVENT_ARCANE_PULSE: + if (_preparingPulsesChecker < 2) + { + DoCastAOE(SPELL_ARCANE_PULSE, true); + events.ScheduleEvent(EVENT_ARCANE_PULSE, 7*IN_MILLISECONDS, 0, PHASE_THREE); + _preparingPulsesChecker++; + } + else + { + DoCastAOE(SPELL_ARCANE_PULSE, true); + events.ScheduleEvent(EVENT_ARCANE_PULSE, 2*IN_MILLISECONDS, 0, PHASE_THREE); + } + break; + case EVENT_LIGHT_DIMENSION_CHANGE: + SendLightOverride(LIGHT_CHANGE_DIMENSIONS, 2*IN_MILLISECONDS); + break; + case EVENT_MOVE_TO_P_THREE_POINT: + Talk(SAY_START_P_THREE); + me->GetMotionMaster()->MovePoint(POINT_IDLE_P_THREE, MalygosPositions[4]); + break; + case EVENT_START_P_THREE: + SendLightOverride(LIGHT_OBSCURE_ARCANE_RUNES, 1*IN_MILLISECONDS); + DoCast(me, SPELL_CLEAR_ALL_DEBUFFS); + DoCast(me, SPELL_IMMUNE_CURSES); + _canAttack = true; + UpdateVictim(); + me->SetFacingToObject(me->getVictim()); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + SetPhase(PHASE_THREE, true); + break; + case EVENT_SURGE_OF_POWER_P_THREE: + if (GetDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL) + { + _tempSurgeTarget = NULL; + _drakeVehicle = NULL; + _playerSurgeTarget = NULL; + if ((_tempSurgeTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, false, SPELL_RIDE_RED_DRAGON_BUDDY))) + if ((_drakeVehicle = _tempSurgeTarget->GetVehicleKit())) + if ((_playerSurgeTarget = _drakeVehicle->GetPassenger(0)->ToPlayer())) + { + Talk(EMOTE_SURGE_OF_POWER_WARNING_P3, _playerSurgeTarget->GetGUID()); + DoCast(_tempSurgeTarget, SPELL_SURGE_OF_POWER_PHASE_3_10); + } + } + else if (GetDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL) + { + _firstSelectedSurgeTargetGUID = NULL; + _secondSelectedSurgeTargetGUID = NULL; + _thirdSelectedSurgeTargetGUID = NULL; + DoCastAOE(SPELL_SURGE_OF_POWER_WARNING_SELECTOR_25); + } + + events.ScheduleEvent(EVENT_SURGE_OF_POWER_P_THREE, urand(9, 18)*IN_MILLISECONDS, 0, PHASE_THREE); + break; + case EVENT_STATIC_FIELD: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 60.0f, false, SPELL_RIDE_RED_DRAGON_BUDDY)) + DoCast(target, SPELL_STATIC_FIELD_MISSLE); + + events.ScheduleEvent(EVENT_STATIC_FIELD, urand(15, 30)*IN_MILLISECONDS, 0, PHASE_THREE); + break; + case EVENT_PREVENT_SAY_SPAM_ON_KILL: + _killSpamFilter = false; + break; + default: + break; + } + } + + if (_phase != PHASE_THREE) + DoMeleeAttackIfReady(); } - void ExecuteVortex() + void JustDied(Unit* /*killer*/) { - DoCast(me, SPELL_VORTEX_1, true); - DoCast(me, SPELL_VORTEX_2, true); + _JustDied(); + Talk(SAY_DEATH); + if (Creature* alexstraszaGiftBoxBunny = me->GetMap()->GetCreature(instance->GetData64(DATA_GIFT_BOX_BUNNY_GUID))) + { + if (GetDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL) + alexstraszaGiftBoxBunny->SummonGameObject(GO_HEART_OF_MAGIC_10, HeartOfMagicSpawnPos.GetPositionX(), HeartOfMagicSpawnPos.GetPositionY(), + HeartOfMagicSpawnPos.GetPositionZ(), HeartOfMagicSpawnPos.GetOrientation(), 0.0f, 0.0f, 0.0f, 1.0f, 0); + else if (GetDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL) + alexstraszaGiftBoxBunny->SummonGameObject(GO_HEART_OF_MAGIC_25, HeartOfMagicSpawnPos.GetPositionX(), HeartOfMagicSpawnPos.GetPositionY(), + HeartOfMagicSpawnPos.GetPositionZ(), HeartOfMagicSpawnPos.GetOrientation(), 0.0f, 0.0f, 0.0f, 1.0f, 0); + } - // the vortex execution continues in the dummy effect of this spell (see its script) - DoCast(me, SPELL_VORTEX_3, true); + me->SummonCreature(NPC_ALEXSTRASZA, AlexstraszaSpawnPos, TEMPSUMMON_MANUAL_DESPAWN); + me->DespawnOrUnsummon(5*IN_MILLISECONDS); + } + + private: + // Used to generate perfect cyclic movements (Enter Circle). + void FillCirclePath(Position const& centerPos, float radius, float z, Movement::PointsArray& path, bool clockwise) + { + float step = clockwise ? -M_PI / 8.0f : M_PI / 8.0f; + float angle = centerPos.GetAngle(me->GetPositionX(), me->GetPositionY()); + + for (uint8 i = 0; i < 16; angle += step, ++i) + { + G3D::Vector3 point; + point.x = centerPos.GetPositionX() + radius * cosf(angle); + point.y = centerPos.GetPositionY() + radius * sinf(angle); + point.z = z; // Don't use any height getters unless all bugs are fixed. + path.push_back(point); + } + } + + // Function that will change lights of map for all players on map. + void SendLightOverride(uint32 overrideId, uint32 fadeInTime) const + { + WorldPacket data(SMSG_OVERRIDE_LIGHT, 12); + data << uint32(1773); // Light.dbc entry (map default) + data << uint32(overrideId); // Light.dbc entry (override) + data << uint32(fadeInTime); + SendPacketToPlayers(&data); + } + + // Send packet to all players in Eye of Eternity + void SendPacketToPlayers(WorldPacket const* data) const + { + Map::PlayerList const& players = me->GetMap()->GetPlayers(); + if (!players.isEmpty()) + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + if (Player* player = itr->getSource()) + if (player->GetAreaId() == AREA_EYE_OF_ETERNITY) + player->GetSession()->SendPacket(data); + } + + uint8 _phase; // Counter for phases used with a getter. + uint8 _summonDeaths; // Keeps count of arcane trash. + uint8 _preparingPulsesChecker; // In retail they use 2 preparing pulses with 7 sec CD, after they pass 2 seconds. + uint64 _arcaneOverloadGUID; // Last Arcane Overload summoned to know to which should visual be cast to (the purple ball, not bubble). + uint64 _firstSelectedSurgeTargetGUID; // All these three are used to keep current tagets to which warning should be sent + uint64 _secondSelectedSurgeTargetGUID; // during Surge of Power 25 man, also they act as sent targets because of that mechanic. + uint64 _thirdSelectedSurgeTargetGUID; + + Unit* _tempSurgeTarget; // These three are used for 10 man Surge of Power targeting. + Vehicle* _drakeVehicle; + Player* _playerSurgeTarget; + + bool _killSpamFilter; // Prevent text spamming on killed player by helping implement a CD. + bool _canAttack; // Used to control attacking (Move Chase not being applied after Stop Attack, only few times should act like this). + bool _despawned; // Checks if boss pass through evade on reset. + bool _executingVortex; // Prevents some events being sheduled during Vortex takeoff/land. + bool _arcaneReinforcements; // Checks if 10 or 25 man arcane trash will be spawned. + bool _flyingOutOfPlatform; // Used to prevent Malygos casting Arcane Overload shields while leaving platform. + bool _firstCyclicMovementStarted; // At first movement start he throws one shield asap, so this check is needed for it only. + bool _performingSurgeOfPower; // Used to prevent starting Cyclic Movement called in Arcane Bomb event. + bool _performingDestroyPlatform; // Used to prevent starting some movements right when Destroy Platfrom event starts. + + float _flySpeed; // Used to store base fly speed to prevent stacking on each evade. + }; + + CreatureAI* GetAI(Creature* creature) const + { + return new boss_malygosAI(creature); + } +}; + +class npc_portal_eoe: public CreatureScript +{ +public: + npc_portal_eoe() : CreatureScript("npc_portal_eoe") { } + + struct npc_portal_eoeAI : public ScriptedAI + { + npc_portal_eoeAI(Creature* creature) : ScriptedAI(creature) + { + _instance = creature->GetInstanceScript(); + } + + void SpellHit(Unit* /*caster*/, SpellInfo const* spell) + { + if (spell->Id == SPELL_PORTAL_OPENED) + { + if (Creature* malygos = me->GetMap()->GetCreature(_instance->GetData64(DATA_MALYGOS))) + { + if (malygos->AI()->GetData(DATA_PHASE) == PHASE_ONE) + DoCast(me, SPELL_SUMMON_POWER_PARK, true); + } + } + } + + void UpdateAI(uint32 /*diff*/) + { + // When duration of opened riff visual ends, closed one should be cast + if (!me->HasAura(SPELL_PORTAL_VISUAL_CLOSED) && !me->HasAura(SPELL_PORTAL_OPENED)) + DoCast(me, SPELL_PORTAL_VISUAL_CLOSED, true); + + if (_instance) + { + if (Creature* malygos = me->GetMap()->GetCreature(_instance->GetData64(DATA_MALYGOS))) + { + if (malygos->AI()->GetData(DATA_PHASE) != PHASE_ONE && me->HasAura(SPELL_PORTAL_OPENED)) + { + me->RemoveAura(SPELL_PORTAL_OPENED); + DoCast(me, SPELL_PORTAL_VISUAL_CLOSED, true); + } + } + } + } + + private: + InstanceScript* _instance; + }; + + CreatureAI* GetAI(Creature* creature) const + { + return new npc_portal_eoeAI(creature); + } +}; + +class npc_power_spark: public CreatureScript +{ +public: + npc_power_spark() : CreatureScript("npc_power_spark") { } + + struct npc_power_sparkAI : public ScriptedAI + { + npc_power_sparkAI(Creature* creature) : ScriptedAI(creature) + { + _instance = creature->GetInstanceScript(); + // Talk range was not enough for this encounter + sCreatureTextMgr->SendChat(me, EMOTE_POWER_SPARK_SUMMONED, 0, CHAT_MSG_ADDON, LANG_ADDON, TEXT_RANGE_MAP); + MoveToMalygos(); + } + + void MoveToMalygos() + { + me->GetMotionMaster()->MoveIdle(); + + if (_instance) + if (Creature* malygos = me->GetMap()->GetCreature(_instance->GetData64(DATA_MALYGOS))) + me->GetMotionMaster()->MoveFollow(malygos, 0.0f, 0.0f); + } + + void UpdateAI(uint32 /*diff*/) + { + if (!_instance) + return; + + if (Creature* malygos = me->GetMap()->GetCreature(_instance->GetData64(DATA_MALYGOS))) + { + if (malygos->AI()->GetData(DATA_PHASE) != PHASE_ONE || _instance->GetBossState(DATA_MALYGOS_EVENT) == FAIL) + { + me->DespawnOrUnsummon(); + return; + } + + if (malygos->HasAura(SPELL_VORTEX_1)) + { + me->GetMotionMaster()->MoveIdle(); + return; + } + + if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() != CHASE_MOTION_TYPE) + me->GetMotionMaster()->MoveFollow(malygos, 0.0f, 0.0f); + } + } + + void JustDied(Unit* /*killer*/) + { + me->CastSpell(me, SPELL_POWER_SPARK_DEATH, true); // not supposed to hide the fact it's there by not selectable + } + + private: + InstanceScript* _instance; + }; + + CreatureAI* GetAI(Creature* creature) const + { + return new npc_power_sparkAI(creature); + } +}; + +class npc_melee_hover_disk : public CreatureScript +{ +public: + npc_melee_hover_disk() : CreatureScript("npc_melee_hover_disk") { } + + struct npc_melee_hover_diskAI : public VehicleAI + { + npc_melee_hover_diskAI(Creature* creature) : VehicleAI(creature) + { + _instance = creature->GetInstanceScript(); + me->SetReactState(REACT_PASSIVE); + // TO DO: These were a bit faster than what they should be. Not sure what is the reason. + me->SetSpeed(MOVE_FLIGHT, 1.25f); + } + + void Reset() + { + VehicleAI::Reset(); + + _wpCount = 0; + } + + void PassengerBoarded(Unit* unit, int8 /*seat*/, bool apply) + { + if (apply) + { + if (unit->GetTypeId() == TYPEID_UNIT) + { + unit->CastSpell(unit, SPELL_TELEPORT_VISUAL_ONLY); + unit->ToCreature()->SetInCombatWithZone(); + } + else if (unit->GetTypeId() == TYPEID_PLAYER) + me->SetDisableGravity(true); + } + else if (!apply) + { + if (unit->GetTypeId() != TYPEID_PLAYER) + { + + me->SetHomePosition(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation()); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetDisableGravity(false); + me->SetCanFly(false); + } + else if (unit->GetTypeId() == TYPEID_PLAYER) + { + me->SetDisableGravity(false); + me->SetCanFly(false); + } + + me->setFaction(FACTION_FRIENDLY); + me->RemoveAllAuras(); + } + } + + void UpdateAI(uint32 diff) + { + _events.Update(diff); + + while (uint32 eventId = _events.ExecuteEvent()) + me->GetMotionMaster()->MovePoint(eventId, MeleeHoverDisksWaypoints[eventId]); + } + + void DoAction(int32 /*action*/) + { + if (Vehicle* vehicleTemp = me->GetVehicleKit()) + if (vehicleTemp->GetPassenger(0) && vehicleTemp->GetPassenger(0)->GetTypeId() == TYPEID_PLAYER) + { + vehicleTemp->RemoveAllPassengers(); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + + me->DespawnOrUnsummon(3*IN_MILLISECONDS); } void MovementInform(uint32 type, uint32 id) @@ -454,220 +1267,561 @@ public: if (type != POINT_MOTION_TYPE) return; - switch (id) + if (_wpCount < 3) { - case MOVE_VORTEX: - me->GetMotionMaster()->MoveIdle(); - ExecuteVortex(); - break; - case MOVE_DEEP_BREATH_ROTATION: - _currentPos = _currentPos == MALYGOS_MAX_WAYPOINTS - 1 ? 0 : _currentPos+1; - me->GetMotionMaster()->MovementExpired(); - me->GetMotionMaster()->MovePoint(MOVE_DEEP_BREATH_ROTATION, MalygosPhaseTwoWaypoints[_currentPos]); - break; - case MOVE_INIT_PHASE_ONE: - me->SetInCombatWithZone(); - break; - case MOVE_CENTER_PLATFORM: - // Malygos is already flying here, there is no need to set it again. - _cannotMove = false; - // malygos will move into center of platform and then he does not chase dragons, he just turns to his current target. - me->GetMotionMaster()->MoveIdle(); - break; + _events.ScheduleEvent(id + 1, 1); + ++_wpCount; + } + else if (Vehicle* hoverDisk = me->GetVehicleKit()) + if (Unit* lordPassenger = hoverDisk->GetPassenger(0)) + lordPassenger->ToCreature()->AI()->DoAction(ACTION_SET_DISK_VICTIM_CHASE); + } + + private: + uint8 _wpCount; // how many points are triggered + InstanceScript* _instance; + EventMap _events; + }; + + CreatureAI* GetAI(Creature* creature) const + { + return new npc_melee_hover_diskAI(creature); + } +}; + +class npc_caster_hover_disk : public CreatureScript +{ +public: + npc_caster_hover_disk() : CreatureScript("npc_caster_hover_disk") { } + + struct npc_caster_hover_diskAI : public VehicleAI + { + npc_caster_hover_diskAI(Creature* creature) : VehicleAI(creature) + { + _instance = creature->GetInstanceScript(); + me->SetReactState(REACT_PASSIVE); + // TO DO: Something is wrong with calculations for flying creatures that are on WP/Cyclic path. + // They should get the same difference as to when at ground from run creature switch to walk. + me->SetSpeed(MOVE_FLIGHT, 0.45f); + } + + void Reset() + { + VehicleAI::Reset(); + } + + void EnterEvadeMode() + { + } + + void PassengerBoarded(Unit* unit, int8 /*seat*/, bool apply) + { + if (apply) + { + if (unit->GetTypeId() == TYPEID_UNIT) + unit->CastSpell(unit, SPELL_TELEPORT_VISUAL_ONLY); + } + else if (!apply) + { + me->StopMoving(); + me->SetDisableGravity(false); + me->SetCanFly(false); + me->RemoveAllAuras(); } } - void StartPhaseTwo() + void DoAction(int32 action) { - SetPhase(PHASE_TWO, true); - - me->SetDisableGravity(true); - me->SetCanFly(true); - - me->GetMotionMaster()->MoveIdle(); - me->GetMotionMaster()->MovePoint(MOVE_DEEP_BREATH_ROTATION, MalygosPhaseTwoWaypoints[0]); - - for (uint8 i = 0; i < 2; i++) + if (action < ACTION_DELAYED_DESPAWN) { - // Starting position. One starts from the first waypoint and another from the last. - uint8 pos = !i ? MAX_HOVER_DISK_WAYPOINTS-1 : 0; - if (Creature* summon = me->SummonCreature(NPC_HOVER_DISK_CASTER, HoverDiskWaypoints[pos])) - if (summon->IsAIEnabled) - summon->AI()->DoAction(ACTION_HOVER_DISK_START_WP_1+i); - - // not sure about its position. - if (Creature* summon = me->SummonCreature(NPC_HOVER_DISK_MELEE, HoverDiskWaypoints[0])) - summon->SetInCombatWithZone(); + Movement::MoveSplineInit init(me); + FillCirclePath(MalygosPositions[3], 35.0f, 282.3402f, init.Path(), true); + init.SetFly(); + init.SetCyclic(); + init.Launch(); + } + else + { + me->DespawnOrUnsummon(3*IN_MILLISECONDS); } } - void UpdateAI(uint32 diff) + private: + void FillCirclePath(Position const& centerPos, float radius, float z, Movement::PointsArray& path, bool clockwise) { - if (!UpdateVictim()) - return; + float step = clockwise ? -M_PI / 9.0f : M_PI / 9.0f; + float angle = centerPos.GetAngle(me->GetPositionX(), me->GetPositionY()); - events.Update(diff); - - if (_phase == PHASE_THREE) + for (uint8 i = 0; i < 18; angle += step, ++i) { - if (!_cannotMove) + G3D::Vector3 point; + point.x = centerPos.GetPositionX() + radius * cosf(angle); + point.y = centerPos.GetPositionY() + radius * sinf(angle); + point.z = z; // Don't use any height getters unless all bugs are fixed. + path.push_back(point); + } + } + + InstanceScript* _instance; + }; + + CreatureAI* GetAI(Creature* creature) const + { + return new npc_caster_hover_diskAI(creature); + } +}; + +class npc_nexus_lord : public CreatureScript +{ + public: + npc_nexus_lord() : CreatureScript("npc_nexus_lord") { } + + struct npc_nexus_lordAI : public ScriptedAI + { + npc_nexus_lordAI(Creature* creature) : ScriptedAI(creature) + { + _instance = creature->GetInstanceScript(); + } + + void Reset() + { + _events.Reset(); + } + + void EnterEvadeMode() + { + } + + void IsSummonedBy(Unit* /*summoner*/) + { + _events.ScheduleEvent(EVENT_ARCANE_SHOCK, 2*IN_MILLISECONDS); + _events.ScheduleEvent(EVENT_HASTE_BUFF, 12*IN_MILLISECONDS); + } + + void DoAction(int32 /*action*/) + { + _events.ScheduleEvent(EVENT_NUKE_DUMMY, 1); + } + + void UpdateAI(uint32 diff) + { + if (!UpdateVictim()) + return; + + _events.Update(diff); + + while (uint32 eventId = _events.ExecuteEvent()) { - // it can change if the player falls from the vehicle. - if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() != IDLE_MOTION_TYPE) + switch (eventId) { - me->GetMotionMaster()->MovementExpired(); - me->GetMotionMaster()->MoveIdle(); + case EVENT_ARCANE_SHOCK: + DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0, 5.0f, true), SPELL_ARCANE_SHOCK); + _events.ScheduleEvent(EVENT_ARCANE_SHOCK, 3*IN_MILLISECONDS); + break; + case EVENT_HASTE_BUFF: + DoCast(me, SPELL_HASTE); + _events.ScheduleEvent(EVENT_HASTE_BUFF, 15*IN_MILLISECONDS); + break; + case EVENT_NUKE_DUMMY: + DoCast(me->getVictim(), SPELL_DUMMY_NUKE, true); + DoCast(me, SPELL_ALIGN_DISK_AGGRO, true); + _events.ScheduleEvent(EVENT_NUKE_DUMMY, 1*IN_MILLISECONDS); + break; } - } else + } + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*killer*/) + { + if (Creature* malygos = me->GetMap()->GetCreature(_instance->GetData64(DATA_MALYGOS))) + malygos->AI()->SetData(DATA_SUMMON_DEATHS, malygos->AI()->GetData(DATA_SUMMON_DEATHS) + 1); + } + + private: + InstanceScript* _instance; + EventMap _events; + }; + + CreatureAI* GetAI(Creature* creature) const + { + return new npc_nexus_lordAI(creature); + } +}; + +class npc_scion_of_eternity : public CreatureScript +{ + public: + npc_scion_of_eternity() : CreatureScript("npc_scion_of_eternity") { } + + struct npc_scion_of_eternityAI : public ScriptedAI + { + npc_scion_of_eternityAI(Creature* creature) : ScriptedAI(creature) + { + _instance = creature->GetInstanceScript(); + } + + void Reset() + { + _events.Reset(); + } + + void IsSummonedBy(Unit* /*summoner*/) + { + _events.SetPhase(PHASE_TWO); + _events.ScheduleEvent(EVENT_ARCANE_BARRAGE, urand(14, 17)*IN_MILLISECONDS, 0, PHASE_TWO); + } + + void EnterCombat(Unit* /*who*/) + { + } + + void AttackStart(Unit* /*target*/) + { + } + + void EnterEvadeMode() + { + } + + void UpdateAI(uint32 diff) + { + _events.Update(diff); + + while (uint32 eventId = _events.ExecuteEvent()) { - if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() != POINT_MOTION_TYPE) + switch (eventId) { - me->GetMotionMaster()->MovementExpired(); - me->GetMotionMaster()->MovePoint(MOVE_CENTER_PLATFORM, MalygosPositions[0].GetPositionX(), MalygosPositions[0].GetPositionY(), MalygosPositions[0].GetPositionZ()); + case EVENT_ARCANE_BARRAGE: + DoCast(me, SPELL_ARCANE_BARRAGE); + _events.ScheduleEvent(EVENT_ARCANE_BARRAGE, urand(4, 12)*IN_MILLISECONDS, 0, PHASE_TWO); + break; } } } - // we need a better way for pathing - if (_delayedMovement) + void JustDied(Unit* /*killer*/) { - if (_delayedMovementTimer <= diff) - { - me->GetMotionMaster()->MovePoint(MOVE_DEEP_BREATH_ROTATION, MalygosPhaseTwoWaypoints[_currentPos]); - _delayedMovementTimer = 8000; - _delayedMovement = false; - } _delayedMovementTimer -= diff; + if (Creature* malygos = me->GetMap()->GetCreature(_instance->GetData64(DATA_MALYGOS))) + malygos->AI()->SetData(DATA_SUMMON_DEATHS, malygos->AI()->GetData(DATA_SUMMON_DEATHS) + 1); } - // at 50 % health malygos switch to phase 2 - if (me->GetHealthPct() <= 50.0f && _phase == PHASE_ONE) - StartPhaseTwo(); + private: + InstanceScript* _instance; + EventMap _events; + }; - // the boss is handling vortex - if (me->HasAura(SPELL_VORTEX_2)) - return; + CreatureAI* GetAI(Creature* creature) const + { + return new npc_scion_of_eternityAI(creature); + } +}; - // We can't cast if we are casting already. - if (me->HasUnitState(UNIT_STATE_CASTING)) - return; +class npc_arcane_overload : public CreatureScript +{ +public: + npc_arcane_overload() : CreatureScript("npc_arcane_overload") { } - while (uint32 eventId = events.ExecuteEvent()) - { - switch (eventId) - { - case EVENT_YELL_2: - Talk(SAY_END_P_TWO); - break; - case EVENT_YELL_3: - Talk(SAY_INTRO_P_THREE); - break; - case EVENT_YELL_4: - Talk(SAY_AGGRO_P_THREE); - break; - case EVENT_YELL_0: - Talk(SAY_END_P_ONE); - break; - case EVENT_YELL_1: - Talk(SAY_AGGRO_P_TWO); - break; - case EVENT_ARCANE_BREATH: - DoCast(me->getVictim(), SPELL_ARCANE_BREATH); - events.ScheduleEvent(EVENT_ARCANE_BREATH, urand(35, 60)*IN_MILLISECONDS, 0, PHASE_ONE); - break; - case EVENT_ARCANE_STORM: - DoCast(me->getVictim(), SPELL_ARCANE_STORM); - events.ScheduleEvent(EVENT_ARCANE_STORM, urand(5, 10)*IN_MILLISECONDS, 0, PHASE_ONE); - break; - case EVENT_VORTEX: - PrepareForVortex(); - events.ScheduleEvent(EVENT_VORTEX, urand(60, 80)*IN_MILLISECONDS, 0, PHASE_ONE); - break; - case EVENT_POWER_SPARKS: - instance->SetData(DATA_POWER_SPARKS_HANDLING, 0); - events.ScheduleEvent(EVENT_POWER_SPARKS, urand(30, 35)*IN_MILLISECONDS, 0, PHASE_ONE); - break; - case EVENT_SURGE_POWER: - me->GetMotionMaster()->MoveIdle(); - _delayedMovement = true; - DoCast(SPELL_SURGE_POWER); - events.ScheduleEvent(EVENT_SURGE_POWER, urand(60, 70)*IN_MILLISECONDS, 0, PHASE_TWO); - break; - case EVENT_SUMMON_ARCANE: - DoCast(SPELL_SUMMON_ARCANE_BOMB); - events.ScheduleEvent(EVENT_SUMMON_ARCANE, urand(12, 15)*IN_MILLISECONDS, 0, PHASE_TWO); - break; - case EVENT_SURGE_POWER_PHASE_3: - DoCast(GetTargetPhaseThree(), SPELL_SURGE_POWER_PHASE_3); - events.ScheduleEvent(EVENT_SURGE_POWER_PHASE_3, urand(7, 16)*IN_MILLISECONDS, 0, PHASE_THREE); - break; - case EVENT_STATIC_FIELD: - DoCast(GetTargetPhaseThree(), SPELL_STATIC_FIELD); - events.ScheduleEvent(EVENT_STATIC_FIELD, urand(20, 30)*IN_MILLISECONDS, 0, PHASE_THREE); - break; - default: - break; - } - } - - DoMeleeAttackIfReady(); + struct npc_arcane_overloadAI : public ScriptedAI + { + npc_arcane_overloadAI(Creature* creature) : ScriptedAI(creature) + { + _instance = creature->GetInstanceScript(); + me->SetReactState(REACT_PASSIVE); } - Unit* GetTargetPhaseThree() + void IsSummonedBy(Unit* summoner) { - Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0); + if ((_malygos = summoner->ToCreature())) + _malygos->AI()->SetGUID(me->GetGUID(), DATA_LAST_OVERLOAD_GUID); + } - // we are a drake - if (target->GetVehicleKit()) - return target; + void UpdateAI (uint32 /*diff*/) + { + } - // we are a player using a drake (or at least you should) - if (target->GetTypeId() == TYPEID_PLAYER) + void DoAction(int32 /*action*/) + { + if (Creature* malygos = me->GetMap()->GetCreature(_instance->GetData64(DATA_MALYGOS))) { - if (Unit* base = target->GetVehicleBase()) - return base; + if (malygos->AI()->GetData(DATA_PHASE) == PHASE_TWO) + me->DespawnOrUnsummon(6*IN_MILLISECONDS); + // If evade is hit during phase II shields should disappear with no delay + else if (malygos->AI()->GetData(DATA_PHASE) == 0) + me->DespawnOrUnsummon(); } + } - // is a player falling from a vehicle? - return NULL; + void SpellHit(Unit* /*caster*/, SpellInfo const* spell) + { + if (spell->Id == SPELL_ARCANE_BOMB_TRIGGER) + { + DoCastAOE(SPELL_ARCANE_BOMB_KNOCKBACK_DAMAGE, true); + DoCast(me, SPELL_ARCANE_OVERLOAD_1, true); + } + } + + private: + InstanceScript* _instance; + Creature* _malygos; + }; + + CreatureAI* GetAI(Creature* creature) const + { + return new npc_arcane_overloadAI (creature); + } +}; + +// SmartAI does not work correctly for vehicles +class npc_wyrmrest_skytalon : public CreatureScript +{ +public: + npc_wyrmrest_skytalon() : CreatureScript("npc_wyrmrest_skytalon") { } + + struct npc_wyrmrest_skytalonAI : public VehicleAI + { + npc_wyrmrest_skytalonAI(Creature* creature) : VehicleAI(creature) + { + } + + void IsSummonedBy(Unit* summoner) + { + me->CastSpell(summoner, SPELL_RIDE_RED_DRAGON_TRIGGERED, true); + } + + void PassengerBoarded(Unit* unit, int8 /*seat*/, bool apply) + { + if (apply) + { + _playerController = NULL; + _playerController = unit->ToPlayer(); + } + if (!apply) + { + me->DespawnOrUnsummon(2050); + me->SetOrientation(2.5f); + me->SetSpeed(MOVE_FLIGHT, 1.0f, true); + Position pos; + me->GetPosition(&pos); + pos.m_positionX += 10.0f; + pos.m_positionY += 10.0f; + pos.m_positionZ += 12.0f; + me->GetMotionMaster()->MovePoint(1, pos); + } } void JustDied(Unit* /*killer*/) { - Talk(SAY_DEATH); - _JustDied(); + // TO DOs: check script beginning for more info. + _playerController->Kill(_playerController, true); } private: - uint8 _phase; - uint32 _bersekerTimer; - uint8 _currentPos; // used for phase 2 rotation... - bool _delayedMovement; // used in phase 2. - uint32 _delayedMovementTimer; // used in phase 2 - uint8 _summonDeaths; - Position _homePosition; // it can get bugged because core thinks we are pathing - bool _mustTalk; - bool _cannotMove; + Player* _playerController; }; + + CreatureAI* GetAI(Creature* creature) const + { + return new npc_wyrmrest_skytalonAI (creature); + } +}; + +// We shouldn't use SAI for stuff that aren't within boss main mechanic +// and SAI type of despawn can cause problems here. +class npc_static_field : public CreatureScript +{ + public: + npc_static_field() : CreatureScript("npc_static_field") { } + + struct npc_static_fieldAI : public ScriptedAI + { + npc_static_fieldAI(Creature* creature) : ScriptedAI(creature) + { + } + + void IsSummonedBy(Unit* /*summoner*/) + { + // For some great reason the spell doesn't time it... + me->DespawnOrUnsummon(30*IN_MILLISECONDS); + } + }; + + CreatureAI* GetAI(Creature* creature) const + { + return new npc_static_fieldAI (creature); + } +}; + +class spell_malygos_portal_beam : public SpellScriptLoader +{ + public: + spell_malygos_portal_beam() : SpellScriptLoader("spell_malygos_portal_beam") { } + + class spell_malygos_portal_beam_AuraScript : public AuraScript + { + PrepareAuraScript(spell_malygos_portal_beam_AuraScript); + + bool Load() + { + return GetCaster()->GetTypeId() == TYPEID_UNIT; + } + + bool Validate(SpellInfo const* /*spell*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_PORTAL_OPENED)) + return false; + + return true; + } + + void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (Creature* target = GetTarget()->ToCreature()) + target->CastSpell(target, SPELL_PORTAL_OPENED); + } + + void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (Creature* target = GetTarget()->ToCreature()) + target->RemoveAura(SPELL_PORTAL_OPENED); + } + + void Register() + { + OnEffectApply += AuraEffectApplyFn(spell_malygos_portal_beam_AuraScript::OnApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + AfterEffectRemove += AuraEffectRemoveFn(spell_malygos_portal_beam_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_malygos_portal_beam_AuraScript(); + } +}; + +class spell_malygos_random_portal : public SpellScriptLoader +{ + public: + spell_malygos_random_portal() : SpellScriptLoader("spell_malygos_random_portal") { } + + class spell_malygos_random_portal_SpellScript : public SpellScript + { + PrepareSpellScript(spell_malygos_random_portal_SpellScript); + + bool Load() + { + return GetCaster()->GetTypeId() == TYPEID_UNIT; + } + + void HandleDummy(SpellEffIndex /*effIndex*/) + { + Creature* malygos = GetCaster()->ToCreature(); + if (Creature* target = GetHitCreature()) + { + Position pos; + pos.m_positionZ = target->GetPositionZ(); + target->GetNearPoint2D(pos.m_positionX, pos.m_positionY, frand(29.1f, 30.0f), target->GetAngle(malygos)); + malygos->GetMotionMaster()->MovePoint(POINT_NEAR_RANDOM_PORTAL_P_NONE, pos); + } + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_malygos_random_portal_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_malygos_random_portal_SpellScript(); + } +}; + +class isPlayerOnVehicleChecker +{ + public: + isPlayerOnVehicleChecker(Unit* source) : _source(source) { } + + bool operator()(WorldObject* unit) + { + if (Unit* target = ObjectAccessor::GetUnit(*_source, unit->GetGUID())) + if (target->IsOnVehicle(target->GetVehicleBase())) + return true; + + return false; + } + + private: + Unit* _source; +}; + +class spell_malygos_arcane_storm : public SpellScriptLoader +{ + public: + spell_malygos_arcane_storm() : SpellScriptLoader("spell_malygos_arcane_storm") { } + + class spell_malygos_arcane_storm_SpellScript : public SpellScript + { + PrepareSpellScript(spell_malygos_arcane_storm_SpellScript); + + bool Load() + { + return GetCaster()->GetTypeId() == TYPEID_UNIT; + } + + bool Validate(SpellInfo const* /*spell*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_ARCANE_STORM_EXTRA_VISUAL)) + return false; + + return true; + } + + void FilterTargets(std::list& targets) + { + Creature* malygos = GetCaster()->ToCreature(); + if (GetSpellInfo()->Id == SPELL_ARCANE_STORM_P_III) + targets.remove_if(isPlayerOnVehicleChecker(malygos)); + + if (!targets.empty()) + Trinity::Containers::RandomResizeList(targets, (malygos->GetMap()->GetDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL ? 4 : 10)); + + for (std::list::const_iterator itr = targets.begin(); itr != targets.end(); ++itr) + malygos->CastSpell((*itr)->ToUnit(), SPELL_ARCANE_STORM_EXTRA_VISUAL, true); + } + + void Register() + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_malygos_arcane_storm_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_malygos_arcane_storm_SpellScript(); + } }; class spell_malygos_vortex_dummy : public SpellScriptLoader { public: - spell_malygos_vortex_dummy() : SpellScriptLoader("spell_malygos_vortex_dummy") {} + spell_malygos_vortex_dummy() : SpellScriptLoader("spell_malygos_vortex_dummy") { } class spell_malygos_vortex_dummy_SpellScript : public SpellScript { PrepareSpellScript(spell_malygos_vortex_dummy_SpellScript) + bool Load() + { + return GetCaster()->GetTypeId() == TYPEID_UNIT; + } + void HandleScript(SpellEffIndex /*effIndex*/) { - Unit* caster = GetCaster(); - - if (!caster) - return; - - // each player will enter to the trigger vehicle (entry 30090) already spawned (each one can hold up to 5 players, it has 5 seats) - // the players enter to the vehicles casting SPELL_VORTEX_4 OR SPELL_VORTEX_5 + Creature* caster = GetCaster()->ToCreature(); + // Each player will enter to the trigger vehicle (entry 30090) which is already spawned (each one can hold up to 5 players, it has 5 seats, + // the players enter the vehicles casting SPELL_VORTEX_4 or SPELL_VORTEX_5. if (InstanceScript* instance = caster->GetInstanceScript()) instance->SetData(DATA_VORTEX_HANDLING, 0); @@ -695,9 +1849,22 @@ class spell_malygos_vortex_visual : public SpellScriptLoader { PrepareAuraScript(spell_malygos_vortex_visual_AuraScript); + bool Load() + { + return GetCaster()->GetTypeId() == TYPEID_UNIT; + } + + bool Validate(SpellInfo const* /*spell*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_VORTEX_1) || !sSpellMgr->GetSpellInfo(SPELL_VORTEX_6)) + return false; + + return true; + } + void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) { - if (Unit* caster = GetCaster()) + if (Creature* caster = GetCaster()->ToCreature()) { ThreatContainer::StorageType const& m_threatlist = caster->getThreatManager().getThreatList(); for (ThreatContainer::StorageType::const_iterator itr = m_threatlist.begin(); itr!= m_threatlist.end(); ++itr) @@ -705,13 +1872,12 @@ class spell_malygos_vortex_visual : public SpellScriptLoader if (Unit* target = (*itr)->getTarget()) { Player* targetPlayer = target->ToPlayer(); - if (!targetPlayer || targetPlayer->isGameMaster()) continue; if (InstanceScript* instance = caster->GetInstanceScript()) { - // teleport spell - i am not sure but might be it must be casted by each vehicle when its passenger leaves it + // Teleport spell - I'm not sure but might be it must be casted by each vehicle when it's passenger leaves it. if (Creature* trigger = caster->GetMap()->GetCreature(instance->GetData64(DATA_TRIGGER))) trigger->CastSpell(targetPlayer, SPELL_VORTEX_6, true); } @@ -720,18 +1886,10 @@ class spell_malygos_vortex_visual : public SpellScriptLoader if (Creature* malygos = caster->ToCreature()) { - // This is a hack, we have to re add players to the threat list because when they enter to the vehicles they are removed. - // Anyway even with this issue, the boss does not enter in evade mode - this prevents iterate an empty list in the next vortex execution. - malygos->SetInCombatWithZone(); - - malygos->SetDisableGravity(false); - malygos->SetCanFly(false); - - malygos->GetMotionMaster()->MoveChase(caster->getVictim()); + malygos->GetMotionMaster()->MoveLand(POINT_LAND_AFTER_VORTEX_P_ONE, MalygosPositions[2]); malygos->RemoveAura(SPELL_VORTEX_1); } } - } void Register() @@ -746,365 +1904,595 @@ class spell_malygos_vortex_visual : public SpellScriptLoader } }; -class npc_portal_eoe: public CreatureScript +class ExactDistanceCheck { -public: - npc_portal_eoe() : CreatureScript("npc_portal_eoe") {} + public: + ExactDistanceCheck(Unit* source, float dist) : _source(source), _dist(dist) { } - CreatureAI* GetAI(Creature* creature) const - { - return new npc_portal_eoeAI(creature); - } - - struct npc_portal_eoeAI : public ScriptedAI - { - npc_portal_eoeAI(Creature* creature) : ScriptedAI(creature) + bool operator()(WorldObject* unit) { - _instance = creature->GetInstanceScript(); - } - - void SpellHit(Unit* /*caster*/, const SpellInfo* spell) - { - if (spell->Id == SPELL_PORTAL_OPENED) - { - DoCast(me, SPELL_SUMMON_POWER_PARK, true); - } - } - - void UpdateAI(uint32 /*diff*/) - { - // When duration of oppened riff visual ends, - // closed one should be cast - if (!me->HasAura(SPELL_PORTAL_VISUAL_CLOSED) && - !me->HasAura(SPELL_PORTAL_OPENED)) - DoCast(me, SPELL_PORTAL_VISUAL_CLOSED, true); - - if (_instance) - { - if (Creature* malygos = Unit::GetCreature(*me, _instance->GetData64(DATA_MALYGOS))) - { - if (malygos->AI()->GetData(DATA_PHASE) != PHASE_ONE) - { - me->RemoveAura(SPELL_PORTAL_OPENED); - DoCast(me, SPELL_PORTAL_VISUAL_CLOSED, true); - } - } - } - } - - void JustSummoned(Creature* summon) - { - summon->SetInCombatWithZone(); + return _source->GetExactDist2d(unit) > _dist; } private: - uint32 _summonTimer; - InstanceScript* _instance; - }; + Unit* _source; + float _dist; }; - -class npc_power_spark: public CreatureScript +class spell_arcane_overload : public SpellScriptLoader { -public: - npc_power_spark() : CreatureScript("npc_power_spark") {} + public: + spell_arcane_overload() : SpellScriptLoader("spell_arcane_overload") { } - CreatureAI* GetAI(Creature* creature) const - { - return new npc_power_sparkAI(creature); - } - - struct npc_power_sparkAI : public ScriptedAI - { - npc_power_sparkAI(Creature* creature) : ScriptedAI(creature) + class spell_arcane_overload_SpellScript : public SpellScript { - _instance = creature->GetInstanceScript(); + PrepareSpellScript(spell_arcane_overload_SpellScript); - MoveToMalygos(); - // Talk range was not enough for this encounter - sCreatureTextMgr->SendChat(me, EMOTE_POWER_SPARK_SUMMONED, 0, CHAT_MSG_ADDON, LANG_ADDON, TEXT_RANGE_MAP); - } - - void EnterEvadeMode() - { - me->DespawnOrUnsummon(); - } - - void MoveToMalygos() - { - me->GetMotionMaster()->MoveIdle(); - - if (_instance) + bool Load() { - if (Creature* malygos = Unit::GetCreature(*me, _instance->GetData64(DATA_MALYGOS))) - me->GetMotionMaster()->MoveFollow(malygos, 0.0f, 0.0f); + return GetCaster()->GetTypeId() == TYPEID_UNIT; } - } - void UpdateAI(uint32 /*diff*/) - { - if (!_instance) - return; - - if (Creature* malygos = Unit::GetCreature(*me, _instance->GetData64(DATA_MALYGOS))) + void ResizeEffectRadiusTargetChecker(std::list& targets) { - if (malygos->AI()->GetData(DATA_PHASE) != PHASE_ONE) - { - me->DespawnOrUnsummon(); - return; - } - - if (malygos->HasAura(SPELL_VORTEX_1)) - { - me->GetMotionMaster()->MoveIdle(); - return; - } - - if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() != CHASE_MOTION_TYPE) - me->GetMotionMaster()->MoveFollow(malygos, 0.0f, 0.0f); + Creature* arcaneOverload = GetCaster()->ToCreature(); + targets.remove_if(ExactDistanceCheck(arcaneOverload, + GetSpellInfo()->Effects[EFFECT_0].CalcRadius(arcaneOverload) * arcaneOverload->GetFloatValue(OBJECT_FIELD_SCALE_X))); } - } - void JustDied(Unit* /*killer*/) + void Register() + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_arcane_overload_SpellScript::ResizeEffectRadiusTargetChecker, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + } + }; + + SpellScript* GetSpellScript() const { - me->CastSpell(me, SPELL_POWER_SPARK_DEATH, true); // not supposed to hide the fact it's there by not selectable + return new spell_arcane_overload_SpellScript(); } - - private: - InstanceScript* _instance; - }; }; -class npc_hover_disk : public CreatureScript +class spell_nexus_lord_align_disk_aggro : public SpellScriptLoader { -public: - npc_hover_disk() : CreatureScript("npc_hover_disk") { } + public: + spell_nexus_lord_align_disk_aggro() : SpellScriptLoader("spell_nexus_lord_align_disk_aggro") { } - CreatureAI* GetAI(Creature* creature) const - { - return new npc_hover_diskAI(creature); - } - - struct npc_hover_diskAI : public npc_escortAI - { - npc_hover_diskAI(Creature* creature) : npc_escortAI(creature) + class spell_nexus_lord_align_disk_aggro_SpellScript : public SpellScript { - if (me->GetEntry() == NPC_HOVER_DISK_CASTER) - me->SetReactState(REACT_PASSIVE); - else - me->SetInCombatWithZone(); + PrepareSpellScript(spell_nexus_lord_align_disk_aggro_SpellScript); - _instance = creature->GetInstanceScript(); + bool Load() + { + return GetCaster()->GetTypeId() == TYPEID_UNIT; + } + + void HandleScript(SpellEffIndex /*effIndex*/) + { + Creature* caster = GetCaster()->ToCreature(); + + if (Creature* target = GetHitCreature()) + target->GetMotionMaster()->MoveChase(caster->getVictim()); + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_nexus_lord_align_disk_aggro_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_nexus_lord_align_disk_aggro_SpellScript(); + } +}; + +class IsPlayerOnHoverDiskCheck +{ + public: + IsPlayerOnHoverDiskCheck(Unit* source, bool isOnHoverDisk) : _source(source), _isOnHoverDisk(isOnHoverDisk) { } + + bool operator()(WorldObject* unit) + { + if (_isOnHoverDisk) + { + if (Unit* passenger = ObjectAccessor::GetUnit(*_source, unit->GetGUID())) + if (passenger->GetVehicleBase() && passenger->GetVehicleBase()->GetEntry() == NPC_HOVER_DISK_MELEE) + return true; + } + else if (!_isOnHoverDisk) + { + if (Unit* passenger = ObjectAccessor::GetUnit(*_source, unit->GetGUID())) + if (!passenger->GetVehicleBase()) + return true; + } + + return false; } - void PassengerBoarded(Unit* unit, int8 /*seat*/, bool apply) + private: + Unit* _source; + + bool _isOnHoverDisk; +}; + +class spell_scion_of_eternity_arcane_barrage : public SpellScriptLoader +{ + public: + spell_scion_of_eternity_arcane_barrage() : SpellScriptLoader("spell_scion_of_eternity_arcane_barrage") { } + + class spell_scion_of_eternity_arcane_barrage_SpellScript : public SpellScript { - if (apply) + PrepareSpellScript(spell_scion_of_eternity_arcane_barrage_SpellScript); + + bool Load() { - if (unit->GetTypeId() == TYPEID_UNIT) + return GetCaster()->GetTypeId() == TYPEID_UNIT; + } + + void FilterMeleeHoverDiskPassangers(std::list& targets) + { + if (targets.empty()) + return; + + Creature* caster = GetCaster()->ToCreature(); + for (std::list::const_iterator itr = targets.begin(); itr != targets.end(); ++itr) + _playersWithoutDisk.push_back((*itr)); + + _playersWithoutDisk.remove_if(IsPlayerOnHoverDiskCheck(caster, false)); + if (_playersWithoutDisk.empty()) + targets.remove_if(IsPlayerOnHoverDiskCheck(caster, true)); + } + + void Register() + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_scion_of_eternity_arcane_barrage_SpellScript::FilterMeleeHoverDiskPassangers, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + } + + std::list _playersWithoutDisk; + }; + + SpellScript* GetSpellScript() const + { + return new spell_scion_of_eternity_arcane_barrage_SpellScript(); + } +}; + +class spell_malygos_destroy_platform_channel : public SpellScriptLoader +{ + public: + spell_malygos_destroy_platform_channel() : SpellScriptLoader("spell_malygos_destroy_platform_channel") { } + + class spell_malygos_destroy_platform_channel_AuraScript : public AuraScript + { + PrepareAuraScript(spell_malygos_destroy_platform_channel_AuraScript); + + bool Load() + { + return GetCaster()->GetTypeId() == TYPEID_UNIT; + } + + bool Validate(SpellInfo const* /*spell*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_DESTROY_PLATFORM_BOOM_VISUAL)) + return false; + + return true; + } + + void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (Creature* target = GetTarget()->ToCreature()) + if (InstanceScript* instance = target->GetInstanceScript()) + if (Creature* platformTrigger = target->GetMap()->GetCreature(instance->GetData64(DATA_ALEXSTRASZA_BUNNY_GUID))) + platformTrigger->CastSpell(platformTrigger, SPELL_DESTROY_PLATFORM_BOOM_VISUAL); + } + + void Register() + { + AfterEffectRemove += AuraEffectRemoveFn(spell_malygos_destroy_platform_channel_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_malygos_destroy_platform_channel_AuraScript(); + } +}; + +class spell_alexstrasza_bunny_destroy_platform_boom_visual : public SpellScriptLoader +{ + public: + spell_alexstrasza_bunny_destroy_platform_boom_visual() : SpellScriptLoader("spell_alexstrasza_bunny_destroy_platform_boom_visual") { } + + class spell_alexstrasza_bunny_destroy_platform_boom_visual_SpellScript : public SpellScript + { + PrepareSpellScript(spell_alexstrasza_bunny_destroy_platform_boom_visual_SpellScript); + + bool Load() + { + return GetCaster()->GetTypeId() == TYPEID_UNIT; + } + + bool Validate(SpellInfo const* /*spell*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_DESTROY_PLATFORM_EVENT)) + return false; + + return true; + } + + void HandleDummy(SpellEffIndex /*effIndex*/) + { + if (Creature* target = GetHitCreature()) { - me->setFaction(FACTION_HOSTILE); - unit->ToCreature()->SetInCombatWithZone(); + target->CastSpell(target, SPELL_DESTROY_PLATFORM_EVENT); } } - else + + void Register() { - // Error found: This is not called if the passenger is a player - if (unit->GetTypeId() == TYPEID_UNIT || unit->GetTypeId() == TYPEID_PLAYER) + OnEffectHitTarget += SpellEffectFn(spell_alexstrasza_bunny_destroy_platform_boom_visual_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_alexstrasza_bunny_destroy_platform_boom_visual_SpellScript(); + } +}; + +class spell_alexstrasza_bunny_destroy_platform_event : public SpellScriptLoader +{ + public: + spell_alexstrasza_bunny_destroy_platform_event() : SpellScriptLoader("spell_alexstrasza_bunny_destroy_platform_event") { } + + class spell_alexstrasza_bunny_destroy_platform_event_SpellScript : public SpellScript + { + PrepareSpellScript(spell_alexstrasza_bunny_destroy_platform_event_SpellScript); + + bool Load() + { + return GetCaster()->GetTypeId() == TYPEID_UNIT; + } + + void HandleSendEvent(SpellEffIndex /*effIndex*/) + { + Creature* caster = GetCaster()->ToCreature(); + if (InstanceScript* instance = caster->GetInstanceScript()) + if (GameObject* platform = caster->GetMap()->GetGameObject(instance->GetData64(DATA_PLATFORM))) + platform->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_DESTROYED); + } + + void HandleScript(SpellEffIndex /*effIndex*/) + { + Creature* caster = GetCaster()->ToCreature(); + caster->CastSpell(caster, SPELL_SUMMON_RED_DRAGON_BUDDY_F_CAST, true); + } + + void Register() + { + OnEffectHit += SpellEffectFn(spell_alexstrasza_bunny_destroy_platform_event_SpellScript::HandleSendEvent, EFFECT_0, SPELL_EFFECT_SEND_EVENT); + OnEffectHitTarget += SpellEffectFn(spell_alexstrasza_bunny_destroy_platform_event_SpellScript::HandleScript, EFFECT_2, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_alexstrasza_bunny_destroy_platform_event_SpellScript(); + } +}; + +class spell_wyrmrest_skytalon_summon_red_dragon_buddy : public SpellScriptLoader +{ + public: + spell_wyrmrest_skytalon_summon_red_dragon_buddy() : SpellScriptLoader("spell_wyrmrest_skytalon_summon_red_dragon_buddy") { } + + class spell_wyrmrest_skytalon_summon_red_dragon_buddy_SpellScript : public SpellScript + { + PrepareSpellScript(spell_wyrmrest_skytalon_summon_red_dragon_buddy_SpellScript); + + bool Load() + { + return GetCaster()->GetTypeId() == TYPEID_PLAYER; + } + + void ChangeSummonPos(SpellEffIndex /*effIndex*/) + { + // Adjust effect summon position to lower Z + WorldLocation summonPos = *GetExplTargetDest(); + Position offset = { 0.0f, 0.0f, -80.0f, 0.0f }; + summonPos.RelocateOffset(offset); + SetExplTargetDest(summonPos); + GetHitDest()->RelocateOffset(offset); + } + + void Register() + { + OnEffectHit += SpellEffectFn(spell_wyrmrest_skytalon_summon_red_dragon_buddy_SpellScript::ChangeSummonPos, EFFECT_0, SPELL_EFFECT_SUMMON); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_wyrmrest_skytalon_summon_red_dragon_buddy_SpellScript(); + } +}; + +class spell_wyrmrest_skytalon_ride_red_dragon_buddy_trigger : public SpellScriptLoader +{ + public: + spell_wyrmrest_skytalon_ride_red_dragon_buddy_trigger() : SpellScriptLoader("spell_wyrmrest_skytalon_ride_red_dragon_buddy_trigger") { } + + class spell_wyrmrest_skytalon_ride_red_dragon_buddy_trigger_SpellScript : public SpellScript + { + PrepareSpellScript(spell_wyrmrest_skytalon_ride_red_dragon_buddy_trigger_SpellScript); + + bool Load() + { + return GetCaster()->GetTypeId() == TYPEID_UNIT; + } + + void HandleScript(SpellEffIndex /*effIndex*/) + { + if (Unit* target = GetHitUnit()) + target->CastSpell(GetCaster(), GetEffectValue(), true); + } + + void Register() + { + OnEffectHitTarget += SpellEffectFn(spell_wyrmrest_skytalon_ride_red_dragon_buddy_trigger_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_wyrmrest_skytalon_ride_red_dragon_buddy_trigger_SpellScript(); + } +}; + +class spell_malygos_surge_of_power_warning_selector_25 : public SpellScriptLoader +{ + public: + spell_malygos_surge_of_power_warning_selector_25() : SpellScriptLoader("spell_malygos_surge_of_power_warning_selector_25") { } + + class spell_malygos_surge_of_power_warning_selector_25_SpellScript : public SpellScript + { + PrepareSpellScript(spell_malygos_surge_of_power_warning_selector_25_SpellScript) + + bool Load() + { + return GetCaster()->GetTypeId() == TYPEID_UNIT; + } + + bool Validate(SpellInfo const* /*spell*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_SURGE_OF_POWER_PHASE_3_25)) + return false; + + return true; + } + + void SendThreeTargets(std::list& targets) + { + Creature* caster = GetCaster()->ToCreature(); + targets.remove_if(isPlayerOnVehicleChecker(caster)); + if (targets.empty()) + return; + + for (std::list::const_iterator itr = targets.begin(); itr != targets.end(); ++itr) + _filteredSelectedTargets.push_back((*itr)); + + if (_filteredSelectedTargets.empty()) + return; + + uint8 guidDataSlot = 14; // SetGuid in Malygos AI is reserved for 14th, 15th and 16th Id for the three targets + Trinity::Containers::RandomResizeList(_filteredSelectedTargets, 3); + for (std::list::const_iterator itr = _filteredSelectedTargets.begin(); itr != _filteredSelectedTargets.end(); ++itr) { - // This will only be called if the passenger dies - if (_instance) + caster->AI()->SetGUID((*itr)->GetGUID(), guidDataSlot++); + if (IS_VEHICLE_GUID((*itr)->GetGUID())) { - if (Creature* malygos = Unit::GetCreature(*me, _instance->GetData64(DATA_MALYGOS))) - malygos->AI()->SetData(DATA_SUMMON_DEATHS, malygos->AI()->GetData(DATA_SUMMON_DEATHS)+1); + if (Vehicle* tempVehicle = (*itr)->ToCreature()->GetVehicleKit()) + if (tempVehicle->GetPassenger(0)) + if (Player* tempPlayer = tempVehicle->GetPassenger(0)->ToPlayer()) + caster->AI()->Talk(EMOTE_SURGE_OF_POWER_WARNING_P3, tempPlayer->GetGUID()); + } + else if (IS_PLAYER_GUID((*itr)->GetGUID())) + { + caster->AI()->Talk(EMOTE_SURGE_OF_POWER_WARNING_P3, (*itr)->GetGUID()); } - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - } - - me->GetMotionMaster()->MoveIdle(); - - if (me->GetEntry() == NPC_HOVER_DISK_MELEE || me->GetEntry() == NPC_HOVER_DISK_CASTER) - { - // Hack: Fall ground function can fail (remember the platform is a gameobject), we will teleport the disk to the ground - if (me->GetPositionZ() > GROUND_Z) - me->NearTeleportTo(me->GetPositionX(), me->GetPositionY(), GROUND_Z, 0); - me->SetHomePosition(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation()); - me->setFaction(FACTION_FRIENDLY); - me->AI()->EnterEvadeMode(); } } - } - void EnterEvadeMode() - { - // we dont evade - } - - void DoAction(int32 action) - { - if (me->GetEntry() != NPC_HOVER_DISK_CASTER) - return; - - switch (action) + void ExecuteMainSpell() { - case ACTION_HOVER_DISK_START_WP_1: - for (uint8 i = 0; i < MAX_HOVER_DISK_WAYPOINTS; i++) - AddWaypoint(i, HoverDiskWaypoints[i].GetPositionX(), HoverDiskWaypoints[i].GetPositionY(), HoverDiskWaypoints[i].GetPositionZ()); - break; - case ACTION_HOVER_DISK_START_WP_2: + // We shouldn't cast stuff from target selector hooks + Creature* caster = GetCaster()->ToCreature(); + caster->AI()->DoCastAOE(SPELL_SURGE_OF_POWER_PHASE_3_25); + } + + void Register() + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_malygos_surge_of_power_warning_selector_25_SpellScript::SendThreeTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + AfterHit += SpellHitFn(spell_malygos_surge_of_power_warning_selector_25_SpellScript::ExecuteMainSpell); + } + + std::list _filteredSelectedTargets; + }; + + SpellScript* GetSpellScript() const + { + return new spell_malygos_surge_of_power_warning_selector_25_SpellScript(); + } +}; + +class spell_malygos_surge_of_power_25 : public SpellScriptLoader +{ + public: + spell_malygos_surge_of_power_25() : SpellScriptLoader("spell_malygos_surge_of_power_25") { } + + class spell_malygos_surge_of_power_25_SpellScript : public SpellScript + { + PrepareSpellScript(spell_malygos_surge_of_power_25_SpellScript) + + bool Load() + { + return GetCaster()->GetTypeId() == TYPEID_UNIT; + } + + void FilterTargets(std::list& targets) + { + Creature* caster = GetCaster()->ToCreature(); + if (!targets.empty()) + targets.clear(); + + for (int guidSlot = 14; guidSlot <= 16; guidSlot++) + { + uint64 guidTypeChecker = caster->AI()->GetGUID(guidSlot); + if (IS_EMPTY_GUID(guidTypeChecker)) + continue; + + if (IS_VEHICLE_GUID(guidTypeChecker)) { - uint8 count = 0; - for (uint8 i = MAX_HOVER_DISK_WAYPOINTS-1; i > 0; i--) + WorldObject* tempTarget = caster->GetMap()->GetCreature(guidTypeChecker); + targets.push_back(tempTarget); + } + else if (IS_PLAYER_GUID(guidTypeChecker)) + { + WorldObject* tempTarget = ObjectAccessor::GetPlayer(*caster, guidTypeChecker); + targets.push_back(tempTarget); + } + } + } + + void Register() + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_malygos_surge_of_power_25_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); + } + }; + + SpellScript* GetSpellScript() const + { + return new spell_malygos_surge_of_power_25_SpellScript(); + } +}; + +class spell_alexstrasza_gift_beam : public SpellScriptLoader +{ + public: + spell_alexstrasza_gift_beam() : SpellScriptLoader("spell_alexstrasza_gift_beam") { } + + class spell_alexstrasza_gift_beam_AuraScript : public AuraScript + { + PrepareAuraScript(spell_alexstrasza_gift_beam_AuraScript); + + bool Load() + { + return GetCaster()->GetTypeId() == TYPEID_UNIT; + } + + bool Validate(SpellInfo const* /*spell*/) + { + if (!sSpellMgr->GetSpellInfo(SPELL_ALEXSTRASZAS_GIFT_BEAM_VISUAL)) + return false; + + return true; + } + + void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (Creature* target = GetTarget()->ToCreature()) + target->CastSpell(target, SPELL_ALEXSTRASZAS_GIFT_BEAM_VISUAL); + } + + void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (Creature* target = GetTarget()->ToCreature()) + target->RemoveAura(SPELL_ALEXSTRASZAS_GIFT_BEAM_VISUAL); + } + + void Register() + { + OnEffectApply += AuraEffectApplyFn(spell_alexstrasza_gift_beam_AuraScript::OnApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + AfterEffectRemove += AuraEffectRemoveFn(spell_alexstrasza_gift_beam_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + } + }; + + AuraScript* GetAuraScript() const + { + return new spell_alexstrasza_gift_beam_AuraScript(); + } +}; + +class spell_alexstrasza_gift_beam_visual : public SpellScriptLoader +{ + public: + spell_alexstrasza_gift_beam_visual() : SpellScriptLoader("spell_alexstrasza_gift_beam_visual") { } + + class spell_alexstrasza_gift_beam_visual_AuraScript : public AuraScript + { + PrepareAuraScript(spell_alexstrasza_gift_beam_visual_AuraScript); + + bool Load() + { + return GetCaster()->GetTypeId() == TYPEID_UNIT; + } + + void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (Creature* target = GetTarget()->ToCreature()) + { + if (target->GetMap()->GetDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL) + _alexstraszaGift = target->SummonGameObject(GO_ALEXSTRASZA_S_GIFT_10, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), target->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 0); + else if (target->GetMap()->GetDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL) + _alexstraszaGift = target->SummonGameObject(GO_ALEXSTRASZA_S_GIFT_25, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), target->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 0); + } + } + + void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (Creature* target = GetTarget()->ToCreature()) + if (InstanceScript* instance = GetCaster()->GetInstanceScript()) + { + _alexstraszaGift->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); + if ((_heartMagic = target->GetMap()->GetGameObject(instance->GetData64(DATA_HEART_OF_MAGIC_GUID)))) { - AddWaypoint(count, HoverDiskWaypoints[i].GetPositionX(), HoverDiskWaypoints[i].GetPositionY(), HoverDiskWaypoints[i].GetPositionZ()); - count++; + _heartMagic->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); + // TO DO: This is hack, core doesn't have support for these flags, + // remove line below if it ever gets supported otherwise object won't be accessible. + _heartMagic->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_INTERACT_COND); } - break; } - default: - return; } - Start(true, false, 0, 0, false, true); - } - - void UpdateEscortAI(const uint32 /*diff*/) - { - // we dont do melee damage! - } - - void WaypointReached(uint32 /*waypointId*/) - { - - } - - private: - InstanceScript* _instance; - }; -}; - - -// The reason of this AI is to make the creature able to enter in combat otherwise the spell casting of SPELL_ARCANE_OVERLOAD fails. -class npc_arcane_overload : public CreatureScript -{ -public: - npc_arcane_overload() : CreatureScript("npc_arcane_overload") {} - - CreatureAI* GetAI(Creature* creature) const - { - return new npc_arcane_overloadAI (creature); - } - - struct npc_arcane_overloadAI : public ScriptedAI - { - npc_arcane_overloadAI(Creature* creature) : ScriptedAI(creature) {} - - void AttackStart(Unit* who) - { - DoStartNoMovement(who); - } - - void Reset() - { - DoCast(me, SPELL_ARCANE_OVERLOAD, false); - } - - void UpdateAI(uint32 /*diff*/) - { - // we dont do melee damage! - } - - }; -}; - -// SmartAI does not work correctly for vehicles -class npc_wyrmrest_skytalon : public CreatureScript -{ -public: - npc_wyrmrest_skytalon() : CreatureScript("npc_wyrmrest_skytalon") {} - - CreatureAI* GetAI(Creature* creature) const - { - return new npc_wyrmrest_skytalonAI (creature); - } - - struct npc_wyrmrest_skytalonAI : public VehicleAI - { - npc_wyrmrest_skytalonAI(Creature* creature) : VehicleAI(creature) { } - - void IsSummonedBy(Unit* summoner) - { - summoner->CastSpell(me, SPELL_RIDE_RED_DRAGON, true); - } - - void PassengerBoarded(Unit* /*unit*/, int8 /*seat*/, bool apply) - { - if (!apply) - me->DespawnOrUnsummon(); - } - }; -}; - -class npc_alexstrasza_eoe : public CreatureScript -{ -public: - npc_alexstrasza_eoe() : CreatureScript("npc_alexstrasza_eoe") {} - - CreatureAI* GetAI(Creature* creature) const - { - return new npc_alexstrasza_eoeAI (creature); - } - - struct npc_alexstrasza_eoeAI : public ScriptedAI - { - npc_alexstrasza_eoeAI(Creature* creature) : ScriptedAI(creature) {} - - void Reset() - { - _events.Reset(); - _events.ScheduleEvent(EVENT_YELL_1, 0); - } - - void UpdateAI(uint32 /*diff*/) - { - while (uint32 eventId = _events.ExecuteEvent()) + void Register() { - switch (eventId) - { - case EVENT_YELL_1: - Talk(SAY_ONE); - _events.ScheduleEvent(EVENT_YELL_2, 4*IN_MILLISECONDS); - break; - case EVENT_YELL_2: - Talk(SAY_TWO); - _events.ScheduleEvent(EVENT_YELL_3, 4*IN_MILLISECONDS); - break; - case EVENT_YELL_3: - Talk(SAY_THREE); - _events.ScheduleEvent(EVENT_YELL_4, 7*IN_MILLISECONDS); - break; - case EVENT_YELL_4: - Talk(SAY_FOUR); - break; - } + OnEffectApply += AuraEffectApplyFn(spell_alexstrasza_gift_beam_visual_AuraScript::OnApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); + AfterEffectRemove += AuraEffectRemoveFn(spell_alexstrasza_gift_beam_visual_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); } + + GameObject* _alexstraszaGift; + GameObject* _heartMagic; + }; + + AuraScript* GetAuraScript() const + { + return new spell_alexstrasza_gift_beam_visual_AuraScript(); } - private: - EventMap _events; - }; }; class achievement_denyin_the_scion : public AchievementCriteriaScript { public: - achievement_denyin_the_scion() : AchievementCriteriaScript("achievement_denyin_the_scion") {} + achievement_denyin_the_scion() : AchievementCriteriaScript("achievement_denyin_the_scion") { } bool OnCheck(Player* source, Unit* /*target*/) { + // Only melee disks can be used if (Unit* disk = source->GetVehicleBase()) - if (disk->GetEntry() == NPC_HOVER_DISK_CASTER || disk->GetEntry() == NPC_HOVER_DISK_MELEE) + if (disk->GetEntry() == NPC_HOVER_DISK_MELEE) return true; + return false; } }; @@ -1114,11 +2502,29 @@ void AddSC_boss_malygos() new boss_malygos(); new npc_portal_eoe(); new npc_power_spark(); - new npc_hover_disk(); + new npc_melee_hover_disk(); + new npc_caster_hover_disk(); + new npc_nexus_lord(); + new npc_scion_of_eternity(); new npc_arcane_overload(); new npc_wyrmrest_skytalon(); + new npc_static_field(); + new spell_malygos_portal_beam(); + new spell_malygos_random_portal(); + new spell_malygos_arcane_storm(); new spell_malygos_vortex_dummy(); new spell_malygos_vortex_visual(); - new npc_alexstrasza_eoe(); + new spell_arcane_overload(); + new spell_nexus_lord_align_disk_aggro(); + new spell_scion_of_eternity_arcane_barrage(); + new spell_malygos_destroy_platform_channel(); + new spell_alexstrasza_bunny_destroy_platform_boom_visual(); + new spell_alexstrasza_bunny_destroy_platform_event(); + new spell_wyrmrest_skytalon_summon_red_dragon_buddy(); + new spell_wyrmrest_skytalon_ride_red_dragon_buddy_trigger(); + new spell_malygos_surge_of_power_warning_selector_25(); + new spell_malygos_surge_of_power_25(); + new spell_alexstrasza_gift_beam(); + new spell_alexstrasza_gift_beam_visual(); new achievement_denyin_the_scion(); } diff --git a/src/server/scripts/Northrend/Nexus/EyeOfEternity/eye_of_eternity.h b/src/server/scripts/Northrend/Nexus/EyeOfEternity/eye_of_eternity.h index c25feaafaf8..db879eab6fb 100644 --- a/src/server/scripts/Northrend/Nexus/EyeOfEternity/eye_of_eternity.h +++ b/src/server/scripts/Northrend/Nexus/EyeOfEternity/eye_of_eternity.h @@ -24,14 +24,19 @@ enum InstanceData MAX_ENCOUNTER, DATA_VORTEX_HANDLING, - DATA_POWER_SPARKS_HANDLING + DATA_POWER_SPARKS_HANDLING, + DATA_RESPAWN_IRIS }; enum InstanceData64 { DATA_TRIGGER, DATA_MALYGOS, - DATA_PLATFORM + DATA_PLATFORM, + DATA_ALEXSTRASZA_BUNNY_GUID, + DATA_HEART_OF_MAGIC_GUID, + DATA_FOCUSING_IRIS_GUID, + DATA_GIFT_BOX_BUNNY_GUID }; enum InstanceNpcs @@ -44,16 +49,22 @@ enum InstanceNpcs NPC_HOVER_DISK_CASTER = 30248, NPC_ARCANE_OVERLOAD = 30282, NPC_WYRMREST_SKYTALON = 30161, - NPC_ALEXSTRASZA = 32295 + NPC_ALEXSTRASZA = 32295, + NPC_ALEXSTRASZA_BUNNY = 31253, + NPC_ALEXSTRASZAS_GIFT = 32448, + NPC_SURGE_OF_POWER = 30334 }; enum InstanceGameObjects { GO_NEXUS_RAID_PLATFORM = 193070, GO_EXIT_PORTAL = 193908, - GO_FOCUSING_IRIS = 193958, - GO_ALEXSTRASZA_S_GIFT = 193905, - GO_ALEXSTRASZA_S_GIFT_2 = 193967 + GO_FOCUSING_IRIS_10 = 193958, + GO_FOCUSING_IRIS_25 = 193960, + GO_ALEXSTRASZA_S_GIFT_10 = 193905, + GO_ALEXSTRASZA_S_GIFT_25 = 193967, + GO_HEART_OF_MAGIC_10 = 194158, + GO_HEART_OF_MAGIC_25 = 194159 }; enum InstanceEvents @@ -63,10 +74,11 @@ enum InstanceEvents enum InstanceSpells { - SPELL_VORTEX_4 = 55853, // damage | used to enter to the vehicle - SPELL_VORTEX_5 = 56263, // damage | used to enter to the vehicle - SPELL_PORTAL_OPENED = 61236, - SPELL_RIDE_RED_DRAGON = 56071, + SPELL_VORTEX_4 = 55853, // damage | used to enter to the vehicle + SPELL_VORTEX_5 = 56263, // damage | used to enter to the vehicle + SPELL_PORTAL_OPENED = 61236, + SPELL_RIDE_RED_DRAGON_TRIGGERED = 56072, + SPELL_IRIS_OPENED = 61012 // visual when starting encounter }; #endif diff --git a/src/server/scripts/Northrend/Nexus/EyeOfEternity/instance_eye_of_eternity.cpp b/src/server/scripts/Northrend/Nexus/EyeOfEternity/instance_eye_of_eternity.cpp index 6b1be15f110..601e58fc323 100644 --- a/src/server/scripts/Northrend/Nexus/EyeOfEternity/instance_eye_of_eternity.cpp +++ b/src/server/scripts/Northrend/Nexus/EyeOfEternity/instance_eye_of_eternity.cpp @@ -24,7 +24,7 @@ class instance_eye_of_eternity : public InstanceMapScript { public: - instance_eye_of_eternity() : InstanceMapScript("instance_eye_of_eternity", 616) {} + instance_eye_of_eternity() : InstanceMapScript("instance_eye_of_eternity", 616) { } InstanceScript* GetInstanceScript(InstanceMap* map) const { @@ -41,9 +41,11 @@ public: portalTriggers.clear(); malygosGUID = 0; + irisGUID = 0; lastPortalGUID = 0; platformGUID = 0; exitPortalGUID = 0; + alexstraszaBunnyGUID = 0; }; bool SetBossState(uint32 type, EncounterState state) @@ -54,7 +56,7 @@ public: if (type == DATA_MALYGOS_EVENT) { if (state == FAIL) - { + { for (std::list::const_iterator itr_trigger = portalTriggers.begin(); itr_trigger != portalTriggers.end(); ++itr_trigger) { if (Creature* trigger = instance->GetCreature(*itr_trigger)) @@ -65,31 +67,18 @@ public: } } - SpawnGameObject(GO_FOCUSING_IRIS, focusingIrisPosition); SpawnGameObject(GO_EXIT_PORTAL, exitPortalPosition); if (GameObject* platform = instance->GetGameObject(platformGUID)) platform->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_DESTROYED); } else if (state == DONE) - { - if (Creature* malygos = instance->GetCreature(malygosGUID)) - malygos->SummonCreature(NPC_ALEXSTRASZA, 829.0679f, 1244.77f, 279.7453f, 2.32f); - SpawnGameObject(GO_EXIT_PORTAL, exitPortalPosition); - - // we make the platform appear again because at the moment we don't support looting using a vehicle - if (GameObject* platform = instance->GetGameObject(platformGUID)) - platform->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_DESTROYED); - - if (GameObject* chest = instance->GetGameObject(chestGUID)) - chest->SetRespawnTime(7*DAY); - } } return true; } - //TODO: this should be handled in map, maybe add a summon function in map + // TO DO: this should be handled in map, maybe add a summon function in map // There is no other way afaik... void SpawnGameObject(uint32 entry, Position& pos) { @@ -112,16 +101,31 @@ public: case GO_NEXUS_RAID_PLATFORM: platformGUID = go->GetGUID(); break; - case GO_FOCUSING_IRIS: - go->GetPosition(&focusingIrisPosition); + case GO_FOCUSING_IRIS_10: + if (instance->GetDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL) + { + irisGUID = go->GetGUID(); + go->GetPosition(&focusingIrisPosition); + } + break; + case GO_FOCUSING_IRIS_25: + if (instance->GetDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL) + { + irisGUID = go->GetGUID(); + go->GetPosition(&focusingIrisPosition); + } break; case GO_EXIT_PORTAL: exitPortalGUID = go->GetGUID(); go->GetPosition(&exitPortalPosition); break; - case GO_ALEXSTRASZA_S_GIFT: - case GO_ALEXSTRASZA_S_GIFT_2: - chestGUID = go->GetGUID(); + case GO_HEART_OF_MAGIC_10: + if (instance->GetDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL) + heartOfMagicGUID = go->GetGUID(); + break; + case GO_HEART_OF_MAGIC_25: + if (instance->GetDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL) + heartOfMagicGUID = go->GetGUID(); break; } } @@ -139,18 +143,27 @@ public: case NPC_PORTAL_TRIGGER: portalTriggers.push_back(creature->GetGUID()); break; + case NPC_ALEXSTRASZA_BUNNY: + alexstraszaBunnyGUID = creature->GetGUID(); + break; + case NPC_ALEXSTRASZAS_GIFT: + giftBoxBunnyGUID = creature->GetGUID(); + break; } } - void ProcessEvent(WorldObject* obj, uint32 eventId) + void ProcessEvent(WorldObject* /*obj*/, uint32 eventId) { if (eventId == EVENT_FOCUSING_IRIS) - { - if (GameObject* go = obj->ToGameObject()) - go->Delete(); // this is not the best way. + { + if (Creature* alexstraszaBunny = instance->GetCreature(alexstraszaBunnyGUID)) + { + alexstraszaBunny->CastSpell(alexstraszaBunny, SPELL_IRIS_OPENED); + instance->GetGameObject(irisGUID)->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_IN_USE); + } if (Creature* malygos = instance->GetCreature(malygosGUID)) - malygos->GetMotionMaster()->MovePoint(4, 770.10f, 1275.33f, 267.23f); // MOVE_INIT_PHASE_ONE + malygos->AI()->DoAction(0); // ACTION_LAND_ENCOUNTER_START if (GameObject* exitPortal = instance->GetGameObject(exitPortalGUID)) exitPortal->Delete(); @@ -194,7 +207,7 @@ public: void PowerSparksHandling() { - bool next = (lastPortalGUID == portalTriggers.back() || !lastPortalGUID ? true : false); + bool next = (lastPortalGUID == portalTriggers.back() || !lastPortalGUID ? true : false); for (std::list::const_iterator itr_trigger = portalTriggers.begin(); itr_trigger != portalTriggers.end(); ++itr_trigger) { @@ -223,6 +236,9 @@ public: case DATA_POWER_SPARKS_HANDLING: PowerSparksHandling(); break; + case DATA_RESPAWN_IRIS: + SpawnGameObject(instance->GetDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL ? GO_FOCUSING_IRIS_10 : GO_FOCUSING_IRIS_25, focusingIrisPosition); + break; } } @@ -236,6 +252,14 @@ public: return malygosGUID; case DATA_PLATFORM: return platformGUID; + case DATA_ALEXSTRASZA_BUNNY_GUID: + return alexstraszaBunnyGUID; + case DATA_HEART_OF_MAGIC_GUID: + return heartOfMagicGUID; + case DATA_FOCUSING_IRIS_GUID: + return irisGUID; + case DATA_GIFT_BOX_BUNNY_GUID: + return giftBoxBunnyGUID; } return 0; @@ -287,10 +311,13 @@ public: std::list vortexTriggers; std::list portalTriggers; uint64 malygosGUID; + uint64 irisGUID; uint64 lastPortalGUID; uint64 platformGUID; uint64 exitPortalGUID; - uint64 chestGUID; + uint64 heartOfMagicGUID; + uint64 alexstraszaBunnyGUID; + uint64 giftBoxBunnyGUID; Position focusingIrisPosition; Position exitPortalPosition; }; From c417c5a1c7787d6b0dea241046de86eb8bf75221 Mon Sep 17 00:00:00 2001 From: Trista Date: Thu, 28 Feb 2013 18:45:00 +0200 Subject: [PATCH 09/13] DB/Spells: Opening spell (id: 61437)added to some of Blood Elf's classes * Add missing generic spell for opening chests for most of Blood Elf's classes. It was preventing them to loot in Eye of Eternity Alexstrasza's Gift Box, Heart of Magic and maybe more. --- .../2013_02_28_00_world_playercreateinfo_spell.sql | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 sql/updates/world/2013_02_28_00_world_playercreateinfo_spell.sql diff --git a/sql/updates/world/2013_02_28_00_world_playercreateinfo_spell.sql b/sql/updates/world/2013_02_28_00_world_playercreateinfo_spell.sql new file mode 100644 index 00000000000..9f0ce0d8533 --- /dev/null +++ b/sql/updates/world/2013_02_28_00_world_playercreateinfo_spell.sql @@ -0,0 +1,11 @@ +-- Add missing generic spell for opening chests for most of Blood Elf's classes +-- (was preventing them to loot Eye of Eternity Alexstrasza's Gift Box, Heart of Magic and maybe more.) +DELETE FROM `playercreateinfo_spell` WHERE `race`=10 AND `Spell`=61437; +INSERT INTO `playercreateinfo_spell` (`race`,`class`,`Spell`,`Note`) VALUES +(10,2,61437, 'Opening'), +(10,3,61437, 'Opening'), +(10,4,61437, 'Opening'), +(10,5,61437, 'Opening'), +(10,6,61437, 'Opening'), +(10,8,61437, 'Opening'), +(10,9,61437, 'Opening'); From 6343a28030e5ca7ad337226ef5e37704714aa594 Mon Sep 17 00:00:00 2001 From: Vincent_Michael Date: Thu, 28 Feb 2013 18:29:43 +0100 Subject: [PATCH 10/13] Core: Whitespace cleanup --- src/server/game/Entities/Player/Player.h | 2 +- .../Nexus/EyeOfEternity/boss_malygos.cpp | 48 +++++++++---------- .../instance_eye_of_eternity.cpp | 4 +- 3 files changed, 27 insertions(+), 27 deletions(-) diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index a3327e20c93..a7c0cb2e736 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -1189,7 +1189,7 @@ class Player : public Unit, public GridObject void RemovePet(Pet* pet, PetSaveMode mode, bool returnreagent = false); uint32 GetPhaseMaskForSpawn() const; // used for proper set phase for DB at GM-mode creature/GO spawn - /// Handles said message in regular chat based on declared language and in config pre-defined Range. + /// Handles said message in regular chat based on declared language and in config pre-defined Range. void Say(std::string const& text, const uint32 language); /// Handles yelled message in regular chat based on declared language and in config pre-defined Range. void Yell(std::string const& text, const uint32 language); diff --git a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp index 658fa48fd3a..b258be20feb 100644 --- a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp +++ b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp @@ -156,7 +156,7 @@ enum Spells enum Movements { POINT_NEAR_RANDOM_PORTAL_P_NONE = 1, - POINT_LAND_P_ONE, + POINT_LAND_P_ONE, POINT_VORTEX_P_ONE, POINT_LAND_AFTER_VORTEX_P_ONE, POINT_LIFT_IN_AIR_P_ONE, @@ -286,7 +286,7 @@ Position const MalygosPositions[MAX_MALYGOS_POS] = { 754.393f, 1301.27f, 292.91f, 0.0f }, // Point vortex { 754.362f, 1301.61f, 266.17f, 0.0f }, // Land after vortex { 754.695f, 1301.66f, 316.65f, 0.0f }, // Point surge of Power phase II - { 755.681f, 1298.41f, 220.06f, 0.0f } // Point idle phase III + { 755.681f, 1298.41f, 220.06f, 0.0f } // Point idle phase III }; Position const AlexstraszaSpawnPos = { 854.551f, 1225.31f, 300.901f, 0.0f }; // Alexstrasza's spawn position @@ -372,10 +372,10 @@ public: me->SetSpeed(MOVE_FLIGHT, _flySpeed * 0.25f); if (_despawned) DoAction(ACTION_HANDLE_RESPAWN); - + SetPhase(PHASE_NOT_STARTED, true); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetReactState(REACT_PASSIVE); + me->SetReactState(REACT_PASSIVE); if (instance) instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); } @@ -383,7 +383,7 @@ public: uint32 GetData(uint32 data) const { switch (data) - { + { case DATA_SUMMON_DEATHS: return _summonDeaths; case DATA_PHASE: @@ -415,7 +415,7 @@ public: DoAction(ACTION_HANDLE_P_THREE_INTRO); } } - } + } } uint64 GetGUID(int32 data) const @@ -624,7 +624,7 @@ public: else if (_phase == PHASE_THREE) summons.DespawnAll(); } - + if (instance) instance->SetBossState(DATA_MALYGOS_EVENT, NOT_STARTED); } @@ -633,7 +633,7 @@ public: { if (victim->GetTypeId() != TYPEID_PLAYER) return; - + if (!_killSpamFilter) { switch (_phase) @@ -667,7 +667,7 @@ public: Talk(SAY_BUFF_SPARK); } else if (spell->Id == SPELL_MALYGOS_BERSERK) - sCreatureTextMgr->SendChat(me, EMOTE_HIT_BERSERKER_TIMER, 0, CHAT_MSG_ADDON, LANG_ADDON, TEXT_RANGE_MAP); + sCreatureTextMgr->SendChat(me, EMOTE_HIT_BERSERKER_TIMER, 0, CHAT_MSG_ADDON, LANG_ADDON, TEXT_RANGE_MAP); } void MoveInLineOfSight(Unit* who) @@ -679,7 +679,7 @@ public: if (who->GetDistance(me) <= 2.5f) who->CastSpell(me, SPELL_POWER_SPARK_MALYGOS, true); } - + void MovementInform(uint32 type, uint32 id) { if (type != POINT_MOTION_TYPE && type != EFFECT_MOTION_TYPE) @@ -928,7 +928,7 @@ public: case EVENT_LIGHT_DIMENSION_CHANGE: SendLightOverride(LIGHT_CHANGE_DIMENSIONS, 2*IN_MILLISECONDS); break; - case EVENT_MOVE_TO_P_THREE_POINT: + case EVENT_MOVE_TO_P_THREE_POINT: Talk(SAY_START_P_THREE); me->GetMotionMaster()->MovePoint(POINT_IDLE_P_THREE, MalygosPositions[4]); break; @@ -1002,7 +1002,7 @@ public: me->DespawnOrUnsummon(5*IN_MILLISECONDS); } - private: + private: // Used to generate perfect cyclic movements (Enter Circle). void FillCirclePath(Position const& centerPos, float radius, float z, Movement::PointsArray& path, bool clockwise) { @@ -1018,7 +1018,7 @@ public: path.push_back(point); } } - + // Function that will change lights of map for all players on map. void SendLightOverride(uint32 overrideId, uint32 fadeInTime) const { @@ -1051,7 +1051,7 @@ public: Unit* _tempSurgeTarget; // These three are used for 10 man Surge of Power targeting. Vehicle* _drakeVehicle; Player* _playerSurgeTarget; - + bool _killSpamFilter; // Prevent text spamming on killed player by helping implement a CD. bool _canAttack; // Used to control attacking (Move Chase not being applied after Stop Attack, only few times should act like this). bool _despawned; // Checks if boss pass through evade on reset. @@ -1361,7 +1361,7 @@ public: path.push_back(point); } } - + InstanceScript* _instance; }; @@ -1680,7 +1680,7 @@ class spell_malygos_portal_beam : public SpellScriptLoader if (Creature* target = GetTarget()->ToCreature()) target->CastSpell(target, SPELL_PORTAL_OPENED); } - + void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) { if (Creature* target = GetTarget()->ToCreature()) @@ -2005,13 +2005,13 @@ class IsPlayerOnHoverDiskCheck if (!passenger->GetVehicleBase()) return true; } - + return false; } private: Unit* _source; - + bool _isOnHoverDisk; }; @@ -2065,7 +2065,7 @@ class spell_malygos_destroy_platform_channel : public SpellScriptLoader class spell_malygos_destroy_platform_channel_AuraScript : public AuraScript { PrepareAuraScript(spell_malygos_destroy_platform_channel_AuraScript); - + bool Load() { return GetCaster()->GetTypeId() == TYPEID_UNIT; @@ -2149,7 +2149,7 @@ class spell_alexstrasza_bunny_destroy_platform_event : public SpellScriptLoader class spell_alexstrasza_bunny_destroy_platform_event_SpellScript : public SpellScript { PrepareSpellScript(spell_alexstrasza_bunny_destroy_platform_event_SpellScript); - + bool Load() { return GetCaster()->GetTypeId() == TYPEID_UNIT; @@ -2157,12 +2157,12 @@ class spell_alexstrasza_bunny_destroy_platform_event : public SpellScriptLoader void HandleSendEvent(SpellEffIndex /*effIndex*/) { - Creature* caster = GetCaster()->ToCreature(); + Creature* caster = GetCaster()->ToCreature(); if (InstanceScript* instance = caster->GetInstanceScript()) if (GameObject* platform = caster->GetMap()->GetGameObject(instance->GetData64(DATA_PLATFORM))) platform->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_DESTROYED); } - + void HandleScript(SpellEffIndex /*effIndex*/) { Creature* caster = GetCaster()->ToCreature(); @@ -2316,7 +2316,7 @@ class spell_malygos_surge_of_power_warning_selector_25 : public SpellScriptLoade OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_malygos_surge_of_power_warning_selector_25_SpellScript::SendThreeTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENEMY); AfterHit += SpellHitFn(spell_malygos_surge_of_power_warning_selector_25_SpellScript::ExecuteMainSpell); } - + std::list _filteredSelectedTargets; }; @@ -2385,7 +2385,7 @@ class spell_alexstrasza_gift_beam : public SpellScriptLoader class spell_alexstrasza_gift_beam_AuraScript : public AuraScript { PrepareAuraScript(spell_alexstrasza_gift_beam_AuraScript); - + bool Load() { return GetCaster()->GetTypeId() == TYPEID_UNIT; diff --git a/src/server/scripts/Northrend/Nexus/EyeOfEternity/instance_eye_of_eternity.cpp b/src/server/scripts/Northrend/Nexus/EyeOfEternity/instance_eye_of_eternity.cpp index 601e58fc323..52ce259117f 100644 --- a/src/server/scripts/Northrend/Nexus/EyeOfEternity/instance_eye_of_eternity.cpp +++ b/src/server/scripts/Northrend/Nexus/EyeOfEternity/instance_eye_of_eternity.cpp @@ -56,7 +56,7 @@ public: if (type == DATA_MALYGOS_EVENT) { if (state == FAIL) - { + { for (std::list::const_iterator itr_trigger = portalTriggers.begin(); itr_trigger != portalTriggers.end(); ++itr_trigger) { if (Creature* trigger = instance->GetCreature(*itr_trigger)) @@ -155,7 +155,7 @@ public: void ProcessEvent(WorldObject* /*obj*/, uint32 eventId) { if (eventId == EVENT_FOCUSING_IRIS) - { + { if (Creature* alexstraszaBunny = instance->GetCreature(alexstraszaBunnyGUID)) { alexstraszaBunny->CastSpell(alexstraszaBunny, SPELL_IRIS_OPENED); From f3e788693423a29c027c1f083f9597968660eda7 Mon Sep 17 00:00:00 2001 From: Shauren Date: Thu, 28 Feb 2013 20:25:20 +0100 Subject: [PATCH 11/13] Core/Spells: Defined two spell attributes --- src/server/game/Entities/Unit/Unit.cpp | 2 +- src/server/game/Miscellaneous/SharedDefines.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 508f4b602de..9989988aa7e 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -11780,7 +11780,7 @@ bool Unit::_IsValidAssistTarget(Unit const* target, SpellInfo const* bySpell) co && target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE)) return false; - if (!bySpell || !(bySpell->AttributesEx6 & SPELL_ATTR6_UNK3)) + if (!bySpell || !(bySpell->AttributesEx6 & SPELL_ATTR6_ASSIST_IGNORE_IMMUNE_FLAG)) { if (HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE)) { diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h index 6f60aec4beb..dd64b2d88dc 100644 --- a/src/server/game/Miscellaneous/SharedDefines.h +++ b/src/server/game/Miscellaneous/SharedDefines.h @@ -486,7 +486,7 @@ enum SpellAttr6 SPELL_ATTR6_DONT_DISPLAY_COOLDOWN = 0x00000001, // 0 client doesn't display cooldown in tooltip for these spells SPELL_ATTR6_ONLY_IN_ARENA = 0x00000002, // 1 only usable in arena SPELL_ATTR6_IGNORE_CASTER_AURAS = 0x00000004, // 2 - SPELL_ATTR6_UNK3 = 0x00000008, // 3 + SPELL_ATTR6_ASSIST_IGNORE_IMMUNE_FLAG = 0x00000008, // 3 skips checking UNIT_FLAG_IMMUNE_TO_PC and UNIT_FLAG_IMMUNE_TO_NPC flags on assist SPELL_ATTR6_UNK4 = 0x00000010, // 4 SPELL_ATTR6_UNK5 = 0x00000020, // 5 SPELL_ATTR6_PRINT_SPELLNAME = 0x00000040, // 6 when activated, spell name is shown at the center of the screen: (client-side attribute) @@ -547,7 +547,7 @@ enum SpellAttr7 SPELL_ATTR7_UNK25 = 0x02000000, // 25 SPELL_ATTR7_UNK26 = 0x04000000, // 26 SPELL_ATTR7_UNK27 = 0x08000000, // 27 Not set - SPELL_ATTR7_BENEFIT_FROM_SPELLMOD = 0x10000000, // 28 Non-permanent, non-passive buffs that may benefit from spellmods + SPELL_ATTR7_CONSOLIDATED_RAID_BUFF = 0x10000000, // 28 May be collapsed in raid buff frame (clientside attribute) SPELL_ATTR7_UNK29 = 0x20000000, // 29 only 69028, 71237 SPELL_ATTR7_UNK30 = 0x40000000, // 30 Burning Determination, Divine Sacrifice, Earth Shield, Prayer of Mending SPELL_ATTR7_CLIENT_INDICATOR = 0x80000000 From 4a6f5d2b54831f2f02aae8fe55a8caa761cedaaf Mon Sep 17 00:00:00 2001 From: Shauren Date: Thu, 28 Feb 2013 20:46:50 +0100 Subject: [PATCH 12/13] Core/Spells: Defined & implemented SPELL_ATTR6_IGNORE_CATEGORY_COOLDOWN_MODS --- src/server/game/Entities/Player/Player.cpp | 2 +- src/server/game/Entities/Unit/Unit.cpp | 2 +- src/server/game/Miscellaneous/SharedDefines.h | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 8647d9d6f5e..cae664ffa1a 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -21474,7 +21474,7 @@ void Player::AddSpellAndCategoryCooldowns(SpellInfo const* spellInfo, uint32 ite if (rec > 0) ApplySpellMod(spellInfo->Id, SPELLMOD_COOLDOWN, rec, spell); - if (catrec > 0) + if (catrec > 0 && !(spellInfo->AttributesEx6 & SPELL_ATTR6_IGNORE_CATEGORY_COOLDOWN_MODS)) ApplySpellMod(spellInfo->Id, SPELLMOD_COOLDOWN, catrec, spell); // replace negative cooldowns by 0 diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 9989988aa7e..e899e5d5930 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -11827,7 +11827,7 @@ bool Unit::_IsValidAssistTarget(Unit const* target, SpellInfo const* bySpell) co // PvC case - player can assist creature only if has specific type flags // !target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE) && else if (HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE) - && (!bySpell || !(bySpell->AttributesEx6 & SPELL_ATTR6_UNK3)) + && (!bySpell || !(bySpell->AttributesEx6 & SPELL_ATTR6_ASSIST_IGNORE_IMMUNE_FLAG)) && !((target->GetByteValue(UNIT_FIELD_BYTES_2, 1) & UNIT_BYTE2_FLAG_PVP))) { if (Creature const* creatureTarget = target->ToCreature()) diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h index dd64b2d88dc..ace844f7cdf 100644 --- a/src/server/game/Miscellaneous/SharedDefines.h +++ b/src/server/game/Miscellaneous/SharedDefines.h @@ -489,7 +489,7 @@ enum SpellAttr6 SPELL_ATTR6_ASSIST_IGNORE_IMMUNE_FLAG = 0x00000008, // 3 skips checking UNIT_FLAG_IMMUNE_TO_PC and UNIT_FLAG_IMMUNE_TO_NPC flags on assist SPELL_ATTR6_UNK4 = 0x00000010, // 4 SPELL_ATTR6_UNK5 = 0x00000020, // 5 - SPELL_ATTR6_PRINT_SPELLNAME = 0x00000040, // 6 when activated, spell name is shown at the center of the screen: (client-side attribute) + SPELL_ATTR6_USE_SPELL_CAST_EVENT = 0x00000040, // 6 Auras with this attribute trigger SPELL_CAST combat log event instead of SPELL_AURA_START (clientside attribute) SPELL_ATTR6_UNK7 = 0x00000080, // 7 SPELL_ATTR6_CANT_TARGET_CROWD_CONTROLLED = 0x00000100, // 8 SPELL_ATTR6_UNK9 = 0x00000200, // 9 @@ -514,7 +514,7 @@ enum SpellAttr6 SPELL_ATTR6_UNK28 = 0x10000000, // 28 Death Grip SPELL_ATTR6_NO_DONE_PCT_DAMAGE_MODS = 0x20000000, // 29 ignores done percent damage mods? SPELL_ATTR6_UNK30 = 0x40000000, // 30 - SPELL_ATTR6_UNK31 = 0x80000000 // 31 some special cooldown calc? only 2894 + SPELL_ATTR6_IGNORE_CATEGORY_COOLDOWN_MODS = 0x80000000 // 31 Spells with this attribute skip applying modifiers to category cooldowns }; enum SpellAttr7 From d069e1b6b4d9f839df1a823d0ec1ddfa6dea303c Mon Sep 17 00:00:00 2001 From: Shauren Date: Thu, 28 Feb 2013 21:20:40 +0100 Subject: [PATCH 13/13] Core/Spells: Defined spell attributes related to aura visibility --- src/server/game/Miscellaneous/SharedDefines.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h index ace844f7cdf..c6e58e9cb3a 100644 --- a/src/server/game/Miscellaneous/SharedDefines.h +++ b/src/server/game/Miscellaneous/SharedDefines.h @@ -474,8 +474,8 @@ enum SpellAttr5 SPELL_ATTR5_UNK24 = 0x01000000, // 24 SPELL_ATTR5_UNK25 = 0x02000000, // 25 SPELL_ATTR5_UNK26 = 0x04000000, // 26 aoe related - Boulder, Cannon, Corpse Explosion, Fire Nova, Flames, Frost Bomb, Living Bomb, Seed of Corruption, Starfall, Thunder Clap, Volley - SPELL_ATTR5_UNK27 = 0x08000000, // 27 - SPELL_ATTR5_UNK28 = 0x10000000, // 28 + SPELL_ATTR5_DONT_SHOW_AURA_IF_SELF_CAST = 0x08000000, // 27 Auras with this attribute are not visible on units that are the caster + SPELL_ATTR5_DONT_SHOW_AURA_IF_NOT_SELF_CAST = 0x10000000, // 28 Auras with this attribute are not visible on units that are not the caster SPELL_ATTR5_UNK29 = 0x20000000, // 29 SPELL_ATTR5_UNK30 = 0x40000000, // 30 SPELL_ATTR5_UNK31 = 0x80000000 // 31 Forces all nearby enemies to focus attacks caster @@ -503,7 +503,7 @@ enum SpellAttr6 SPELL_ATTR6_UNK17 = 0x00020000, // 17 Mount spell SPELL_ATTR6_CAST_BY_CHARMER = 0x00040000, // 18 client won't allow to cast these spells when unit is not possessed && charmer of caster will be original caster SPELL_ATTR6_UNK19 = 0x00080000, // 19 only 47488, 50782 - SPELL_ATTR6_UNK20 = 0x00100000, // 20 only 58371, 62218 + SPELL_ATTR6_ONLY_VISIBLE_TO_CASTER = 0x00100000, // 20 Auras with this attribute are only visible to their caster (or pet's owner) SPELL_ATTR6_CLIENT_UI_TARGET_EFFECTS = 0x00200000, // 21 it's only client-side attribute SPELL_ATTR6_UNK22 = 0x00400000, // 22 only 72054 SPELL_ATTR6_UNK23 = 0x00800000, // 23